gtaylor / python-colormath

A python module that abstracts common color math operations. For example, converting from CIE L*a*b to XYZ, or from RGB to CMYK
python-colormath.readthedocs.org
BSD 3-Clause "New" or "Revised" License
456 stars 83 forks source link

Spectral to xyz values #102

Closed hoonkai closed 4 years ago

hoonkai commented 4 years ago

Hi

I'm trying to convert some spectral measurements to CIELab.xyz by doing the following:

spectrum = [0.210776,0.252114,0.324058,0.51328,0.81575,0.91755,0.906283,0.875658,0.83983,0.808047,0.776573,0.748423,0.722062,0.697147,0.669805,0.641675,0.615496,0.588516,0.56613,0.558417,0.560493,0.569653,0.580898,0.592616,0.607429,0.626789,0.648801,0.670411,0.688268,0.698663,0.702309,0.702582,0.700639,0.69871,0.700197,0.707411]

spc = SpectralColor(*spectrum, observer='2', illuminant='d50')
xyz = convert_color(spc, XYZColor)
print(xyz) ### XYZColor (xyz_x:0.6298 xyz_y:0.6068 xyz_z:0.6021)

However, i1Profiler gives much different values:

Screen Shot 2020-01-13 at 4 42 00 am

Also the spreadsheet here give values that agree with i1Profiler:

Screen Shot 2020-01-13 at 4 44 16 am

Anyone know why convert_color's values are quite far off?

Thanks

JayPalm commented 3 years ago

Experiencing similar problems with differing spectral to XYZ conversions. How were you able to resolve this?

KelSolaar commented 3 years ago

Hi,

The conversion above as given by @hoonkai is mostly correct, the problem is that his values are coming from a list with 36 elements but python-colormath expects 50, i.e. [340-830, 10]. So the 36 values get mapped from 340nm to 690nm which is obviously producing unexpected results.

Trying to redo the same with Colour, we effectively get very similar output:

>>> import colour
>>> v = [0.210776,0.252114,0.324058,0.51328,0.81575,0.91755,0.906283,0.875658,0.83983,0.808047,0.776573,0.748423,0.722062,0.697147,0.669805,0.641675,0.615496,0.588516,0.56613,0.558417,0.560493,0.569653,0.580898,0.592616,0.607429,0.626789,0.648801,0.670411,0.688268,0.698663,0.702309,0.702582,0.700639,0.69871,0.700197,0.707411]
>>> w = colour.SpectralShape(340, 690, 10).range()
>>> sd = colour.SpectralDistribution(v, w)
>>> colour.sd_to_XYZ(sd, illuminant=colour.SDS_ILLUMINANTS['D50'], method='Integration') / 100
array([ 0.63134464,  0.60726962,  0.60298485])