您的原始图像已经在使用jet 颜色图。问题是,当您将其转换为灰度时,您会丢失一些关键信息。见下图。
在原始图像中,您有一个热图。蓝色区域通常表示“低值”,而红色区域表示“高值”。但是当转换为灰度时,这两个区域都表示低值,因为它们接近暗像素(见箭头)。
一个可能的解决方案是这样的:
您获取图像的每个像素,找到最近的(最近的)
jet 颜色图中的颜色值,并将其索引用作灰度值。
我将首先向您展示最终代码和结果。解释如下:
I = im2double(imread('myimage.png'));
map = jet(256);
Irgb = reshape(I, size(I, 1) * size(I, 2), 3);
Igray = zeros(size(I, 1), size(I, 2), 'uint8');
for ii = 1:size(Irgb, 1)
[~, idx] = min(sum((bsxfun(@minus, Irgb(ii, :), map)) .^ 2, 2));
Igray(ii) = idx - 1;
end
clear Irgb;
subplot(2,1,1), imagesc(I), axis equal tight xy
subplot(2,1,2), imagesc(Igray), axis equal tight xy
结果:
>> whos I Igray
Name Size Bytes Class Attributes
I 110x339x3 894960 double
Igray 110x339 37290 uint8
说明:
首先,您将获得jet 颜色图,如下所示:
map = jet(256);
它将返回一个256x3 颜色图,其中包含喷射调色板上可能的颜色,其中每一行都是一个 RGB 像素。正如预期的那样,map(1,:) 是一种深蓝色,map(256,:) 是一种深红色。
然后,你这样做:
Irgb = reshape(I, size(I, 1) * size(I, 2), 3);
...将您的110x339x3 图像转换为37290x3 矩阵,其中每一行都是一个RGB 像素。
现在,对于每个像素,您可以计算该像素到map 像素的欧几里得距离。您取最近的索引并将其用作灰度值。减一 (-1) 是因为索引在 1..256 范围内,但灰度值在 0..255 范围内。
注意:欧几里得距离最后取平方根,但由于我们只是试图找到最接近的值,因此没有必要这样做。
编辑:
这是一个快 10 倍的代码版本:
I = im2double(imread('myimage.png'));
map = jet(256);
[C, ~, IC] = unique(reshape(I, size(I, 1) * size(I, 2), 3), 'rows');
equiv = zeros(size(C, 1), 1, 'uint8');
for ii = 1:numel(equiv)
[~, idx] = min(sum((bsxfun(@minus, C(ii, :), map)) .^ 2, 2));
equiv(ii) = idx - 1;
end
Irgb = reshape(equiv(IC), size(I, 1), size(I, 2));
Irgb = Irgb(end:-1:1,:);
clear equiv C IC;
它运行得更快,因为它利用了图像上的颜色仅限于jet 调色板中的颜色这一事实。然后,它计算unique 颜色并仅将它们与调色板值匹配。由于要匹配的像素更少,算法运行得更快。以下是时间:
-
之前:
经过的时间是 0.619049 秒。
-
之后:
经过的时间是 0.061778 秒。