如何将 RGB 直方图转换为色谱?
How can I convert an RGB histogram into a color spectrum?
如何转换图像的 RGB 直方图以创建显示组合颜色以及正确颜色波长范围的直方图?
示例代码:
pkg load image
f=imread('/tmp/marbles.jpg');
f=uint8(f); %need to convert back to uint8 to show picture
%Split into RGB Channels
f_red = f(:,:,1);
f_green = f(:,:,2);
f_blue = f(:,:,3);
%Get histValues for each channel
[y_f_red, x] = imhist(f_red);
[y_f_green, x] = imhist(f_green);
[y_f_blue, x] = imhist(f_blue);
subplot (2,1,1); imshow(f);
subplot (2,1,2); plot(x, y_f_red, 'r', x, y_f_green, 'g', x, y_f_blue, 'b');
示例图像以及代码生成的单独 RGB 直方图:
我试图让直方图看起来像下图,但颜色从红色变为蓝色:
另一个图像示例:
PS: 我正在使用与 MATLAB 非常相似的 Octave 4.0。
在标准颜色表示(如 RGB 或 HSV)和光谱波长之间进行转换存在巨大障碍:许多颜色不能由单一波长的光表示。品红色、粉红色、棕色或 any 灰度颜色代表不同波长的混合。因此,生成等效光谱波长是一项复杂得多的工作(您可能会发现一些有用的想法和链接 here and here)。
创建颜色本身的直方图可能是更好的方法(如 my other answers 之一所示),但如果您真的想以一种简单的方式将颜色与波长相关联,您可以尝试以下方法。 ..
第一步是将 RGB 值转换为 HSV 值,然后创建色调通道的直方图。我会改编部分 my answer from here to do that. The next step will be to map hues to wavelengths of light, using some rather gross approximations adapted from this answer:
rgbImage = imread('test_image.png'); % Load image
hsvImage = rgb2hsv(rgbImage); % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360
binEdges = 0:270; % Edges of histogram bins
N = histc(hPlane(:), binEdges); % Bin the pixel hues from above
wavelength = 620-(170/270).*(0:269); % Approximate wavelength
hBar = bar(wavelength, N(1:end-1), 'histc'); % Plot the histogram
set(hBar, 'CData', 270:-1:1, ... % Change the color of the bars using
'CDataMapping', 'direct', ... % indexed color mapping (360 colors)
'EdgeColor', 'none'); % and remove edge coloring
colormap(hsv(360)); % Change to an HSV color map with 360 points
axis([450 620 0 max(N)]); % Change the axes limits
set(gca, 'Color', 'k'); % Change the axes background color
set(gcf, 'Pos', [50 400 560 200]); % Change the figure size
xlabel('Wavelength (nm)'); % Add an x label
ylabel('Bin counts'); % Add a y label
注意: 为使上述内容在 Octave 中正常工作,可能需要将 set(hBar, ...
行更改为以下内容:
set(hBar, 'FaceColor', 'flat', 'EdgeColor', 'none');
set(get(hBar, 'Children'), 'CData', 270:-1:1, 'CDataMapping', 'direct');
这是直方图:
但是,这有一个问题。如果我们改为使用 my other answer 中的代码来绘制所有色调值的直方图,我们将得到:
请注意,当我们抛出部分色调范围以转换为波长时,有一大群洋红色、粉红色和微红色像素被排除在外(它们不对应于光谱中的单个波长).将这些纳入结果需要更复杂的从色调到波长的转换。
您不能将 RGB 转换为 wavelength 除非满足图像和光线的某些物理属性。无论如何你可以通过反转来伪造它:
- RGB values of visible spectrum
如果不知道怎么看:
但结果将与物理波长直方图不同...为此,您需要通过旋转棱镜光学器件或一组带通滤波器来获取多波段图像...
PS。 HSV 远非准确...
顺便说一句。最简单的方法是从光谱颜色创建调色板并将输入图像转换为它(索引颜色),然后创建按波长排序的直方图(和/或颜色索引)...
基于 gnovices 答案,但使用图像而不是条形图(在我的系统上需要 0.12 秒):
rgbImage = imread ("17S9PUK.jpg");
hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1);
binEdges = 1:360;
N = histc (hPlane(:), binEdges);
cm = permute (hsv (360), [3 1 2]);
img = repmat (cm, max(N), 1);
row_index = max(N) - N';
sp = sparse (row_index(row_index>0), (1:360)(row_index>0), true);
mask = flipud (cumsum (sp));
img(repmat (logical(1 - full(mask)), [1 1 3])) = 0;
image (img)
set (gca, "ydir", "normal");
xlabel('hue');
ylabel('Bin counts');
如何转换图像的 RGB 直方图以创建显示组合颜色以及正确颜色波长范围的直方图?
示例代码:
pkg load image
f=imread('/tmp/marbles.jpg');
f=uint8(f); %need to convert back to uint8 to show picture
%Split into RGB Channels
f_red = f(:,:,1);
f_green = f(:,:,2);
f_blue = f(:,:,3);
%Get histValues for each channel
[y_f_red, x] = imhist(f_red);
[y_f_green, x] = imhist(f_green);
[y_f_blue, x] = imhist(f_blue);
subplot (2,1,1); imshow(f);
subplot (2,1,2); plot(x, y_f_red, 'r', x, y_f_green, 'g', x, y_f_blue, 'b');
示例图像以及代码生成的单独 RGB 直方图:
我试图让直方图看起来像下图,但颜色从红色变为蓝色:
另一个图像示例:
PS: 我正在使用与 MATLAB 非常相似的 Octave 4.0。
在标准颜色表示(如 RGB 或 HSV)和光谱波长之间进行转换存在巨大障碍:许多颜色不能由单一波长的光表示。品红色、粉红色、棕色或 any 灰度颜色代表不同波长的混合。因此,生成等效光谱波长是一项复杂得多的工作(您可能会发现一些有用的想法和链接 here and here)。
创建颜色本身的直方图可能是更好的方法(如 my other answers 之一所示),但如果您真的想以一种简单的方式将颜色与波长相关联,您可以尝试以下方法。 ..
第一步是将 RGB 值转换为 HSV 值,然后创建色调通道的直方图。我会改编部分 my answer from here to do that. The next step will be to map hues to wavelengths of light, using some rather gross approximations adapted from this answer:
rgbImage = imread('test_image.png'); % Load image
hsvImage = rgb2hsv(rgbImage); % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360
binEdges = 0:270; % Edges of histogram bins
N = histc(hPlane(:), binEdges); % Bin the pixel hues from above
wavelength = 620-(170/270).*(0:269); % Approximate wavelength
hBar = bar(wavelength, N(1:end-1), 'histc'); % Plot the histogram
set(hBar, 'CData', 270:-1:1, ... % Change the color of the bars using
'CDataMapping', 'direct', ... % indexed color mapping (360 colors)
'EdgeColor', 'none'); % and remove edge coloring
colormap(hsv(360)); % Change to an HSV color map with 360 points
axis([450 620 0 max(N)]); % Change the axes limits
set(gca, 'Color', 'k'); % Change the axes background color
set(gcf, 'Pos', [50 400 560 200]); % Change the figure size
xlabel('Wavelength (nm)'); % Add an x label
ylabel('Bin counts'); % Add a y label
注意: 为使上述内容在 Octave 中正常工作,可能需要将 set(hBar, ...
行更改为以下内容:
set(hBar, 'FaceColor', 'flat', 'EdgeColor', 'none');
set(get(hBar, 'Children'), 'CData', 270:-1:1, 'CDataMapping', 'direct');
这是直方图:
但是,这有一个问题。如果我们改为使用 my other answer 中的代码来绘制所有色调值的直方图,我们将得到:
请注意,当我们抛出部分色调范围以转换为波长时,有一大群洋红色、粉红色和微红色像素被排除在外(它们不对应于光谱中的单个波长).将这些纳入结果需要更复杂的从色调到波长的转换。
您不能将 RGB 转换为 wavelength 除非满足图像和光线的某些物理属性。无论如何你可以通过反转来伪造它:
- RGB values of visible spectrum
如果不知道怎么看:
但结果将与物理波长直方图不同...为此,您需要通过旋转棱镜光学器件或一组带通滤波器来获取多波段图像...
PS。 HSV 远非准确...
顺便说一句。最简单的方法是从光谱颜色创建调色板并将输入图像转换为它(索引颜色),然后创建按波长排序的直方图(和/或颜色索引)...
基于 gnovices 答案,但使用图像而不是条形图(在我的系统上需要 0.12 秒):
rgbImage = imread ("17S9PUK.jpg");
hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1);
binEdges = 1:360;
N = histc (hPlane(:), binEdges);
cm = permute (hsv (360), [3 1 2]);
img = repmat (cm, max(N), 1);
row_index = max(N) - N';
sp = sparse (row_index(row_index>0), (1:360)(row_index>0), true);
mask = flipud (cumsum (sp));
img(repmat (logical(1 - full(mask)), [1 1 3])) = 0;
image (img)
set (gca, "ydir", "normal");
xlabel('hue');
ylabel('Bin counts');