Closed hotgluebanjo closed 1 year ago
@KelSolaar if you have time or any suggestions; don't know if this repo is monitored much.
Never mind, got it.
# Usage of Adobe DNG ColorMatrix2 matrices from DCRAW.
# - https://www.cloudynights.com/topic/529426-dslr-processing-the-missing-matrix/?p=7088475
# - https://www.dpreview.com/forums/thread/3973636#forum-post-57370152
# - https://ninedegreesbelow.com/files/dcraw-c-code-annotated-code.html#E
import colour
import numpy as np
example_matrix = [
[4716, 603, -830],
[-7798, 15474, 2480],
[-1496, 1937, 6651],
]
# ColorMatrix2 is XYZ to camera native.
colormatrix2 = np.asarray(example_matrix, dtype=float)
colormatrix2 /= 10_000
bt709_to_xyz = colour.RGB_COLOURSPACES["ITU-R BT.709"].matrix_RGB_to_XYZ
bt709_to_camnat = np.matmul(colormatrix2, bt709_to_xyz)
# Scale so all rows sum to one. This does not change ratios
# between each coefficient; only scales all three. The key and
# weird bit is that it's on BT.709.
bt709_to_camnat[0] = bt709_to_camnat[0] / np.sum(bt709_to_camnat[0])
bt709_to_camnat[1] = bt709_to_camnat[1] / np.sum(bt709_to_camnat[1])
bt709_to_camnat[2] = bt709_to_camnat[2] / np.sum(bt709_to_camnat[2])
# Comparable to DXOMark matrices.
camnat_to_bt709 = np.linalg.inv(bt709_to_camnat)
# Finally.
camnat_to_xyz = np.matmul(bt709_to_xyz, camnat_to_bt709)
print("Camera to BT.709:")
print(camnat_to_bt709)
print("Camera to XYZ:")
print(camnat_to_xyz)
Matrices match
dcraw -4 -T -o 0
to -o 1
and -o 5
.
The output somewhat matches the PhysLight example, with slight differences. I guess there needs to be some kind of adaptation.
[[ 0.84577580328554 -0.12466479613679 0.22934491990293]
[ 0.41510812703395 0.66843732176224 -0.08354544879619]
[ 0.06934538560373 -0.22271261874517 1.24242498390132]]
Hey @hotgluebanjo,
Glad you figured it out! We should probably include the derivation for future code archeologists!
Cheers,
Thomas
Hey Thomas,
That would be great! Might be interesting to compare.
A related question I've been meaning to ask: I happened to find a comment of yours about manufacturer camera matrices and was wondering about this statement:
They can be derived with some work or obtained with a NDA
What kind of derivation might that be? If a manufacturer's SDK or software has a "Camera RGB" debayer option, it's a pretty straightforward solve. Is it possible without that kind of option?
I guess accuracy wouldn't be possible without a baseline (I only ask because of the wonderous existence of this), but perhaps approximating might help to remove the bogus values these matrices sometimes introduce -- almost as a camera-specific gamut mapping solution, from which a more complex response could be formed.
My casual idea was making a diffraction grating setup and then solving from there. I know this is a really specific and strange scenario. :D
This matrix is used for comparison:
However it doesn't match the Adobe matrix from DCRAW or LibRaw.
Is there a simple explanation for how to prepare them? Or an alternative method? The annotated code hasn't helped much, and it seems they're obfuscated. Any help would be appreciated.