抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

颜色管理是图形学中一个非常重要的课题,图形学与图像和颜色的可视化息息相关,但是我们有时候追求的是储存元数据的信息,有时候又追求的是图像看上去合理,符合美术工作人员的期待。不同的显示器、不同的颜色空间管理以及不同的人眼都会产生颜色的感知偏差。

参考:

学习过程中,如有错误,欢迎指正。

一、Gamma 矫正

Gamma矫正最初是为了适应CRT显示器的非线性输出问题,由于sRGB色彩空间提出的时代,流行的CRT显示器显示图片时,实际发出的亮度和电信号(也就是颜色数据)表示的亮度不是线性的,CRT显示器的非线性输出具体来说是,如果输入一个0.5的值到显示器,显示器会呈现出0.218的值。因此需要提前对图像数据进行一个1 / 2.2 = 0.4545的一个幂次变换,此过程称为伽马校正,校正过后的图像数据处在伽马空间中。但是其实sRGB并不只是一个单纯的伽马校正,是个接近1 / 2.2的分段函数。
而目前Gamma矫正的存在则是主要为了适应人眼的非线性感知问题。人眼对暗部细节的感知更加丰富,因此使用gamma矫正在储存图像时,相当于对源数据的暗部进行了展开,亮部进行了压缩,这样能储存更丰富的暗部细节信息。但gamma矫正本质上是一种编码格式,并不应该影响实际的数据,比如源数据在储存为RGB格式时做了gamma矫正,那么在从RGB文件中读取时要做反gamma矫正重新映射回源数据。
另外,由于历史遗留原因,我们使用的大部分显示器,仍然沿袭CRT显示器的这种非线性输出,也就是我们再把数据传递给显示器时需要做一个类似gamma矫正的变换,而显示器则会做一个类似CRT显示器的反gamma变换。

二、色彩模型 Color Model

色彩模型规定了颜色能够被哪些分量(也就是原色)进行表示。举例来说RGB色彩模型下的颜色就可以用RGB三原色的数值来进行表示,比如存在一个颜色可以表示为[Red = 0.2, Green = 0.75, Blue = 0.13]。
常见的色彩模型有RGB、CMYK、HSV、HSL等。
其中,电子设备流媒体等一般都使用RGB色彩模型,这也是最常用的色彩模型,而印刷一般使用CMYK色彩模型。HSV色彩模型更多用于设计中调整颜色。

RGB计色法及三基色概念

色彩空间的基础就是颜色,要弄清楚色彩空间首先就要弄清楚颜色是怎么被记录和显示的。各种不同波长的光线通过直射、折射或者反射的方式进入我们的眼睛,刺激视网膜上的锥状细胞来产生颜色的感觉。
锥状细胞分为三种:L(Long-长波)型、M(Medium-中波)型和S(Short-短波)型。其识别颜色的波长的峰值分别为:L型-564580nm;M型-534545nm;S型-420~440nm。由于 L型 细胞的敏感区更接近红色,所以称为感红细胞;M型 为感绿细胞;S型 为感蓝细胞。如下图:
三种视锥细胞

由于人类对不同颜色光线混合的反应是线性的(格拉斯曼定律),对于不同光谱所组成的色光,只要对这三种锥状细胞产生的刺激相同,就可以形成一样的色彩感觉,所以几乎所有的颜色都可以由三种基本颜色混合而成。

在1931年,CIE(国际照明委员会)规定的三基色为:700nm-红光;546nm-绿光;435nm-蓝光,并且用配色实验(增加或减少 RGB 颜色,使待配色与 RGB 混合色视觉效果相同)配出了色光的 RGB 分布系数。

值得一提的是,RGB 计色会出现负数,出现负数的原因在于 RGB 亮度是累加的,如果出现比较暗的光线,则必须在待配色中增加 RGB 分量。如下图 R 为负意味着,只靠三基色的混合无法达到和该波长的光视觉效果相同,只能在该波长的光里面加红基色,才能达到两边视觉效果相同,因此就出现了R的负值。
RGB 混色曲线

XYZ计色法

上文说到了 RGB 混合中出现了负值,容易产生错误;且 RGB 不能直观体现亮度的信息。为了解决 RGB 计色所存在的问题,CIE 通过对 RGB 计色法的线性变换,创造出了 XYZ 计色法。
XYZ 计色法中的 Y 分量单独表示亮度,X 与 Z 不包含亮度信息,且 XYZ 永远为正。XYZ 并没有实际的物理意义,为虚基色,CIEXYZ 所能表述的颜色要比 CIERGB 多,它的色度由 XYZ 的比例来决定。
值得注意的是,从RGB到XYZ的变换本质上是一个二维的线性变换,是在$r+g+b=1$这个前提确定的平面上进行的从rg空间到xy空间的变换,变换基于这样一个实验前提:
国际照明委员会(CIE)在颜色匹配实验中发现,当红R、绿G、蓝B这三原色光的相对亮度比例为1.0000: 4.5907 : 0.0601时就能匹配等能白光,所以CIE选取这一比例作为红、绿、蓝三原色的单位量,即(R)、(G)、(B)= 1:1:1。
尽管这时三原色光的亮度值并不相等,但CIE却把每一原色的亮度值作为一单位看待,所以色光加色法中红、绿、蓝三原色光等比例混合(r=g=b=0.333)结果为白光。
具体来说,在rg空间确定xz直线的方法就是:联立$L = 1.0000r + 4.5907g + 0.0601b = 0$和$r+g+b=1$,如下图
RGB 混色曲线
下图为 XYZ 混色曲线。
XYZ 混色曲线

