Solved – Converting spectral data to RGB and normalizing appropriately

correlationhistogramnormalization

I have spectral data which tells me how strong of a response in RGB values for some color-space I get for a particular wavelength of light.

Typically, if I want "plain" white light, I'd have to sum up all the values in equal amounts and it should result in RGB #FFFFFF white. However, my data isn't normalized like that. I overshoot pure white by quite a bit. And what's worse, this overshoot doesn't happen equally for my three channels, ending up in something that evidently is not pure white.

Now I wonder: Would it be accurate to just normalize by a factor per color channel so it "simply works"? Or do I have to consider correlations between color channels and the spectral data set more carefully? If so, how exactly would I go about that?

If my actual dataset helps, it's simply what WolframAlpha puts out when you put in wavelengths in the visible spectrum.
For instance, 500nm results in RGB: {0., 0.671, 0.492} – it's accurate to 1nm and goes from 380nm to 750nm.


Now, I'm not sure if this is the right place to ask this question. I could think of several SE sites that may touch on this to varying extends. However, I believe that this can probably be applied to more generic problems that would arise in statistics and the fit is closest to it, so I'll ask here. If you think, this rather is unrelated, please comment me either how to make the question more relevant or where I should ask it. Similarly, I'm not sure if I am using the best tags.

Best Answer

tl;dr: $RGB$ is the wrong space to do the normalizing in since it is device dependent. You should work with device independent color coordinates like $xyL$. Only in the final step transform to $RGB$. Any per-scene intensity reduction has to be made by scaling the $L$ coordinate from $xyL$ space with a common factor.

For a transparency model based on physics see this paper, especially section 2.2. Follow-up paper 1, follow up paper 2.

Long answer: I think it's necessary to avoid some conceptual confusion regarding the subject matter. Most importantly, color is not a physical property.

  • Light (=physical quantity) is characterized by its energy distribution over the spectrum. The human visual system responsible for daylight vision has three cone types with different sensitivity over the spectrum (peak sensitivity for Long, Medium, and Short wavelengths). This means that a light beam will elicit a specific triple in cone excitations (but different lights may well lead to the same cone excitation triple).
  • Color (=psychological property) is linked to the cone excitation triple. Therefore, one way to uniquely represent one color impression is to take the corresponding cone excitation triple (strictly speaking, this is only true for isolated light beams). Nicely enough, the space generated by these triples behaves like a linear 3D-vector space. Versions of this space are the $XYZ$ and the $LMS$ color space. A common transformation is $xyL$ space where chromaticity ($xy$) and luminance $L$ are separated.
  • Using the cone sensitivity functions thought to be universal for all humans, you can calculate the corresponding cone excitation triple or $xyL$ coordinates for all light beams with a specified energy distribution of the spectrum.
  • $RGB$ is a different kind of space: It tells a monitor the intensities for each of its three "light guns" (as it was called for CRTs). This is device dependent, meaning that one $RGB$-triple is uniquely associated with one specific light and hence one color impression only for a particular monitor. This problem is what monitor calibration is all about. In addition, since the output of a monitor is restricted in energy, it cannot create arbitrary lights and hence arbitrary color impressions.

Coming to the question of normalizing: With your goal of physically correct rendering, you need to do all your computations per wavelength. With the final result, you then need to apply the cone sensitivity functions to get to $xyL$ space. Then, you need to apply the monitor specs to know which $RGB$ values will produce these $xyL$ triples. For this step, you need to have the specs for a typical LCD (this is what Wolfram alpha must be doing - otherwise the answer would be nonsensical since there is no unique relationship between a device dependent format like $RGB$ and a device independent light).

If some $xyL$ triples cannot be elicited due to monitor restrictions, you need to reduce the intensity of the rendered scene until all $xyL$ triples are inside the monitor gamut. This can be done with a single scalar factor that applies to all $L$ coordinates. This will make the whole scene uniformly darker. Since the 3D-shape of the monitor gamut is weird, this is not a simple normalizing step.