8

How does one take a color expressed in an RGB value (say, three coordinates from 0-255) and produce from it a color temperature in kelvin (or mireds)?

I see this question which looks pretty close. However, the question mentions x and y, an answer mentions R1 and S1, which I think are CIE XYZ color space coordinates. I'm not quite sure how to get to those either. Someone else links to a paper. Someone else says RGB values are meaningless without "stating a color space" (I thought my monitor decided to display something simply from RGB values?).

Can someone just lay out the whole thing without pointing to other places and assuming I know what all the color terminology is?

Community
  • 1
  • 1
dfrankow
  • 20,191
  • 41
  • 152
  • 214
  • Do you need to convert from RGB to Kelvin or from Kelvin to RGB? – cameronroytaylor Aug 10 '16 at 14:41
  • How well-versed are you in linear algebra and (infinitely-dimensional) vector spaces? AFAIK their concepts were actually invented/developed (as generalizations of the already previously known finite-dimensional vector concepts) for the treatment of color theory. So it might be easier to answer this question if an answer is allowed to use the concepts, names and notations from these fields of mathematics. – das-g Aug 10 '16 at 14:47
  • @cameronroytaylor RGB to kelvin. – dfrankow Aug 10 '16 at 16:34
  • @das-g I am reasonably well versed in linear algebra and vector spaces. – dfrankow Aug 10 '16 at 16:34
  • Not yet an answer, but [the math behind](http://www.brucelindbloom.com/index.html?Math.html) this [online color calculator](http://www.brucelindbloom.com/index.html?ColorCalculator.html) might prove useful. – das-g Aug 10 '16 at 22:12
  • see [Star B-V color index to apparent RGB color](https://stackoverflow.com/a/22630970/2521214) – Spektre Sep 22 '22 at 08:55

2 Answers2

14

You could use Colour to perform that computation using the colour.xy_to_CCT_Hernandez1999 definition:

  import numpy as np
  import colour

  # Assuming sRGB encoded colour values.
  RGB = np.array([255.0, 235.0, 12.0])

  # Conversion to tristimulus values.
  XYZ = colour.sRGB_to_XYZ(RGB / 255)

  # Conversion to chromaticity coordinates.
  xy = colour.XYZ_to_xy(XYZ)

  # Conversion to correlated colour temperature in K.
  CCT = colour.xy_to_CCT(xy, 'hernandez1999')
  print(CCT)

  # 3557.10272422
Regster Up
  • 113
  • 1
  • 2
  • 7
Kel Solaar
  • 3,660
  • 1
  • 23
  • 29
  • @dfrankow: Glad it helped! If the answer solved your issue please mark it as accepted. If you have any more questions don't hesitate to ping me. – Kel Solaar Aug 12 '16 at 02:45
  • Just a note since it's not explicitly stated: this makes the assumption that the RGB colours are actually sRGB colours. Which is probably wrong, but a good enough approximation. – Michael Mauderer Aug 13 '16 at 19:06
  • @MichaelMauderer: It was assumed by the comment "# Assuming sRGB encoded colour values." – Kel Solaar Aug 13 '16 at 19:43
  • @KelSolaar What does that assumption mean, practically speaking? I'm hoping not only for code, but understanding of what's happening. – dfrankow Aug 14 '16 at 23:50
  • @dfrankow: It means that the RGB values are expected to be encoded accordingly to sRGB colourspace specification (i.e. they are using its gamut and transfer function). Colour provides the `colour.RGB_to_XYZ` definition if you want to have more control about the input RGB colourspace. – Kel Solaar Aug 16 '16 at 23:04
  • @KelSolaar Sure, that's what it means technically. But, what does it mean practically speaking? When I say a web page color is (b0, b0, b0), is that sRGB? Do most monitors display something close to sRGB? What does it mean? – dfrankow Aug 18 '16 at 02:48
  • 1
    (b0, b0, b0) are code values for the working RGB colourspace of your webpage / browser which is almost certainly sRGB: https://www.w3.org/Graphics/Color/sRGB.html. Most of the images you will find online are also sRGB encoded, if not it will be specified as being in another colourspace (through mean of an embedded ICC profile for example). If you don't know which encoding is being used, the safest bet is usually assuming it is sRGB. Most consumers monitors are calibrated to sRGB specifications too. – Kel Solaar Aug 18 '16 at 06:43
  • any idea if there is a javascript equivalent library? this is very cool – Kelvin U Aug 23 '17 at 22:32
  • @KelSolaar May I ask why you used XYZ colour space instead of LUV colour space? Also, this temperature you've calculated is of ONE pixel only right? I've seen references calculate x and y chromaticity by just taking mean of X, Y, Z of every pixel but this doesn't seem like it'll be accurate? Thanks for your time! – Reine_Ran_ Sep 24 '18 at 07:31
  • How can we find average temperature of a masked region? – Reine_Ran_ Sep 24 '18 at 08:33
  • @ReineFang: xy chromaticity coordinates are computed from the CIE xyY colourspace which is transformation of CIE XYZ. Yes it is computed for one pixel but you could indeed take the average or the mean of a region. – Kel Solaar Sep 25 '18 at 18:39
  • 1
    Why does [100.0, 100.0, 200.0], a light-blue color, return a negative result? – xinux Oct 23 '21 at 09:54
  • This is a good question, I haven't tried that particular colour but the concept of correlated colour temperature only holds true within a certain distance of the planckian locus, i.e. 5x10−2 Duv. – Kel Solaar Oct 23 '21 at 18:57
1

Here is a formula in Java,

  double n = ((0.23881) * Color.red(previewColor) + (0.25499) * Color.green(previewColor) + (-0.58291) * Color.blue(previewColor)) / ((0.11109) * Color.red(previewColor) + (-0.85406) * Color.green(previewColor) + (0.52289) * Color.blue(previewColor));
  double cct  = 449 * Math.pow(n,3) + 3525 * Math.pow(n,2) + 6823.3 * n + 5520.33;

here the value for previewColor is the integer representation of the color

Hashir Labs
  • 190
  • 2
  • 6