2
$\begingroup$

I'm working on an open source hardware project for a video/photo light, and it involves a fair bit of color math. I am trying to find my way from Color Temperature (CT) in Kelvin to current values used to drive the RGB LED's. I've struggled with this for quite a while now :-)

This is what I'm currently doing:

I take any CT value between 1800 and 15000 Kelvin and find the color coordinates. The CT is a value along the planchian locus of the CIE 1931 color space. I found a spline function here: http://en.wikipedia.org/wiki/Planckian_locus (the Approximation section). For a CT of 4000 I get x=0.380528339, y=0.376733566 and that looks correct to me.

Next I convert the xy coordinates to XYZ. I have semi-randomly set Y (brightness) to 0.6 to not saturate the LED current drivers.

Y = 0.6 X = x * (Y/y) Z = (1-x-y) * (Y/y) 

Next, I do a matrix transformation. I take the CIE standard observer at the same wavelengths as the LED emitters:

Xbar    0.907244    0.1096  0.0579 Ybar    0.417036    0.7932  0.1693 Zbar    0.000220    0.0572  0.6162 

I take a spectrometer reading of the individual LED emitters. The spectrometer gives me the CIE XYZ values for the Red, Green and Blue LEDs:

X    2.14   0.88    1.14 Y    0.95   2.7 0.59 Z    -0.04  0.33    6.73 

I found the MINVERSE() function in Excel to invert the LED XYZ readings. Then use MMULT() to multiply the CIE standard observer with the inverted LED XYZ, and I get:

0.8093637   -0.0775645  -0.1122626 0.0302540   0.7946191   -0.0104841 -0.0136168  0.0499041   0.1587569 

So now I take the above array and multiply it by the XYZ values previously calculated from the Color Temperature:

R = (0.8093637 * X) + (-0.0775645 * Y) + (-0.1122626 * Z); G = (0.0302540 * X) + (0.7946191 * Y) + (-0.0104841 * Z); B = (-0.0136168 * X) + (0.0499041 * Y) + (0.1587569 * Z); 

All this is supposed to transform the CT in CIE 1931 color space to the color response of the LED emitters.

But when I drive the LEDs with these RGB values, I get a compressed scale. 2000 K input measures as 4000 K. 15000 K input measures as 8000 K. I'm not really a math person and I can't for the life of me figure out where I go wrong!

EDIT: to clarify

  • 0
    @Emre The Spectrometer software gives me the XYZ values as well.2011-07-08

2 Answers 2

2

OK... first of all, could you clarify a few things:

  1. Where is that "CIE standard observer" matrix from, and what is it for? I assume it's for transforming from something to the XYZ color space, but what?
  2. Exactly which matrices did you invert and multiply, and in what order, to get the third matrix you gave? I can't get it from any of the obvious permutations of the other two matrices.
  3. What do you need the first and third matrices for, anyway? If the second matrix you have, in effect, gives a transformation from LED intensities to the XYZ color space, shouldn't it be enough to just multiply the XYZ color vector with its inverse?

Anyway, doing just that with the values you gave, I get the XYZ to LED intensity transformation matrix $ M = \begin{bmatrix} \phantom{+}2.14 & 0.88 & 1.14 \\ \phantom{+}0.95 & 2.7\phantom{0} & 0.59 \\ -0.04 & 0.33 & 6.73 \end{bmatrix}^{-1} = \begin{bmatrix} \phantom{+}0.5398 & -0.1665 & -0.0768 \\ -0.1927 & \phantom{+}0.4338 & -0.0054 \\ \phantom{+}0.0127 & -0.0223 & \phantom{+}0.1484 \end{bmatrix}, $ the XYZ color vector $ V_{XYZ} = \begin{bmatrix} 0.6060 \\ 0.6\phantom{000} \\ 0.3866 \end{bmatrix} $ and the LED intensity vector $ V_{RGB} = M \cdot V_{XYZ} = \begin{bmatrix} 0.1975 \\ 0.1414 \\ 0.0517 \end{bmatrix}. $ Does that give the output you expect?

Also, just to be sure, are the LED inputs really linear functions of the brightness? If not, you may have to apply an extra correction step for that.

  • 0
    OK, in that case I don't think you need the CIE matrix for anything: just invert the LED-to-XYZ matrix you got from the spectrometer readings and multiply your XYZ colors with that.2011-07-09
1

This is just a first attempt to figure out what's wrong; it might take some interaction via the comments to get to the bottom of this.

When you say "I take a spectrometer reading of the Red, Green and Blue LED emitters" and then you write a matrix with rows labeled X, Y, Z, do you mean that you send some unit of current through each of the three LEDs and measure the emitted light, and the three columns specify X, Y, Z values that you measure for the red, green and blue LED, respectively? If so, are these CIE XYZ values that you measure?

If that's what you mean, then I don't see how the CIE standard observer gets into it. Since you want to generate light with a particular set of CIE XYZ coordinates, corresponding to a particular colour temperature (and your arbitrary brightness), and you know the CIE XYZ values generated by a unit of current through each of the LEDs, shouldn't you just invert that one matrix and apply it to the desired XYZ values to obtain the required currents?

Another question (which may be irrelevant if you don't actually need the CIE standard observer): You write "I take the CIE standard observer:" and then specify a matrix with rows labeled X, Y, Z. The CIE standard observer is specified by tristimulus values along the entire spectrum; the columns of the matrix seem to correspond roughly to the tristimulus values at wavelengths 485nm, 525nm, 617nm -- why these?

  • 0
    I can live with it ;-)2011-07-11