三. 不同的Color Space以及其换算

由于我们是进行设计、创作、游戏等,最终都会使用显示器、屏幕等进行显示,而这些设备一般都是使用RGB色彩模型,因此此文章只讨论RGB色彩模型相关的问题。

白点(White Point)和原色(Primaries)

白点是一个色彩空间里设定为白色的点,用开尔文或者色度来表示。原色就是一个色彩空间的基本颜色,其他颜色都可以通过这些基本颜色进行表示,也用色度表示。每个色彩空间有不同的原色、白点。

以DCI-P3 D65色彩空间为例(D65表示其白点为6500开尔文色温的颜色),其白点为(0.3127, 0.3290),原色为R = (0.68, 0.32),G = (0.265, 0.650),B = (0.15, 0.06)。

CIE XYZ颜色空间

CIE XYZ颜色空间中的XYZ是对之前CIE RGB颜色空间的一个修改,因为之前CIE RGB颜色空间不能表达出人眼可见的所有颜色。CIE XYZ颜色空间可以表达所有的可见颜色,是绝对颜色空间,因此常常用这个CIE xy色度图来度量其他颜色空间的色域(Gamut),这种表示方法也叫三色刺激值(Tristimulus Value)表示,也称为色度(Chromaticity)表示。

RGB色彩空间

RGB色彩模型下有很多色彩空间,常见的有sRGB、Adobe RGB、ProPhoto RGB、DCI-P3、Rec.2020、Rec.709、ACES2065-1、ACEScc/ACEScct、ACEScg。

sRGB

sRGB(Standard RGB)是目前最常用的色彩空间,它是一个带有伽马的色彩空间。

Rec.709色彩空间

也是一个伽马空间,通常认为它的伽马值为2.4,但实际上也是个分段函数。Rec.709和sRGB其实色域差不多。

DCI-P3

DCI-P3蛮怪的,它的色温是6300开尔文,但不是在CIE Standard Illuminant下的,所以不能称为63D,而且白点稍微有点发绿,好怪。然后它是一个系数为2.6的伽马空间,这是为了能适当兼容sRGB。但是DCI-P3色域比sRGB大了有30%,因此许多HDR设备都用这个色彩空间,比如你的手机。

Display-P3

Display-P3是苹果创造的色彩空间,要正常一点。它使用65D的白点,系数为2.2的伽马空间,非常兼容sRGB,感觉还不错。

Rec.2020

Rec.2020又比上面两个P3的色域大上一圈,色域相当不错,但是显然造价更高,在激光影院可能会使用。

Adobe RGB

Adobe RGB和DCI-P3的色域面积是差不多的,然而是两个差别不小的色彩空间,所以说在选购显示器的时候不要只关注色域的面积,主要看它的色度图以及和你想要的色彩空间的覆盖率。

四. 色域 Color Gamut

由于 CIE XYZ 三基色所合成的色光是由他们的比值所决定的,因此我们可以对xyz分量做归一化,取 $x+y+z = 1$。相当于原来的色域在三维空间中是一个三维的范围,但是我们现在只取$x+y+z = 1$这个平面上的部分考虑,如下图:
平面切割色域范围
在这个平面上,已知其中两项就可以得到 XYZ 计色法的色度,所以 XYZ 计色法的色度就可以由 xy 二维坐标来表示,我们取该平面在二维空间下的投影,就得到了我们在很多地方都可以看到的马蹄图,他的学名叫CIE XYZ色度图。
XYZ 混色曲线

马蹄形的左右两边的轮廓线代表了波长由 380nm-700nm 连续变化的单色光;马蹄形的底边代表了紫红色光。值得一提的是,紫红色光并不是单色光,而是由红色(700nm)和紫色(380nm)混合而成。在马蹄形内部,越靠近马蹄形边缘的颜色饱和度越高。

相信大家都接触过不少的色域,比如有些相机里会自带一些色域:sRGB、Adobe RGB。还有部分厂家会有自己特有的色彩空间,如索尼的 S-Gamut3、松下的 V-Gamut、富士的 F-Log-Gamut;以及各种国际标准色彩空间:ProPhoto RGB、P3、Rec.709、Rec.2020 等等。
这些色域都可以在色彩空间色度图中表现出来,严格来讲这些色域都是颜色空间 CIEXYZ 的子集。可以通过线性变化来得到。

