使用浮点值编写图像

8

我的代码读取一个RGB图像,处理后产生浮点数结果。如何在Matlab 7.6.0 (R2008a)中编写这些值作为图像,保持这些浮点数值?

6个回答

4

实际上,可以将64位像素数据(即表示双精度浮点值所需的位数)装入特定的图像格式中,具体来说是PNG。而且你甚至可以完全恢复数据。关键是将所有内容编码为uint16值,并使用真彩RGB图像(3个16位数据的颜色平面)以及一个alpha透明度映射(另外16位)。以下是编码步骤:

data = rand(4);              % Just some sample data, a small 4-by-4 matrix
hexData = num2hex(data(:));  % Get the 16 digit hex codes for each pixel
C = mat2cell(hexData, numel(data), [4 4 4 4]);  % Split the hex codes into 4 groups of 4
C = cellfun(@(c) {uint16(hex2dec(c))}, C);  % Convert each hex value into a 16 bit integer
colorData = reshape([C{1:3}], [size(data) 3]);  % 4-by-4-by-3 uint16 color data
alphaData = reshape(C{4}, size(data));          % 4-by-4 uint16 alpha data
imwrite(colorData, 'double_data.png', 'Alpha', alphaData);  % Save image

您现在拥有一个有效的图像文件,但如果您查看它,它可能看起来像随机的垃圾。现在,您可以这样解码它:
[imColor, ~, imAlpha] = imread('double_data.png');  % Load image
imSize = size(imColor);  % Get image size
imHex = [dec2hex(imColor(:, :, 1)) ...  % Convert each uint16 to hex and concatenate
         dec2hex(imColor(:, :, 2)) ...
         dec2hex(imColor(:, :, 3)) ...
         dec2hex(imAlpha)];
imdata = reshape(hex2num(imHex), imSize(1:2));  % Reproduce data

并进行相等性检查:

>> isequal(imdata, data)

ans =

  logical

   1           % it's the same!

5
图或者没发生过。 - Andras Deak -- Слава Україні
3
你的意思是你看不到我发帖中的16像素图像吗?它就在那个句号旁边...或许就是那个句号? - gnovice

1

以下函数将单精度灰度或RGB图像写入tif文件。而且你会发现这些天,如果像素值在(0,1)的范围内,Windows资源管理器可以很好地处理单精度图像。当你读取它时,可以像往常一样使用imread

function writeftif(outim,outfilename)
t = Tiff(outfilename,'w');
if size(outim,3)==3
    t.setTag('Photometric',Tiff.Photometric.RGB);
elseif size(outim,3)==1
    t.setTag('Photometric',Tiff.Photometric.MinIsBlack);
end
t.setTag('Compression',Tiff.Compression.None);
t.setTag('BitsPerSample',32);
t.setTag('SamplesPerPixel',size(outim,3));
t.setTag('SampleFormat',Tiff.SampleFormat.IEEEFP);
t.setTag('ImageLength',size(outim,1));
t.setTag('ImageWidth',size(outim,2));
t.setTag('PlanarConfiguration',Tiff.PlanarConfiguration.Chunky);
% Write the data to the Tiff object.
t.write(single(outim));
t.close();

1

可以使用TIFF图像格式编写具有浮点值的图像。以下是一个示例:

A=single(7.6*rand(10,10))

t = Tiff('test.tif', 'w'); 
tagstruct.ImageLength = size(A, 1); 
tagstruct.ImageWidth = size(A, 2); 
tagstruct.Compression = Tiff.Compression.None; 
tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP; 
tagstruct.Photometric = Tiff.Photometric.MinIsBlack; 
tagstruct.BitsPerSample = 32; 
tagstruct.SamplesPerPixel = 1; 
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky; 
t.setTag(tagstruct); 
t.write(A); 
t.close();

B=imread('test.tif')

Photoshop无法打开此文件。 - Royi
通常,需要软件支持这种类型的图像。 - Mohammad nagdawi

1
数字图像中用于表示每个元素的位数称为图像的位深度。位深度告诉我们图像元素可以采取的离散级别数量。无论这些元素是作为整数类型还是浮点类型存储,都不重要:位深度确定了可能存在的离散级别数量。
如何解释位深度取决于图像是灰度还是彩色。例如,8位灰度图像的强度范围为[0,255],而24位彩色图像也在[0,255]内具有强度。之所以使用这种命名方式,是因为使用8位红、绿和蓝三色分量存储一个彩色像素需要24位。为避免混淆,通常按每个颜色通道的位数来称呼彩色图像。例如,PNG格式支持每个通道高达16位,或者对于带有alpha层的真彩色(RGB)总共为48位。 imwrite的文档列出了MATLAB中可用的格式和位深度。
从MATLAB以最高精度保存彩色图像(MxNx3矩阵):
%// Assume an image called 'im' of type double.
%// First normalize to fall into [0,1].
im = im - min(im(:)); %// Save these numbers somewhere
im = im / max(im(:)); %// if you need to recover the original values later!
%// Best PNG quality.
imwrite(im,'image.png','bitdepth',16);

如果您需要更高的精度,您必须将图像保存为通用数据格式而不是专用图像格式。


0
如果您的RGB值超出了范围(0,1),只需将RGB值转换为0到1之间的值。如果您想恢复原始浮点值,则可以将转换值保存为图像文件名的一部分。

问题在于我想将这些值保存为图像,并保留这些浮点值,因为当我使用imwrite函数时,这些值将被转换为无符号整数。 - Student

0

当您保存图像时,查看器需要知道值的完整可能范围。通常的约定是,如果值为浮点数,则范围为[0..1],如果值为uint8,则范围为[0..255]等。

当您保存具有浮点值(如2.34)的图像时,您应该问自己,查看器将如何知道如何解释它?

我的答案是:您无法。您应该将您的值转换为有效范围,然后再保存它。例如,如果您的浮点范围为[0..10],则可以将所有值乘以1000并保存为uint16。这样,您就可以(几乎)保留浮点值的精度。


6
TIFF很好地支持浮点图像。我不在乎查看器如何处理它;这是数据,没有什么好的理由阻止我拥有一个像素值为2.34的像素。如果像素类型是float,则范围是MIN_FLOAT到MAX_FLOAT。噢,对了,你可以使用“Tiff”类实现这一点。 - Ed S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接