-
-
Notifications
You must be signed in to change notification settings - Fork 278
Description
Description
I was looking over the implementation paper of sCAM, and was verifying my results against Colour Science's, and I am a little confused about one point.
sCAM uses the IPT LMS transformation matrix. The sCAM paper states that the color should be in D65 when converting to Iab, but does not state what D65 is. What is interesting is that it states the HPE matrix is used, but what is listed is the modified one that IPT uses, which was specifically adapted for a white point of [0.9504, 1.0, 1.0889] (which is specifically stated in the IPT paper).
TO_LMS = [
[0.4002, 0.7075, -0.0807],
[-0.2280, 1.1500, 0.06124],
[0.0, 0.0, 0.9184]
]
FROM_LMS = LMS_TO_XYZ = [
[1.8502, -1.1383, 0.2385],
[0.3668, 0.6439, -0.0107],
[0.0, 0.0, 1.0889]
]I will note that the IPT paper specifies
1.8501in the inverse matrix, but this appears to be a mistake, as the inverse clearly yields a1.8502.>>> import numpy as np >>> m = [ ... [0.4002, 0.7075, -0.0807], ... [-0.2280, 1.1500, 0.06124], ... [0.0, 0.0, 0.9184] ... ] >>> np.linalg.inv(m) array([[ 1.85024294, -1.13830164, 0.23848454], [ 0.36683078, 0.64388454, -0.01070149], [ 0. , 0. , 1.08885017]])
Now the forward transform creates noise in anything greater than 16-bit due to rounding.
>>> w = [0.9504, 1.0, 1.0889]
>>> np.matmul(m, w)
array([0.99997585, 0.99999304, 1.00004576])But if we used the inverse transform, we can see that it yields a good LMS transform of [1, 1, 1] to the expected white point past 16-bit. It is clear that the transformation matrix was tailored to [0.9504, 1.0, 1.0889].
>>> mi = [ ... [1.8502, -1.1383, 0.2385], ... [0.3668, 0.6439, -0.0107], ... [0.0, 0.0, 1.0889] ... ] >>> np.matmul(mi, [1, 1, 1]) array([0.9504, 1. , 1.0889]) >>> np.matmul(np.linalg.inv(mi), [0.9504, 1.0, 1.0889]) array([1., 1., 1.])
Colour Science seems to assume a white point of:
TVS_D65_sCAM = np.array([0.95047, 1.00000, 1.08883])And while I am aware this is a commonly used white point, and am aware of how it is derived, it seems to be an odd choice for the LMS matrix being used.
Is [0.95047, 1.00000, 1.08883] truly the white point that should be used? Or should it be [0.9504, 1.0, 1.0889]?
Currently, even when inputting [0.95047, 1.00000, 1.08883] into the sCAM conversion, you will not get 100% lightness in sCAM 1) due to the reverse LMS transform being generated from the forward transform which generates noise in anything greater than 16-bit, and 2) the LMS transform is not meant for the white point being used (unless it was adapted to the D65 variant being used).
If the appropriate white point (in the context of the IPT LMS matrix) was used, and the forward transform was generated from the reverse transform, you would then yield a clean 100% lightness in sCAM for the same white if it was the input.
Anyway, I thought it was worth bringing up the topic.