色域图 上图为各个色域在 CIEXYZ 色度图上的映射,三角形三个顶点分别是对应 RGB 的颜色。Rec.709 与 sRGB 的范围相同。

确定 RGB 三点以及白点的值,就可以表达一个色域。色域中的 RGB 值可以通过线性变化得到 XYZ 的值:
$$ \begin{bmatrix} x\y\z \end{bmatrix} = \begin{bmatrix} M \end{bmatrix} \begin{bmatrix} r\g\b \end{bmatrix}$$
各个色彩空间的 [M] 值 可以通过标准制定者给出的数值得到,可以参考网站:http://www.brucelindbloom.com 或是各个白皮书中找到。

目前被大多数显示设备所接受并使用的 Rec.709 标准使用的色域与 sRGB 相同,并且网络上显示图片的标准也是 sRGB,这就意味着 sRGB 目前统治着大部分的市场。部分相机虽然支持更大的色域范围,如:ProPhoto RGB、Adobe RGB、S-Gamut3、F-Gamut 等,但是要上传到网络空间则须转换到 sRGB 的色域。

若色域未经转换就直接丢给 Rec.709 标准的显示器或者上传到网络空间的话,会产生颜色偏差。这是因为 Rec.709 标准的显示器把更宽广色域的 RGB 三值直接对应到 sRGB 的值中所产生的偏差,通常会出现饱和度下降的情况;若两个色域的白点也不一致的话,色温也会出现偏差。

下图为 ProPhoto RGB 和 sRGB(Rec.709)的色域对比,同样的重心坐标在两个不同的颜色空间代表的是不同的颜色:
ProPhoto RGB 和 sRGB(Rec.709)的色域对比

五. 颜色变换管线

微软有在文档里写普通的颜色变换管线和Windows实现任意两个色彩空间转换的过程。

颜色变换管线

首先0是原本的色彩空间,首先如果这个色彩空间不是线性空间,则需要先进行反伽马变换1,变换完后就到了线性空间,线性空间的颜色就可以通过颜色矩阵2这种线性变换来变换到其他颜色空间,如果目标颜色空间也是一个伽马空间,则要施加一个对应的伽马校正3,然后就得到了转换后的颜色空间。
颜色变换管线

Windows的颜色变换管线

Windows使用单独的管线。其实这个例子都不太像是颜色变换管线而是图像显示管线了。
颜色变换管线
介绍一下各个步骤:

  • 第0步,那就是Framebuffer里面渲染得到的颜色数据,它们都是RGB伽马空间的,可以是sRGB, sYCC, HDR10, 或者scRGB颜色空间。
  • 第1步,反伽马,转换到线性空间。
  • 2a、2b、2c是颜色空间转换的三个变换,它们乘在一起就是颜色空间的转换矩阵。
  • 2a:从线性空间转换到CIE XYZ的绝对颜色空间。
  • 2b:做一些例如校准的调整,可编程。
  • 2c:从CIE XYZ转换到目标的线性的RGB色彩空间上。
  • 2a和Framebuffer相关,2c和显示器相关,普通应用可以控制2b这个矩阵。
  • 显示颜色也分两步。
  • 3a:使用EOTF来伽马校正,由显示器驱动完成。
  • 3b:做一些例如校准的调整,又是可编程的那种。
  • 3a的转换由wire format color space(实在搜不到)来指定,但应该就是显示器的颜色空间,例如SDR显示器就需要做一次伽马校正,HDR10显示器就需要做一次逆PQ(或称ST.2084)电光传输函数的变换。
  • 完成上述步骤后,Framebuffer(没错,还是在Framebuffer里)里的数据就会扫描到你GPU连接显示器的那条线里,然后显示。

六. 色调映射(Tone Mapping)

简单地从色域较大的空间转换到色域较小的空间,一定会产生SDR中无法表现的颜色,如果直接将超出范围的颜色进行截断,就会出现如大片相同颜色,因此需要在转换之前先进行色调映射。此外HDR图像是浮点表示的,可能会产生值超过1的部分,但SDR是归一化的色彩空间,所以数据上来说,其归一化后的数值只能从0到1,要将HDR图像转换到SDR,就需要色调映射。

色调映射的基本原理就是把颜色变化从更大的色域范围压缩到更小的色域范围,但是仍保持颜色的差别和对比。

色调映射的算法蛮多,比较常用的有CE Tone Mapping、Filmic Tone Mapping,但现在基本都被ACES色调映射统一了。这篇文章说ACES色调映射是ACES提出的,但是我找不到任何证据(比如ACES官网上查不到任何色调映射相关的文字)说明这是ACES提出,而应该是Epic Games的图程Krzysztof Narkowicz基于ACES的ODT提出的,他在他的博客中有提到,在研究出来之后称为了UE的默认色调映射函数,UE的文档可以看到。

七. ACES(Academy Color Encoding System)流程

这玩意太难了先搁置。

评论