常见颜色空间
color model & color space
我们每天说的RGB,这个称呼严格来讲应该归属于color model,而不是color space。这里我们区分一下color model和color space。
- color model色彩模型是指一个抽象的数学模型,用来描述一个颜色怎么样被表达成一组数字,通常来讲会用3个或者4个数值来表示。
- color space当色彩模型有了对组成元素数值具体的表述方式和规则的时候,也就是把色彩模型具体规定到了一个颜色的集合,这个集合有着具体的表示方式和计算方式的时候,这就叫color space了。
对比一下概念,color space是具体化了的color model,可以被用来表达一个颜色。也就是需要指定具体的颜色表述方式。我们常见的色彩模型有CIE系列、RGB、CMYK、HSV/HSL、YUV都算是色彩模型。我们最常见的RGB color model中又包含sRGB、AdobeRGB、Apple RGB、ProPhoto RGB、ScRGB等。上面一章中讲的CIE系列这里归为moel,它是与设备无关的,包括CIE RGB XYZ Lab等,CIE是个很特殊的存在,它们都是从人眼原理经过实验得到的色彩空间,
比如拿CIE XYZ来说,一方面它们有primary colors,有一定的规则和表述方式,但是另一方面它们的primary colors(可以将上面图中的Cr Cg Cb变换后的值作为他的primary colors)又不是真实存在的,这里所以吧CIE系列单独归为一类color model,在第二章中已经具体讲了几个主要的CIE标准,这里就不再补充了。另外,CIE XYZ通常是其他color space的参考。比如,我们最常见的sRGB颜色空间RGB对应CIE XYZ参考的定义如下:
RGB
如上所述,单纯讲RGB是addtive color model,它根据三原色原理规定了一个坐标轴分别代表RGB的立方体数学模型,它是最常见的色彩模型,但是其实并不友好,鬼知道给你一组RGB混合出来是什么样子,除了纯色,我现在连双色等比例混合的公式都没背下来。这个color model中包含很多color spaces,这些color spaces之间的区别是它们的primary colors不同,像上面说的sRGB的(0,255,0)绿色对应的CIE xyY标准中的色域图中颜色是(0.30,0.60),但是AdobeRGB中为(0.21,0.71)。注意,色彩空间的标准文档中一半找不到具体的Y的值,是因为通过Y值代表色彩的亮度,与色彩空间所默认遵循的Standard illuminant有关,标准照明的规则(常见的如D65和D60)中会指明white的xy值(一般来说也是只给出在CIE XYZ色域图中的xy色度值,Y规则化到1.0),也就是说大多数的色彩空间primary colors的定义都是只给出RGB的xy和white的xy,然后自己需要计算出来对应的真实颜色的XYZ的值,步骤基本包括计算white的Y、计算RGB unadapted XYZ矩阵并求逆、矩阵相乘得到adapted RGB的Y值、计算RGB XYZ值,具体的例子见sRGB色彩空间XYZ值计算方式,最后面稍微改改就能算出来sRGB和XYZ之间的转换矩阵。下图给出来了。这里我们发现从XYZ到sRGB的时候矩阵中有负值出现,看一下下面的sRGb的色域图,它其实只有很小的一个色域范围,负值意味着是在三角形外部的,这种出现负值的RGB最简单的方式就是归一化到0-1之间,也就是三角形外面的颜色简单的直接用三角形边界上的值表示。从计算出来的值需要写到图像到描述中,如jpeg的icc profile中的PCS。例如,标准照明D65定义的white point为xy(0.31271,0.32902),关于照明标准还很复杂,大分类ABCDEFL,别问我为什么没有GHIJK,这里ABCDEFL不是按的字母序取的名字,而是都有一定的含义,如A是什么钨丝光源,B是noon sunlight,D是natural daylight,L是LED,另外照明标准还有什么standard observer的因素会影响white的定义,刚刚说的值是standard 2 degree obserer。
sRGB
sRGB由微软和惠普1996年提出的色彩空间标准,一般用于显示器、打印机和网络,这也基本是我们最常见的色彩空间,广泛应用于我们通常说的RGB也基本(default color space)是建立在sRGB上的。我们见到的图片基本都使用的sRGB。sRGB为了适应更多的设备,色域很小,基本是色彩空间中色域最小的了,甚至都不能包含打印用的CMYK空间。
提到sRGB不得不提到一个国际电信联盟ITU-R推荐的色彩标准Rec.709,也就是视频领域经常看到的bt709,它是在1990年为了HDTV高清电视提出来的,但是sRGB也使用了Rec709标准的一部分。对应的还有一个bt601,是用在标清电视SDTV上的。BT709中定义了编码和transfermation coefficients,在bt601中只定义了encoding相关的东西。
sRGB在primary colors使用和bt709一致,使用的照明也相同都是D65,也就是说sRGB和bt709的色域是相同的。它们的不同主要在transfer function上,sRGB和bt709的transfer function都是一个分段函数,在特别小的范围内是一段线性函数,剩下的是指数函数,前半截是直线的原因是防止取全局的平均下来sRGB的decoding gamma为2.2,bt709的transfer gamma为1.96左右。
至于为什么要有gamma这东西的存在,有很多的历史原因,也有很多的物理设备和人的感知的原因,简单来说就是1,历史中大量使用了CRT显示器,由于电压和显示非线性会偏暗,2,物理设备的采集中高亮区域色阶过剩,暗部色阶不够用,3,人眼也对亮度其实也是非线性的,具体见最后一章讲解gamma correction。采集设备在编码的时候会根据gamma值(encoding gamma,通常小于1,sRGB 1/2.2,bt709 1/1.96),进行非线性映射,在decoding进行显示的时候用gamma值校正,将图像压暗。
一个真实在XYZ表示的真实颜色进行encode的过程,首先要映射为sRGB颜色,经过计算,映射矩阵如下图中的表示,然后进行gamma映射,decoding的时候过程相反。
bt709是一个很丰富的标准,除了primary color、D65规定了色域、给出了transfer function以外,还包含了对HDTV中pixel count规定了分辨率1080p/1080i,frame rate规定了60 Hz, 50 Hz, 30 Hz, 25 Hz and 24 Hz,digital representation规定了两种编码方式R'G'B'和Y'CbCr,使用8bits或10bits编码。
AdobeRGB
由Adobe这个lazy company于1998年提出,提出的主要目的是为了解决sRGB不能覆盖CMYK的问题,也就是为了在显示器使用RGB原色model看到打印需要的全色域,主要是在蓝绿色方向进行了扩展,完全覆盖sRGB,基本覆盖CMYK。
Apple RGB
早期的苹果产品,目前已转向sRGB。
prophoto RGB
由柯达提出的参考color space,它的RGB原色定义已经超出了visible color范围,基本包含了90%的CIE LAB色域,主要都是为了专业处理考虑的。
scRGB
微软和HP脑洞的产物,色域非常大,RGB原色允许负值,基本包含了所有的CIE color space色域,而且与sRGB兼容,不过用起来好像不太方便。
CMYK
C青M洋红Y黄,注意这里K严格来讲并不是指Black,而是单词Key,是指Key color,因为实际条件下用CMY很难混合出来纯粹的深灰或者黑色,那么加了一个K,这个K一般就是黑色。主要用于印刷行业,相比于RGB model的addtive model,CMYK是减性模型,说白了就是越混合颜色越黑。CMYK与RGB有一定的对应关系,CMY非别是BRG的补色,比如30%C其实是70%的B。
HSL & HSV
HSL和HSV(也叫HSB)是对人很友好的色彩空间,因为给你说了每个值,脑海中就能想象出来颜色的基本的样子。两个都对RGB modol来讲都可以看成是圆柱坐标系表示。这里H都是Hue色相,通常的取值范围是0-360度,S都是saturation饱和度,L是亮度,V是明度。另外它们对饱和度、亮度的拆分比例不同。L这里是值Lightness/Luminance,叫亮度,V和B代表Value和Brightness,叫明度。L是指从最暗的的黑色到色相纯色再到白色,也就是说在最大L的时候,不光H是多少,都是白色。V是从黑色到标准色相,明度最大的时候是就是纯色H,只有在S最小的时候才是白色。也就是HSL中轴是代表黑到白的灰色,HSV中轴是白色。PhotoShop中的拾色器是HSL模型,色相/饱和度命令用的是HSV。
下面是LV的对比:
YUV family
YUV models
YUV最初的目的是为了将Y亮度和色彩分开,Y在这里是指Luminance亮度,UV是指色彩。YUV是为了电视机和媒体产生的,最早的时候为了使得彩色电视机和黑白电视机兼容,Y可以单独传输。这里Y也是说了是Luminance是指视觉亮度,而不是Luma,还是与HSL不太相同,HSL更加的偏重颜色本身的特性,而YUV中Y调制的比例更符合人眼,这与XYZ模型基本保持一致,名字也直接沿用过来了。YUV严格来说这个称呼更多的是指color model,而不是color space。下面的图中Blue和Green在HSL和HSV中亮度是相同的,但是在YUV中(更确切的说是在Y'CbCr中)RGB纯色的亮度比例为0.299:0.587:0.114。
在视频领域中,其实我们说的YUV严格来讲是叫Y'UV,这里Y'是指经过gamma校正后的值,因为我们的视频都有gamma校正的存在。只不过默认值是2.2(Bt 709的transfer为1.96)。另外,我们常见的Y'CbCr是为了数字信号表示出现的,色彩表示上相比YUV的向RB有一定的偏移,是为了各种压缩来做的,比如视频、图片基本都是Y'CbCr来进行压缩的。对比一下Y'UV主要是用于传统模拟电视,而Y'CbCr用于数字电视。总之,我们现在大多数讲的YUV,基本是指Y'CbCr。
说多一点,咱们原来老电视上分PAL模式、NTSC模式、SECAM模式,这些模式就是就决定了采用哪种色彩模型,PAL和SECAM基于Y'UV,NTSC基于Y'IQ。Y'IQ和Y'UV基本一样,就不介绍了。
到这里我们再说一下Bt601和Bt709的问题,bt601用在SDTV和jpeg(有一部分老标准使用的是bt601)中,也就是Y'CbCr(后面我还是直接称为YUV吧)在使用的时候需要指定color space。bt601计算出来的RGB转YUV matrix如下:
虽然它们的transfer function 相同(即gamma约定相同),工作中对于视频转码时要注意所用的color space的问题,从bt601和709互转的时候可能出现颜色不一致的问题。
YUV数据格式PixFmt
YUV格式从YUV分量的存放位置分为两大类,planar和packed,planar模式是指一幅图像的YUV分别用三个独立的数组表示,pakced是指连续交错存储YUV分量。YUV实际应用中有三种主要的采样方式,YUV 444 422 411 420 420p。444就是只每个像素3个字节,422每两个Y取一对UV分量,也就是每两个像素4四个字节,411就是每4个Y一对UV分量,也就是4个像素6个字节,420并不是指缺了一个U或者V,而是指UV分量隔行采样一次。
这里就拿YUV422举个例子说一下存储方式:
- YUY2 (不叫YUYV)
两个Y共用相邻的UV(CbCr),即Y00和Y01两个点都是使用Cb00 Cr00,往后依次类推。 - UYVY
相比YUYV排列顺序换了一下。 - YUV422p
这里p的意思是planar的意思,不是像上面的交错存储,而是先存所有的Y,然后是U,然后是V,使用方法和422相同。 - YUV420p & YV12
YUV420p是一种plane模式,也叫I420,遵循420的提取方式,Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00。YV12同YUV420p一样,不过UV是反的。 - NV12
NV12和NV21也都是YUV420的一种,不过不像YUV420p有三个plane分别存放YUV,只有两个plane,UV交错存放。
比如一个6404803的图像,要存储成YUV420p,那么总大小需要6404801.5=460800字节,相比444节省了一半空间。三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。即YUV数据的0--640×480字节是Y分量值,640×480--640×480×5/4字节是U分量,640×480×5/4 --640×480×3/2字节是V分量。
实际存储是按行存储的,那么YUV420p的大概是这样样子的:
即:
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP
更多:有时候我们见到的视频虽然大多是YUV420p或者YUV420sp,但是有时候也会遇到YUVj420p,这里讲一下yuvj420p。
YUV420P vs. YUVJ420P
简单来看,两个格式的唯一区别就是YUV420P的色彩值范围是[16, 235],而YUVJ420P是[0,255]。有些硬件设备包括一些手机硬编码出来的可能是YUVJ420P。Numerical approximations中说明了一下为什么是[16,235],大致是说由于处理为了加速很多运算的最后几位精度会被丢弃,在丢弃以后由于color space转换的问题,加上中间的gamma校正问题,以及显示问题可能会出现负数,产生invalid RGB,所以这里BT709就加了个[16,235]的限制。而且恰好1-15可以用来传输负脉冲信号,236-254传输过冲信号,0和255用来同步脉冲(写完这些我都太没看懂……)
gamma correction
单独简单讲一下gamma校正吧。为什么有gamma校正的存在,众说纷纭,主要是有下面几个原因:
- 老的CRT显示器自带2.2的gamma,end to end 1
- 人眼对暗部细节更敏感,对亮度感知不均匀,0.2左右的反射率产生的灰认为是中灰,灰阶紧张,充分利用编码空间,人其实对他的感受也是非线性的
- 后来干脆微软和Hp推出sRGB标准,定义了2.2,也是很多显示器使用的
- 相机其实是为了模仿人眼
我更支持2的说法,人眼感受亮度的非线性问题,由于目前我们大多数表示方式都是8bits的,这就严重限制了能表示的色阶,但是人眼又是非线性的,即对于高亮度的范围内,人眼的分辨能力要比暗部的时候差一些,我们从黑色到白色画一个均匀的变化图如下:
第一张图所示,我们想要的中灰色其实位于0.2左右的位置,这么对于高亮分配到的色阶太多就浪费了,暗部人眼明明更敏感,单分配到的色阶很少。假如我们直接按线性的方式定义色阶,那么暗部的很多细节注定要在量化的时候很丢掉,导致暗部细节丢失严重。为了解决这个问题,我们就需要想要的中灰色实际表示成0.5,恰好着对应了一个2.2左右的gamma变换:
依据这个gamma变化用在相机的采样中,即采样的时候执行1/2.2左右的gamma变化,提升暗部色阶,整个图像会变亮,我们就可以得到更多的暗部细节,保留更多细节。
有了gamma变化以后,是很方便了,显示器也定义了自己的display gamma(sRGB即显示器遵循的)大概在2.2左右,恰好能还原采样的时候的gamma变换。但是也引来很多的新问题,下面说两个。
-
gamma meta信息的不同应用解释不一致问题
这有个很有意思的图片,它的gamma值为0.02,在safari中我们看到的是一个apple,但是在chrome中看到的是一个pear,很奇妙吧。其实就是利用了不同应用对图片的gamma值的处理不同,safri中解释了gamma值,看起来是个apple(存储在高亮范围内,gamma变化会把高亮压低,看到apple,会把pear压到看不清楚),而chrome忽视了gamma值,所以我们只能看到正常范围内的亮度值表示的东西,是个pear(存储在正常灰度范围内)。 -
对实际应用的RGB带来坑爹的问题
youtube上有个有意思的视频,说的是在我们使用instagram和ps的时候,如果我们画了一个红色和绿色,相互接触,我们想要在中间加个模糊效果,一般来说大多数软件的做法是取两边颜色的平均值。但是我们发现这么做以后中间会出现灰色的间隔(中间那个图),而不是我们想要的RG混合的黄色(最后那个图)!这其实是因为我们处理的红色和绿色的色值都是做过gamma变换以后的值,举个例子吧,如果我们的gamma值取0.5,那么encoding gamma就是一个开方操作,decoding gamma是一个平方操作,软件取平均是对开方以后的值进行的变化(gamma变换后的值),但是这么做并不是我们想要的对实际颜色取平均的目的!根据下面的公式,这样得到的值是小于我们要的目标值的。所以正确的做法是先做一遍gamma display,得到值以后取平均,然后在encoding gamma变换以下,为了最后的显示!
对于我们采集的图像和pc自己制作的图像是不一样的,我们采集的图像已经做过gamma变化了,但是我们自己制作的图像并没有,所有软件在display的时候会又一个buffer来做gamma变换,为了预览展示:
The processing Flow
总结一下,从物理图像到我们的显示设备的整理流程:
FFMPEG相关
AVPixelFormat
AVColorPrimaries
AVColorTransferCharacteristic
AVColorSpace
AVColorRange
其他
color space转换
基本灰度变换
color correction
References:
- wikipedia color space
- wikipedia color primary
- csdn blog: color space
- a bt709 story, to Bt2020
- YUV
- BT709
- difference between YUV YCbcr
- a color matrix discuss
- gamma correction
- Rec709 vs sRGB
- Color correction handbook
- HDR
- LUT
- Color wiki
- color vision
- color space CIE 1931
- primary color
- RGB color space
- rg chromaticity
- color model
- color space
- difference between color model and space disscus
- UI 设计知识库
- RGB color spaces在xyY中的参考值表
- Standard illuminant
- sRGB xyY RGB & white compute
- icc profile
- sRGB
- sRGB vs BT709
- 知乎一篇gamma讲解
- gamma correction wikipedia
- A good gamma correction blog
- Adobe RGB
- 明度、亮度、辉度
- Luma & Luminance
- YUV
- where is purple
- yuv 420 csdn blog
- chroma subsampling
- 雷神 yuv420p
- why yuv420p 16-235
- 8bit vs. 10bit video sample youtube
- thought of 42 comparision video
- What makes a good display
- HDR wiki
- 知乎 色彩空间的表示与转换
- 知乎 色温与白平衡
- bt 601 & bt 709 matrix