How can I convert an RGB histogram into a color spectrum?

只谈情不闲聊 提交于 2019-12-05 22:13:08
gnovice

There's a huge hurdle to converting between standard color representations (like RGB or HSV) and spectral wavelength: many colors can't be represented by a single wavelength of light. Colors such as magenta, pink, brown, or any grayscale color represent mixtures of different wavelengths. Generating an equivalent spectral wavelength is therefore a much more complicated endeavor (you may find some useful ideas and links here and here).

Creating histograms of the colors themselves may be a better way to go (illustrated in one of my other answers), but if you really want to relate color to wavelength in a simple fashion you can try the following...

A first step will be to convert RGB values to HSV values, then create a histogram of the hue channel. I'll adapt part of 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

NOTE: For the above to work properly in Octave, it may be necessary to change the set(hBar, ... line to the following:

set(hBar, 'FaceColor', 'flat', 'EdgeColor', 'none');
set(get(hBar, 'Children'), 'CData', 270:-1:1, 'CDataMapping', 'direct');

And here's the histogram:

There is, however, one issue with this. If we instead use the code exactly as it is in my other answer to plot the histogram of all the hue values, we would get this:

Note that there is a big cluster of magenta, pink, and reddish pixels that gets excluded when we toss out part of the hue range to convert to wavelengths (they don't correspond to a single wavelength in the light spectrum). Incorporating these into the results would require a more complicated conversion from hue to wavelength.

Spektre

you can not convert RGB to wavelength unless some physical properties of the image and light is met. Anyway you can fake this by inversing:

if you do not know how look at:

But the result will not be the same as physical wavelengths histogram ... For that you would need multi-band image acquisition either by rotating prism optics or by set of bandpass filters ...

PS. HSV is far from accurate ...

Btw. the easiest way to do this is create palette from the spectral colors and convert your input image to it (indexed colors) and then just create histogram sorted by wavelength (and or color index)...

Based on gnovices answer but with an image instead of bar (take 0.12s on my system):

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!