【问题标题】:How can I convert an RGB histogram into a color spectrum?如何将 RGB 直方图转换为色谱?
【发布时间】:2017-09-16 02:57:57
【问题描述】:

如何转换图像的 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:我使用的是 Octave 4.0,它与 MATLAB 非常相似。

【问题讨论】:

  • 您是否要获取颜色值的直方图,例如this answer 中的第二张图像?如果是这样,您希望首先按照那里的描述将 RGB 图像转换为 HSV。
  • 此外,将 RGB 值转换为波长/频率是有问题的:请参阅帖子 herehere
  • 类似,但如果你注意到红色仍然出现在两边

标签: matlab image-processing histogram octave matlab-figure


【解决方案1】:

在标准颜色表示(如 RGB 或 HSV)和光谱波长之间进行转换存在巨大障碍:许多颜色不能用单一波长的光表示。品红色、粉红色、棕色或任何灰度颜色等颜色表示不同波长的混合。因此,生成等效光谱波长是一项复杂得多的工作(您可能会发现一些有用的想法和链接 herehere)。

创建颜色本身的直方图可能是一种更好的方法(如my other answers 之一所示),但如果您真的想以一种简单的方式将颜色与波长相关联,您可以尝试以下方法...

第一步是将 RGB 值转换为 HSV 值,然后创建色调通道的直方图。我将调整my answer from here 的一部分来做到这一点。下一步将使用来自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 中的代码来绘制所有色调值的直方图,我们会得到:

请注意,当我们丢弃部分色调范围以转换为波长(它们不对应于光谱中的单个波长)时,会有一大群洋红色、粉红色和微红色像素被排除在外。将这些纳入结果将需要更复杂的从色调到波长的转换。

【讨论】:

    【解决方案2】:

    您不能将 RGB 转换为 波长,除非满足图像和光线的某些物理特性。无论如何,您可以通过反转来伪造它:

    如果不知道怎么看:

    但结果与物理波长直方图不同...为此,您需要通过旋转棱镜光学器件或一组带通滤光片获取多波段图像...

    附言。 HSV 远非准确...

    顺便说一句。 最简单的方法是从光谱颜色创建调色板并将输入图像转换为它(索引颜色),然后创建按波长(和/或颜色索引)排序的直方图...

    【讨论】:

    • 谢谢,如果我发现它有用,我会对此进行一些研究并发布代码。
    • @RickT 问题在于并非所有颜色都在光谱中,因此您需要处理它。简单地选择最接近的颜色在物理上是不正确的。最好将抖动与光谱颜色调色板一起使用。由于 RGB 以与单个光谱波长相同的方式累积......您还需要处理颜色的强度,因此深黄色与亮黄色相同。所以我会创建有序的光谱调色板,每个波长的阴影等级很少,然后使用dithering 做直方图和组波长。
    • 这也是我正在研究的东西stackoverflow.com/questions/2374959/…
    • 大多数光谱颜色代码都是错误的(与真实光谱数据不匹配)并且因为我需要它尽可能接近真实的东西,所以我创建了自己的...检查第一个链接我的答案?此外,仅基于矩阵乘法的转换 RGB/XYZ 是廉价的假货(如 CIE)。要获得更精确的值,您需要通过 X、Y、Z 灵敏度曲线进行积分,例如 How do I draw a rainbow in Freeglut? 如果您真的需要它...
    【解决方案3】:

    基于 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');
    

    【讨论】:

      猜你喜欢
      • 2016-12-17
      • 2010-09-26
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 2017-03-21
      • 2011-03-02
      • 2021-12-14
      • 1970-01-01
      相关资源
      最近更新 更多