颜色空间和色域映射

       一般的设备通常是用RGB的方式来表示颜色,但是随着新的标准和设备的不断更新,出现了在不同色域下的RGB表示方式。比较常见的是bt2020,bt709和bt601等。出现这些原因主要是随着硬件设备的更迭,显示器可以表达了更广的色域。随之而来就带来了一些所谓的看到同一颜色统一的问题,例如在bt2020下的红色RGB=(1,0,0)和bt709下的RGB=(1,0,0)是不一样的红。在BT709的显示器上是无法正常显示符合bt2020的HDR视频,亮度达不到,色彩也达不到。因此就涉及到了色调映射技术。在前面的文章 介绍过这方面的内容。但是重点放在了亮度方面的映射(例如hable),色度方面我们使用的是ffmpeg中zscale=p=bt709的滤镜命令直接从bt2020转到了bt709下的色度。这当中经历了什么我们全然不知。这篇文章就是记录一下这中间的详细过程以及涉及到的各种颜色空间之间的联系。

颜色空间

色度

了解颜色空间的前提,首先要知道色度学,比如说,为什么我们经常使用的RGB三个值,就可以表示视频下的所有颜色。首先可以通过这里下载到相应的文章介绍,在3.1章节中详细介绍了色度学。这里就以概括的方式来记录一下。以及解释一下可能存在的疑惑。

光是一种波,是波就会有频率,不同频率的光波,我们看到的颜色是不一样的。人类之所以能够看到颜色,是因为人眼中只有三种视觉锥细胞的特性,只使用红色( r),绿色( g)和蓝色( b)三种光线,来模拟所有其他的颜色。这三种颜色称为三原色。国际照明委员为CIE在1931年通过一项实验,他们使用三种波长的光: 700nm(红色光), 546.1nm(绿色光), 435.8nm(蓝色光)作为基色,通光量的比值为:1:4.5907:0.0601,调节三种基色的强度(强度是波的幅度,表现在光上面就是该色读的‘亮度’)并混合后就观察到和单一频率相同颜色的光。

 但是,在435.8nm-546.1nm 这一段的红色光通量为负值,因此在实际生产中无法实现,所以实际上并非所有单色光(只有一个频率,不会发生色散)都可以由 RGB三原色表示出来。这里出现负值的原因是,待配色光为单色光,其饱和度很高,而 RGB三色混合后,饱和度会降低。因此,想要配出一些单色光,需要将 RGB 三色光中的某一个与待配色光混合,才能实现。此时就会出现负值。那为什么之前说rgb的混合可以表示所有的颜色呢。这是因为,我们平时很少能够看到单色光(频率单一),大部分都是混合色。而对于非单色光,任意光谱分布的RGB至都可以由积分得出,解释这一现象的基本观点是:视觉四原色理论认为,在整个的光谱中根本就没有单色光。如果还是不能理解,可以参考这里。另外,所谓的负数,其实可以当成添加该颜色的补色,这样就比较容易理解一些。另一方面,可以这样理解,颜色是人眼观察到的,人眼觉察到颜色是由于光波刺激网膜上的锥状细胞来产生颜色的感觉,而锥状细胞分为三种:L(Long-长波)型、M(Medium-中波)型和S(Short-短波)型。其识别颜色的波长的峰值分别为:L型-564~580nm;M型-534~545nm;S型-420~440nm,如图

由于 L型 细胞的敏感区更接近红色,所以称为感红细胞;M型 为感绿细胞;S型 为感蓝细胞。人类对不同颜色光线混合的反应是线性的(格拉斯曼定律),对于不同光谱所组成的色光,只要对这三种锥状细胞产生的刺激相同,就可以形成一样的色彩感觉。从上图上看,三基色所在的波频率,都有其他颜色的分量。因此会触发435.8nm-546.1nm这段,使用单色光的情况配比,红色分量变成负数。

最终为了归一化和消除亮度带来感受上的差别,得出下图

 归一化后的结果:

 因为三个数值的总和为1,知道了两个值,第三个值就自动得出。可以用两维坐标进行表示。

