哪个矩阵对于将 XYZ 映射到 sRGB 的线性 RGB 是正确的?
Which matrix is correct to map XYZ to linear RGB for sRGB?
映射矩阵似乎有 3 个主要变体,它们在小数点后第三或第四位出现偏差。哪个会被认为是标准矩阵?
- 布鲁斯·林德布鲁姆 http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
从 (x, y) 计算出红色、绿色、蓝色和 D65 参考白色 (X, Y, Z)
RGB -> XYZ
+0.4124564 +0.3575761 +0.1804375
+0.2126729 +0.7151522 +0.0721750
+0.0193339 +0.1191920 +0.9503041
XYZ -> RGB (by inverting RGB -> XYZ)
+3.2404542 -1.5371385 -0.4985314
-0.9692660 +1.8760108 +0.0415560
+0.0556434 -0.2040259 +1.0572252
- W3C https://www.w3.org/Graphics/Color/srgb
EasyRGB https://easyrgb.com/en/math.php 似乎使用 W3C,但被截断了
XYZ -> RGB
+3.2406255 -1.5372080 -0.4986286
-0.9689307 +1.8757561 +0.0415175
+0.0557101 -0.2040211 +1.0569959
XYZ -> RGB
+3.24096994 -1.53738318 -0.49861076
-0.96924364 +1.87596750 +0.04155506
+0.05563008 -0.20397696 +1.05697151
严格来说,其中 none 是正确的,因为它们是从 IEC 61966-2-1:1999 给出的原色和白点派生而来,并在任意小数位进行四舍五入。所以这里有两个真正的选择,要么使用标准给出的矩阵,即四舍五入到小数点后 4 位,要么直接以全机器精度计算归一化主矩阵及其逆矩阵,最好是双精度。
MATRIX_sRGB_TO_XYZ = np.array([
[0.4124, 0.3576, 0.1805],
[0.2126, 0.7152, 0.0722],
[0.0193, 0.1192, 0.9505],
])
"""
*sRGB* colourspace to *CIE XYZ* tristimulus values matrix.
MATRIX_sRGB_TO_XYZ : array_like, (3, 3)
"""
MATRIX_XYZ_TO_sRGB = np.array([
[3.2406, -1.5372, -0.4986],
[-0.9689, 1.8758, 0.0415],
[0.0557, -0.2040, 1.0570],
])
"""
*CIE XYZ* tristimulus values to *sRGB* colourspace matrix.
MATRIX_XYZ_TO_sRGB : array_like, (3, 3)
"""
IEC 61966-2-1:1999 使用原色和白点的 ITU-R BT.709 没有指定矩阵,例如,以双精度计算它们:
>>> import colour
>>> import numpy as np
>>> np.set_printoptions(formatter={'float': '{:0.15f}'.format}, suppress=True)
>>> colour.models.RGB_COLOURSPACE_BT709.matrix_RGB_to_XYZ
array([[0.412390799265959, 0.357584339383878, 0.180480788401834],
[0.212639005871510, 0.715168678767756, 0.072192315360734],
[0.019330818715592, 0.119194779794626, 0.950532152249661]])
>>> colour.models.RGB_COLOURSPACE_BT709.matrix_XYZ_to_RGB
array([[3.240969941904523, -1.537383177570094, -0.498610760293003],
[-0.969243636280880, 1.875967501507721, 0.041555057407176],
[0.055630079696994, -0.203976958888977, 1.056971514242879]])
从技术上讲,舍入差异应该被使用 8 位整数表示的任何量化效果所吸收,但是当您使用浮点值时它们会产生影响,而 IEC 61966-2-1:1999 矩阵不会例如正确往返。
问题在于同时提供 primaries/whitepoint 和转换矩阵 from/to RGB to/from CIE XYZ 会产生歧义。你选择哪一个?人们会倾向于选择矩阵,因为它们已经被计算过了,这很容易通过 运行 一个基本的 Google Search.
来验证
对于与其他软件的交换,您可能希望选择已发布的矩阵,但是,对于内部颜色转换工作,派生矩阵是首选,因为如果您执行大量的前后运算,舍入的影响会较小第四次转换。但实际上,你会发现这并没有太大关系。
链接到的 W3C 定义是最早的预标准化提案。它已被弃用,因为它因过度舍入而产生错误。最终的 IEC 61966-2-1:1999 纠正了这个错误,并在 IEC 61966-2-1:1999/AMD1:2003 中进一步修订。
CSSColor 4 中有一个 W3C 定义,它引用了 IEC 标准中的原色度和白点
https://drafts.csswg.org/css-color-4/#valdef-color-srgb
该规范附带的(信息性)示例代码具有根据这些色度以双精度计算的矩阵,并且没有任何舍入
https://drafts.csswg.org/css-color-4/#color-conversion-code
如果四舍五入到小数点后 8 位,它们与维基百科文章中给出的矩阵完全匹配。
CSS 颜色 4 的早期版本使用了来自 Lindbloom 网站的矩阵。我将示例代码更改为使用直接计算的代码,这消除了一些麻烦的往返错误。
如果我按照计算这些值的方法(也在 Lindbloom 的网站上给出),我不会得到他为 sRGB 所做的答案。我怀疑他的计算出现了错误,也许是错误的白点值?
所以维基百科有一个错误,在 IEC 标准中使用了小数点后 4 位的 XYZ 矩阵(因为倒矩阵第 2 行必须是 BT.709-2 矩阵系数,请参见 SMPTE 177)。在这里介绍过:https://en.wikipedia.org/w/index.php?title=SRGB&diff=949593434&oldid=946057212
我还原了该更改,现在两个矩阵都与 IEC 中的一样。我还从 sRGB IEC 标准的第一修正案中向 BT.709 矩阵添加了更高精度的 XYZ(是的,我有)。他们说这对于 16 位就足够了。他们也只是将小数点后 4 位矩阵还原为 XYZ,而不是进一步定义它。 https://en.wikipedia.org/w/index.php?title=SRGB&diff=1018331095&oldid=1018328711
此外,当然,@kel-solaar 在这里是正确的,您可以进一步定义两个矩阵,但他没有说明的是求逆应该具有更高的精度,因为这就是矩阵求逆的方式作品。 (不是 YCbCr 这就是 YCbCr 矩阵的工作方式(毕竟倒矩阵中有 2 个零和 3 个一),但 XYZ 和 ICtCp 就是这种情况,ITU 建议使用带 14 个小数点的 ICtCp 矩阵。)也,我认为你不需要真正提高精度,只需提高倒矩阵的精度就足够了。
映射矩阵似乎有 3 个主要变体,它们在小数点后第三或第四位出现偏差。哪个会被认为是标准矩阵?
- 布鲁斯·林德布鲁姆 http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
从 (x, y) 计算出红色、绿色、蓝色和 D65 参考白色 (X, Y, Z)
RGB -> XYZ
+0.4124564 +0.3575761 +0.1804375
+0.2126729 +0.7151522 +0.0721750
+0.0193339 +0.1191920 +0.9503041
XYZ -> RGB (by inverting RGB -> XYZ)
+3.2404542 -1.5371385 -0.4985314
-0.9692660 +1.8760108 +0.0415560
+0.0556434 -0.2040259 +1.0572252
- W3C https://www.w3.org/Graphics/Color/srgb
EasyRGB https://easyrgb.com/en/math.php 似乎使用 W3C,但被截断了
XYZ -> RGB
+3.2406255 -1.5372080 -0.4986286
-0.9689307 +1.8757561 +0.0415175
+0.0557101 -0.2040211 +1.0569959
XYZ -> RGB
+3.24096994 -1.53738318 -0.49861076
-0.96924364 +1.87596750 +0.04155506
+0.05563008 -0.20397696 +1.05697151
严格来说,其中 none 是正确的,因为它们是从 IEC 61966-2-1:1999 给出的原色和白点派生而来,并在任意小数位进行四舍五入。所以这里有两个真正的选择,要么使用标准给出的矩阵,即四舍五入到小数点后 4 位,要么直接以全机器精度计算归一化主矩阵及其逆矩阵,最好是双精度。
MATRIX_sRGB_TO_XYZ = np.array([
[0.4124, 0.3576, 0.1805],
[0.2126, 0.7152, 0.0722],
[0.0193, 0.1192, 0.9505],
])
"""
*sRGB* colourspace to *CIE XYZ* tristimulus values matrix.
MATRIX_sRGB_TO_XYZ : array_like, (3, 3)
"""
MATRIX_XYZ_TO_sRGB = np.array([
[3.2406, -1.5372, -0.4986],
[-0.9689, 1.8758, 0.0415],
[0.0557, -0.2040, 1.0570],
])
"""
*CIE XYZ* tristimulus values to *sRGB* colourspace matrix.
MATRIX_XYZ_TO_sRGB : array_like, (3, 3)
"""
IEC 61966-2-1:1999 使用原色和白点的 ITU-R BT.709 没有指定矩阵,例如,以双精度计算它们:
>>> import colour
>>> import numpy as np
>>> np.set_printoptions(formatter={'float': '{:0.15f}'.format}, suppress=True)
>>> colour.models.RGB_COLOURSPACE_BT709.matrix_RGB_to_XYZ
array([[0.412390799265959, 0.357584339383878, 0.180480788401834],
[0.212639005871510, 0.715168678767756, 0.072192315360734],
[0.019330818715592, 0.119194779794626, 0.950532152249661]])
>>> colour.models.RGB_COLOURSPACE_BT709.matrix_XYZ_to_RGB
array([[3.240969941904523, -1.537383177570094, -0.498610760293003],
[-0.969243636280880, 1.875967501507721, 0.041555057407176],
[0.055630079696994, -0.203976958888977, 1.056971514242879]])
从技术上讲,舍入差异应该被使用 8 位整数表示的任何量化效果所吸收,但是当您使用浮点值时它们会产生影响,而 IEC 61966-2-1:1999 矩阵不会例如正确往返。
问题在于同时提供 primaries/whitepoint 和转换矩阵 from/to RGB to/from CIE XYZ 会产生歧义。你选择哪一个?人们会倾向于选择矩阵,因为它们已经被计算过了,这很容易通过 运行 一个基本的 Google Search.
来验证对于与其他软件的交换,您可能希望选择已发布的矩阵,但是,对于内部颜色转换工作,派生矩阵是首选,因为如果您执行大量的前后运算,舍入的影响会较小第四次转换。但实际上,你会发现这并没有太大关系。
链接到的 W3C 定义是最早的预标准化提案。它已被弃用,因为它因过度舍入而产生错误。最终的 IEC 61966-2-1:1999 纠正了这个错误,并在 IEC 61966-2-1:1999/AMD1:2003 中进一步修订。
CSSColor 4 中有一个 W3C 定义,它引用了 IEC 标准中的原色度和白点 https://drafts.csswg.org/css-color-4/#valdef-color-srgb 该规范附带的(信息性)示例代码具有根据这些色度以双精度计算的矩阵,并且没有任何舍入 https://drafts.csswg.org/css-color-4/#color-conversion-code
如果四舍五入到小数点后 8 位,它们与维基百科文章中给出的矩阵完全匹配。
CSS 颜色 4 的早期版本使用了来自 Lindbloom 网站的矩阵。我将示例代码更改为使用直接计算的代码,这消除了一些麻烦的往返错误。
如果我按照计算这些值的方法(也在 Lindbloom 的网站上给出),我不会得到他为 sRGB 所做的答案。我怀疑他的计算出现了错误,也许是错误的白点值?
所以维基百科有一个错误,在 IEC 标准中使用了小数点后 4 位的 XYZ 矩阵(因为倒矩阵第 2 行必须是 BT.709-2 矩阵系数,请参见 SMPTE 177)。在这里介绍过:https://en.wikipedia.org/w/index.php?title=SRGB&diff=949593434&oldid=946057212
我还原了该更改,现在两个矩阵都与 IEC 中的一样。我还从 sRGB IEC 标准的第一修正案中向 BT.709 矩阵添加了更高精度的 XYZ(是的,我有)。他们说这对于 16 位就足够了。他们也只是将小数点后 4 位矩阵还原为 XYZ,而不是进一步定义它。 https://en.wikipedia.org/w/index.php?title=SRGB&diff=1018331095&oldid=1018328711
此外,当然,@kel-solaar 在这里是正确的,您可以进一步定义两个矩阵,但他没有说明的是求逆应该具有更高的精度,因为这就是矩阵求逆的方式作品。 (不是 YCbCr 这就是 YCbCr 矩阵的工作方式(毕竟倒矩阵中有 2 个零和 3 个一),但 XYZ 和 ICtCp 就是这种情况,ITU 建议使用带 14 个小数点的 ICtCp 矩阵。)也,我认为你不需要真正提高精度,只需提高倒矩阵的精度就足够了。