Calculate R,G,B components from given a,b values of CIE L*a*b* color space

13 views (last 30 days)
I need to calculate a map, which I call RGB spectrum of some image. It is number of image pixels that appears for each of unique colors combinations.
It takes several hours to calculate such values for image of ~2k x 2k pixels, if I directly loop through unique RGB combinations, but if I convert RGB picture into L*a*b* format, such calculation takes a few minutes. Calculated result is a function of a* and b* vectors. I'm attaching result for peppers.png
How to calculate corresponding R, G, B components from these vectors? What value of L should I use? Is it important, do I need L or can exchange it by some constant?
Thanks a lot for help
  3 Comments
Valeriy
Valeriy on 1 Jul 2021
Edited: Image Analyst on 2 Jul 2021
DGM, thank you for your reply.
>You're trying to basically map the frequency of color points in an image.
In my understanding, frequency is number of something (pixels, waves' periods, colors), related to some unit of time, length, space, etc. For this case it seems to me that final result is more close to the spectrum. But this is question of definition.
>If you want what amounts to a 3D histogram/heatmap, you'll first need to figure out how you want to visualize a volumetric image.
You are right, but at first I need to obtain result. It could be RGB axes with volumetric data of amount of pixels, similar for Color Inspector 3D of ImageJ, BUT with colors, which related not to RGB color combination, but coded by amount of corresponding pixels into image.It could be set of 3D slices, stereoimage of final distribution, etc. Or any other kind of such data presentation.
Valeriy
Valeriy on 1 Jul 2021
In the above ab Spectrum of peppers, I have found surprising results, which I didn't understand immediately.
The main color of the image is the color of the background, violet. It corresponds to the strong peak ab = (118,148). I have to squeeze the presented range of intensities to show weaker peppers' peaks. On the left side of it, there is peak ab = (98,159); I suppose that it corresponds to green peppers. Surprising is the bridge between these peaks. Here is a digital photo, and this bridge proves the discovery of Eugene Delacroix, French painter of the XIX century, impressionist predecessor, who saw so-called in painting "color reflexes". This is an effect when the color of one object is mixed with the colors of other neighbors' objects. He saw it and we can see them in his masterpieces. This bridge is clear evidence of the physical, optical background of his observation.
A similar bridge we can see between the same, main violet background peak and wide peak (170,190). I suppose (my question is still not answered) that it corresponds to red, orange peppers. It is not solid, it broke somewhere in the center. Its reason is unclear for the moment, perhaps it is related to weak camera dynamical range.

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 1 Jul 2021
Edited: Image Analyst on 1 Jul 2021
In your comment above, you forgot to attach the bridge picture/painting.
Perhaps you want colorcloud() to build a 3-D color gamut of your image. Unfortunately it's just a visualization of the 3-D gamut/histogram and doesn't return the histogram.
Or you can easily compute the 3-D histogram of your image in a few seconds, even for a 2k by 2k image, with a simple nested for loop.
rgbImage = imread('peppers.png'); % Read in demo image.
rgbImage = imresize(rgbImage, [2048, 2048]); % Make 2k by 2k
hist3d = zeros(256, 256, 256); % Initialize counts
[rows, columns, numberOfColorChannels] = size(rgbImage)
startTime = tic;
% Create histogram.
for col = 1 : columns
for row = 1 : rows
r = rgbImage(row, col, 1) + 1; % Convert range from 0-255 to 1-256 because indexes can't be 0.
g = rgbImage(row, col, 2) + 1;
b = rgbImage(row, col, 3) + 1;
hist3D(r, g, b) = hist3d(r, g, b) + 1;
end
end
elapsedSeconds = toc(startTime);
fprintf('Done. Elapsed seconds = %.1f.\n', elapsedSeconds);
rows =
2048
columns =
2048
numberOfColorChannels =
3
Done. Elapsed seconds = 2.0.
Converting from RGB to CIELAB should take only a few seconds and you can then build a histogram of LAB values if you want. If it takes several hours, you're doing something wrong.
If you then sum the hist3d across the third dimension you will get the a vs b image you got in the image you attached. It's basically kind of like looking straight down the L axis.
My final suggestion is to build the color frequency IMAGE, which sounds perhaps like what you're describing. It is not a histogram but essentially makes a gray scale image where the brightness of the pixel is related to how much that pixel's color appears in the image. Here is a program that does that: https://www.mathworks.com/matlabcentral/fileexchange/28164-color-frequency-image?s_tid=srchtitle
In the image above, see how there are a lot of pixels with the sky color? So those pixels are bright. And the ocean also has a lot so it's almost as bright. The green and white have a lower area fraction of the image so those pixels are darker.
  20 Comments
Valeriy
Valeriy on 6 Aug 2021
Hello @Image Analyst, sorry for the delay in replying to you. Jobless activity is hard and timeconsuming job.
>See attached demo. What areas would you call "red"?
Thank you for the interesting demo.
>Color science is a confusing topic,
Yes, sure, I see, but let's see if I need it for such a task?
After some thinking, what I have, when I analyze camera recorded luminescence image. Original luminescence light from each pixels' location has some complicated spectrum S(λ), where λ is light's wavelength. The camera has three kinds of sensors with its own spectral sensitivity: R(λ), G(λ), B(λ). For each pixel we have (Ro, Go, Bo), the sum of products:
Ro = sum(S.*R); Go = sum(S.*G); Bo = sum(S.*B);
They are pure physical, optical values, only for user convenience, they are translated by a monitor to color presentation. They are not colors, they are only colorized optical quantities. It definitely means that the observed camera image is 4D, so any attempt to squeeze, reduce its dimensionality to the 3D structure is wrong. It means as well that I must to work with img = (Ro(:,:),Go(:,:),Bo(:,:)) matrice.
Next, what I need is to calculate 4D rgb histogram of img, H(r,g,b) and to find a way how to observe and separate its clusters.
I'm not sure that it will be convenient to apply stereo H presentation and introduce user-defined segment(s) into it. So I'm thinking about 3 projections of H on the RG, GB, BR planes, like I illustrate in the attached image.
By the way, how is possible to plot such an image, if I have corresponding RG, GB, BR projections? This image I did in graphics editor.
Another question, Image Segmentation Using the Color Thesholder App is very convenient tool, does exist something similar for RGB image format?
Thank you a lot for your help
Image Analyst
Image Analyst on 6 Aug 2021
Edited: Image Analyst on 6 Aug 2021
It is true that the emitted spectrum from your scene is continuous (a function of lambda, the wavelength). And it's true that the camera has filters over the pixels that have a continous spectral transmissivity. And you do integrate the product of spectral emittance of these scene times spectral tramnsmissitivy of the camera to get the single color value, like your Ro, Go, or Bo. And you do end up with a 3-channel image. But it's a 3-dimensional image. Even if you had not summed over wavelength and stayed with, say 32 different images (one image for each 10 nm band), you'd still ahve a 3-D image. It would be hyper spectral with 32 color channels instead of only 3 but both cases are 3-D. The hyper spectral image is not 4-D or 32-D. It's 3-D -- rows-by-columns-by-32 wavelength bands. The histogram is a 3-D histogram (not 4-D) for an RGB image, and for a 32 channel hyperspectral image, it would be a 32-D histogram.
If you have the known theoretical spectral emittance of the fluorescent material, and you know the spectral transmissitivities of the RGB filters on the camera, and you have the RGB values, you can get the "loadings" of the signal for each wavelength using multivariate curve resolution. This gives you the emittance of your signal at each wavelength.
The Color Thresholder can be used with any 3-D color space, like CIELAB, HSV, or RGB, so I don't understand that question.

Sign in to comment.

More Answers (1)

Dmitry Kaplan
Dmitry Kaplan on 1 Jul 2021
Edited: Dmitry Kaplan on 1 Jul 2021
... This is probably not an answer, but a suggestion -- I simply don't have enough info. If your rgb valus are limited to 1-byte values (i.e. each of the components color components is between 0 and 255), then I would consider creating a 256^3 x 1 sparse matrix and use accumarray to sum up histogram counts. Something like this:
rgb = double(imread('peppers.png'));
rgb_index = rgb(:,:,1)*256*256+rgb(:,:,2)*256+rgb(:,:,3); %create index of color histogram red*256*256+green*256*blue
res = accumarray(rgb_index(:)+1,1,[256^3,1],[],[],true); %don't forget to subtract 1 when converting indeces back to rbg if needed

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!