哪个矩阵对于将 XYZ 映射到 sRGB 的线性 RGB 是正确的?

问题描述

似乎映射矩阵有 3 个主要变体,它们与小数点后第 3 位或第 4 位有所不同。哪个会被视为标准矩阵?

  1. 布鲁斯·林德布鲁姆http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
    从红色、绿色、蓝色和 D65 参考白色 (X,Y,Z) 的 (x,y) 计算
  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  
  1. 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  
  1. 维基百科https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation
    声称是 sRGB 规范
  XYZ -> RGB
  +3.24096994 -1.53738318 -0.49861076  
  -0.96924364 +1.87596750 +0.04155506  
  +0.05563008 -0.20397696 +1.05697151  

解决方法

严格来说,这些都不正确,因为它们源自 IEC 61966-2-1:1999 给出的原色和白点,并在一些任意小数位四舍五入。所以这里有两个真正的选择,要么使用标准给出的矩阵,即四舍五入到小数点后四位,要么直接以全机器精度(理想情况下为双精度)计算归一化主矩阵及其逆矩阵。

IEC 61966-2-1:1999

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)
"""

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 矩阵不舍入时,它们会产生后果 -例如,正确旅行。

问题在于提供原色/白点和从/到 RGB 到/从 CIE XYZ 的转换矩阵会产生歧义。你选择哪一个?人们会倾向于选择矩阵,因为它们已经被计算过,这很容易通过运行基本的 Google Search 来验证。

为了与其他软件交换,您可能想要选择已发布的矩阵,但是,对于内部颜色转换工作,首选派生矩阵,因为如果执行大量来回转换,您将减少舍入的影响.但实际上,你会发现这并不重要。

,

链接到的 W3C 定义是最早的预标准化提案。它已被弃用,因为它由于过度舍入而出现错误。最终的 IEC 61966-2-1:1999 纠正了这个错误,并在 IEC 61966-2-1:1999/AMD1:2003 中进一步修订。

CSS Color 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 Color 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 个 1),但 XYZ 和 ICtCp 就是这种情况,ITU 建议使用带有 14 个小数点的 ICtCp 矩阵。)另外,我认为你不需要真的提高精度,只要提高逆矩阵的精度就足够了。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...