RGB <->CIE-XYZ

感觉这些理论知道一些就可以,主要是得出CIE-XYZ和CIE-xyY的表示方法以及从传统RGB的表示方法到XYZ的转换。

其中CIE-XYZ和CIE-xyY是归一化前后的联系。x = X /(X + Y + Z),y = Y /(X + Y + Z),z = Z /(X + Y + Z).

 上面马蹄状内的颜色就可以表示人眼所能看到的所有颜色,与设备无关。各种色域标准所包含的颜色不同,TB2020和BT709的颜色范围:

 常见的色域表:

 以及相应色域下RGB-XYZ颜色空间的转换系数:

 以bt2020为例:rgb=(1,0,0)表示红色,有第一个矩阵系数可知X = 0.637,Y=0.2627, Z=0。其中色域表中是以CIE-xyY的标准。所以

x = X/(X+Y+Z) = 0.637/(0.637+0.2627+0) = 0.708,

y= Y/(X+Y+Z) = 0.2627/(0.637+0.2627+0) = 0.292.

正好符合色域表中的R的坐标点。  这其中隐藏这z的值为z =  1 - 0.708  -  0.292 = 0

其他的可以参考这里的一些资料

CIE-xyY这种不仅仅是归一化这么简单的事情,这主要是颜色的概念可以分为亮度和色度。比如说白色是明亮的颜色,而灰色被认为是不太亮的白色。换句话说,白色和灰色的色度是一样的,而明度不同。所以可以选择固定亮度,从而推导出色度。因此CIE-xyY中的Y其实是表示着YUV表达式中的亮度(明度)一样,通过RGB-XYZ转换系数矩阵中的第二行的三个系数可以发现,就是不同色域空间下RGB-YUV中Y的转换系数公式。

CIE-xyY=>CIE-XYZ的转换通过:

CIE-Lab和CIE-LCH

在平时使用过程中,CIE-XYZ和CIE-xyY颜色模型并不能精确地表示所感知到的颜色。而且,在这些颜色模型中感知到的颜色和实际的颜色之间是存在差异的.具体的可以翻墙查看维基百科上的解释。大体可总结为:在1976年,CIE通过修改和重命名Yxy模型来纠正这些视觉扭曲,得到CIE L*a*b*模型,其中的颜色差异更接近于实际感知的颜色差异。一般的色差公式也是在CIE-Lch的空间上进行计算。

 该图是三维图的二维表示。该图是参考了很多文献,几乎都是圆柱形状,但是个人感觉应该是个正方体形状,这个应该是CIE-lch的。这个在之后介绍的sRGB的色域在CIE-Lab上的表示时,维基百科给出的是正方体形状

相同明度(L)的所有颜色,都是垂直在由a*和b*轴组成的同一个圆形平面上:

  • a*值正->红色,
  • a*值负->绿色,
  • b*值正->黄色,
  • b*值负->蓝色。

L的值域由0到100,L=50时,就相当于50%的黑;a和b的值域都是由+127至-128,其中+127 a就是洋红色,渐渐过渡到-128 a的时候就变成绿色;同样原理,+127 b是黄色,-128 b是蓝色。

CIE-Lch可以说是CIE-Lab的变形。

CIE-XYZ -> CIE-Lab 

可以使用如下公式:

 Xn,Yn,Zn是在XYZ上的白点位置,因此以色域表中的bt2020为例,当RGB=(1,1,1)即白色的时候:

X + Y + Z = [0.637 + 0.1146 + 0.1689 + 0.2627 + 0.678 + 0.0593 + 0 + 0.0281 + 1.061] = 3.0096

白点位置(x, y )=(0.3127,0.329)=> z = (1 - 0.3127 - 0.329) = 0.3583

所以 (Xn, Yn, Zn) = (0.3127,0.329,0.3583) * 3.0096 = (0.94110192,0.9901584,1.07833968)

