Open heinemannj opened 3 years ago
Hi,
Zoltan here.
I made this example for a workshop some time ago, the explanation here should show how it works.
In a nutshell, once you have the coordinates for the three primary channels, you can use the formula in the explanation to make a simple and cheap chromameter. I did this with my sensor, and found out that I got about 10% accuracy, which is pretty impressive: the sensor itself is $5, and the Minolta chromameter, which can do 3% accuracy is something like $2000.
This is now thankfully getting out of date, because we have the WS2812 LEDs, which have pre-set primaries.
Hi Zoltan,
first of all thanks for your response. My vision is to use this sensor for a cheap colorimeter.
I wants to measure colors and color differences in CIE Lab. In general I'm able to transform sensors RGB data into XYZ D50 und finally into CIE Lab. But results compared to ColorChecker standard are very bad.
I've reviewed your project but I was not able to understand how to convert xy values into XYZ/Lab.
*out_x = ( r_luminance / sum_luminance ) * primary_r_x + ( g_luminance / sum_luminance ) * primary_g_x + ( b_luminance / sum_luminance ) * primary_b_x;
*out_y = ( r_luminance / sum_luminance ) * primary_r_y + ( g_luminance / sum_luminance ) * primary_g_y + ( b_luminance / sum_luminance ) * primary_b_y;
Note: I'm a dummy on colorimetry but I want's to improve :)
After thinking a little bit more in depth:
The sensor is providing: RGB raw data Your calculation provides patched values for: xy
Transform: RGB raw data -> XYZ D65: XYZ convert your xy values plus the Y from above back to X'YZ' D65 and then finally into CIE Lab and to sRGB
Right or is there a more easy and reliable way?
Well, with this sensor, it is a bit more complicated than that at first, and this is what made me write the code. Each colour channel is very far from monochromatic, and their sensitivities are also different. I made the curve digitiser in Matlab, and it generates the spectral response in the csv files. Then, these digitised curves are pushed though the integral with the human perception curves, which generate the human perception (to which you refer to as 'XYZ' if I am correct) equivalent stimulus intensities. And finally, the code uses these values to generate the chromaticity coordinates.
This script generates these primary coordinates for your sensor, which now takes not only the spectral responses, but also the relative sensitivity differences into account. From this point onward you won't need the find_chromaticity_of_primaries
script ever again.
And finally, now that you know the primary chromaticity coordinates, you can calculate the 'colour' 'seen' by the sensor, with the calculation you referred as above. Effectively, it's an averaging calculation, and the average point is being pulled in the gamut by the three ADC values.
So it is not as complicated as you wrote, because we do more than half the work beforehand. In the production code (your code, that reads the sensor and outputs the chromaticity coordinates), the RGB values from the sensor can then be converted directly to chromaticity coordinates, without any hassle. You will need floating-point numbers though, so it won't be particularly fast.
Oh, and when you see what colour gamut the sensor actually can measure, you will be disappointed. It is much smaller than sRGB.
I think find_chromaticity_of_primaries
will also run on Octave, so you won't have to get Matlab. An example set of digitised curves are also included in .csv files, so you can calculate the primaries yourself.
Sorry - I can not follow you completely - I will provide an calculation example. Please point me into the right direction.
ColorChecker 2014 References: http://xritephoto.com/documents/literature/en/ColorData-1p_EN.pdf
- Index 10 (Purple)
- sRGB(94 60 108)
- CIE Lab(30.325 22.976 -21.587)
CIE Calculator: http://www.brucelindbloom.com/
My TCS34725 raw RGB data:
Color difference of "8" between CIE Lab reference and my measurement - but my measurement was really quick and dirty ...
TCS34725 sensor Primary CIE 1931 xy-coordinates based on your research:
Red: x = 0.582692, y = 0.382919
Green: x = 0.283233, y = 0.525670
Blue: x = 0.144560, y = 0.134175
Your xy values calculation advice:
*out_x = ( r_luminance / sum_luminance ) * primary_r_x + ( g_luminance / sum_luminance ) * primary_g_x + ( b_luminance / sum_luminance ) * primary_b_x;
*out_y = ( r_luminance / sum_luminance ) * primary_r_y + ( g_luminance / sum_luminance ) * primary_g_y + ( b_luminance / sum_luminance ) * primary_b_y;
My TCS34725 sensor raw data as above:
R = 87.4286
G = 65.5714
B = 102
Sum = 255
My calculation of xy values:
x = (87.4286/255) * 0.582692 + (65.5714/255) * 0.283233 + (102/255) * 0.144560 = 0.330435
y = (87.4286/255) * 0.382919 + (65.5714/255) * 0.525670 + (102/255) * 0.134175 = 0.320129
My Y value from previous calculation sheet:
Y = 6.8033
My xyY values:
x = 0.330435
y = 0.320129
Y = 6.8033
Big color difference of "23" between CIE Lab reference and your patching advice of my raw RGB data ...
Do you have any explanations?
Can you tell me how did you obtain this measurement? Specifically, what light source (or monitor) you used, and what were the settings for the sensor?
My measurement was quick and dirty:
Turn sensor LED off
Integration Time 700ms
Gain 1x
Clear channel was at every time >65535: ~1000
ColorCheckerChart tiff picture displayed on an DELL LED Display
Sensor in an black box parallel to the display - ~1cm above the surface
No other light than the a small monitor array (1,5 x 1,5 cm) is reaching the sensor
After reading the 10. time of Bruce Justin Lindbloom documentation I found the following calculations:
But applying the origional sRGB transformation matrix is much more accurate then the one I've calculated with your primaries ...
Strange. A few things that come into my mind:
I'm very interested how I can practically use your chromaticity coordinates for the TCS 34725 color sensor.
"... Once these chromaticity coordinateas are obtained, the sensor's detected colour can be calculated from the ADC values themselves ..."
Can you please provide a practial example for this calculation.