5
$\begingroup$

I'm trying to compute the following integral:

$$\int_{380 \, \mathrm{nm}}^{700 \, \mathrm{nm}}\mathbf{RGB}(\mathrm{Hue}(\lambda))\frac{\mathrm{d}\lambda}{\lambda^4}$$

where $\mathbf{RBG}$ takes in a Hue and outputs a vector like {0., 1., 1.}.

This is how I've tried to implement this:

lambdaToHue[wavelength_] := Hue[-.8/(700 - 380) wavelength + 1.75]

which takes wavelengths into Hues, (evaluating it on 380 gives purple, on 700 gives red). Then

hueToRBG[hue_] := Table[ColorConvert[hue, "RGB"][[i]], {i, 1, 3}]

takes Hues into vectors, so e.g. evaluating it on lambdaToHue[380] gives {0.8, 0., 1.}. So I can put in values for wavelength and get numbers from hueToRBG[wavelengthToHue[wavelengths]]. So I should be able to compute an integral, like

NIntegrate[hueToRBG[lambdaToHue[l]]/l^4,{l,380,700}]

but in reality Mathematica complains:

"The integrand Hue[1.75 -0.0025\ l] has evaluated to \
non-numerical values for all sampling points in the region with \
boundaries {{380,700}}"

How can I get mathematica to actually just compute the integral of this function which takes numbers into lists of numbers? It works fine, e.g., for

NIntegrate[{x,Sin[x],Sqrt[x]}/x^4,{x,2,4}].

Much thanks!

$\endgroup$
7
  • 1
    $\begingroup$ Better use ColorData["VisibleSpectrum"] instead of Hue. Should be more related to the actual physical colors... $\endgroup$ Commented Dec 3, 2018 at 20:19
  • 1
    $\begingroup$ @HenrikSchumacher thanks I'll be sure to use that! But I still have the same issue with Mathematica complaining that I'm trying to integrate over colors without noticing that I'm actually summing vectors $\endgroup$
    – Diffycue
    Commented Dec 3, 2018 at 20:36
  • $\begingroup$ I have found an extremely hacky way of doing this; waiting for a better solution: integrate numerically using Total /@ Transpose[(Table[ ColorData["VisibleSpectrum"][\[Lambda]] /. RGBColor[a___] -> {a}, {\[Lambda], 380, 750, 0.1}]* Table[0.1/\[Lambda]^2.5, {\[Lambda], 380, 750, 0.1}])] $\endgroup$
    – Diffycue
    Commented Dec 3, 2018 at 20:57
  • 1
    $\begingroup$ Sum [.1 1/\[Lambda]^4 Apply[List, ColorData["VisibleSpectrum"][\[Lambda]]], {\[Lambda], 380, 750, 0.1}] evaluates to {1.56038*10^-9, 1.46384*10^-9, 2.74953*10^-9} black $\endgroup$ Commented Dec 3, 2018 at 21:16
  • 1
    $\begingroup$ Perhaps: f[\[Lambda]_?NumericQ, k_] := (ColorData["VisibleSpectrum"][\[Lambda]])[[k]];NIntegrate[f[\[Lambda], #]/\[Lambda]^4, {\[Lambda], 380, 700}] & /@ Range[3]? $\endgroup$
    – chuy
    Commented Dec 3, 2018 at 21:29

1 Answer 1

3
$\begingroup$

As noted in this thread, the CIE sensitivity functions are built-in, yet undocumented:

ChromaticityPlot; (* force autoload *)
xyz = Interpolation[Transpose[{Image`ColorOperationsDump`$wavelengths, #}]] & /@ 
      Transpose[Image`ColorOperationsDump`tris];

However,

MinMax[Image`ColorOperationsDump`$wavelengths]
   {{385, 745}}

its coverage is a little off from the desired integral in the OP, so I'll just demonstrate the integral from $385$ to $700\,\mathrm{nm}$. (If wanted, you can download a finer tabulation with more coverage.)

From here, we can use the sRGB conversion functions from this answer, and then use NIntegrate[] with the setting Method -> "InterpolationPointsSubdivision":

(* gamma correction *)
sRGBGamma = Function[x, With[{z = Abs[x]},
                             Sign[x] Piecewise[{{12.92 z, z <= 0.0031308}},
                                               1.055 z^(1/2.4) - 0.055]],
                     Listable];

NIntegrate[Clip[#, {0, 1}]/λ^4, {λ, 385, 700},
           Method -> "InterpolationPointsSubdivision"] & /@ 
sRGBGamma[{{3.2404542, -1.5371385, -0.49853141},
           {-0.96926603, 1.8760108, 0.041556017},
           {0.055643431, -0.20402591, 1.0572252}}.Through[xyz[λ]]]
   {1.48544*10^-9, 1.36666*10^-9, 2.28451*10^-9}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.