在白点的位置此时Y = 0.2627 + 0.678 + 0.0593 = 1 。1/0.9901584 = 1.00993942。这里由于误差造成的,精确度比较高时应该等于1,但这里为了验证这个转换过程,就只按照上面给的数据来计算。 函数f(t),此时t=1.00993942, t的三分之一次方1.003302223,因此L = 116.383057905 - 16 = 100.383057905。

下面根据这个思路看一下BT709和BT2020下的红色在CIE-lab中L的位置

红色 = (1,0,0)

BT2020:红色时,X+Y+Z = 0.637 + 0.2627 = 0.8997,X = 0.637, Y =0.2627, Z = 0; 

白点位置:(Xn, Yn, Zn) = (0.3127,0.329,0.3583) * 3.0096 = (0.94110192,0.9901584,1.07833968)

L(红色) = 116×(0.2627/0.9901584)^1/3 - 16 = 58.5378

BT709:红色时 X+Y+Z =0.4124+0.2126+0.0193 = 0.6443, X = 0.4124, Y =0.2126, Z = 0.0193 

白点位置(Xn, Yn, Zn) = (0.3127,0.329,0.3583) * 3.0395 = (0.95045165,0.9999955,1.08905285)

L(红色)= 116X(0.2126/0.329)^1/3 - 16 = 84.2876

CIE-Lab  CIE-XYZ

 我们通常使用的bt2020或者bt709在这两个颜色模型中应该是什么形状呢,这里只给出了sRGB的形状,bt2020和bt709差不多很相似。

CIE-Lab<->CIE-Lch

其中的L表示的都一样

h表示着hue,c是chroma

以上公式和相关系数在bt2446上也能查询到。

形状

sRGB在CIE-LAB_color_space空间的形状

 sRGB在CIE-Lch_color_space的形状

 色域映射

在文章开头提到的bt202-bt709的转换过程中涉及到的色域映射,我们可能在bt2407这个建议书中给出的公式:

即bt2020-bt709的色域空间转换系数为:

1.6605, -0.5876, -0.0728
-0.1246, 1.1329, -0.0083
-0.0182, -0.1006, 1.1187

同样的可以得到709到2020的系数:

0.627, 0.329, 0.0433
0.0691, 0.92, 0.0113
0.0164, 0.088, 0.896

我们只看向下转换的公式是如何得来的,由RGB-XYZ颜色空间的转换系数可知,bt2407中的那个公式,由bt2020中某个像素点在XYZ中的位置是没有改变的,只是相对与bt709中的rgb的值改变了。例如在bt2020中红色(1,0,0)的值,在CIE-xyY中是(0.708,0.292),相对于bt709时的RGB为(1.66,-0.1246,-0.0182)。但是,在一个标准的色域空间下,rgb值的范围之0-1. 一个好的色域映射就是如何处理超出边界的值,处理后在709色域下颜色看起来和2020时尽量一致。bt2047上的方法很粗暴,直接采用clip的方式。在开头中这里引用的ffmpeg的色调映射zscale=p=bt709算法中,就是这个公式的计算步骤。ffmpeg在这之后就开始使用选择相应的色调映射方法。色调映射以亮度映射为目的,以hable为例子,最终映射系数是除以峰值亮度的,如果大于峰值亮度(1.0),在ffmpeg中会被clip。不过其hable本身在高亮度区域就会被压缩的很厉害,clip的带来的效应很减弱很多。但终归是大于bt709色域内的颜色是被压缩削峰的。

由上面的例子看出,目前ffmpeg中基于zscale的色调映射方法过程中的色域映射都很粗暴,因此好的色域映射方法是被忽略的一部分,好在也有很多人在研究这一方面,bt2407建议书中(延伸其他)在最后也给出了六个色域映射的方法。大部分都是在CIE-lab或CIE-Lch颜色空间上。

另外在github上该项目,对颜色做了大量的研究。可以作为参考,积累一下知识。很遗憾的该项目是基于日文的,看起来有些费劲。

  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值