常見顏色空間
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)
202410157.png
兩個Y共用相鄰的UV(CbCr),即Y00和Y01兩個點都是使用Cb00 Cr00,往后依次類推。 - UYVY
202455202.png
相比YUYV排列順序換了一下。 - YUV422p
3.png
這里p的意思是planar的意思,不是像上面的交錯存儲,而是先存所有的Y,然后是U,然后是V,使用方法和422相同。 - YUV420p & YV12
yuv420p.png
YUV420p是一種plane模式,也叫I420,遵循420的提取方式,Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00。YV12同YUV420p一樣,不過UV是反的。 - NV12
nv12.png
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的大概是這樣樣子的:
yuv420p mem.png
即:
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