在看這篇文章的時(shí)候,我們需要帶著幾個(gè)問題。
- 什么是YUV?
- 為什么視頻采集要用YUV而不用RGBA?
- RGB和YUV的區(qū)別以及關(guān)聯(lián)?
RGB(A)顏?編碼
三原色指色彩中不能再分解的三種基本顏色,我們通常說的三原色,是色彩三原色以及光學(xué)三原色。而光學(xué)三原色就指的是紅(R),綠(G),藍(lán)(B)。由RGB可以組成任何顏色。
在圖像顯示中,一張圖片可以分解成無數(shù)個(gè)像素點(diǎn)組成,而這個(gè)像素點(diǎn)就可以用RGB來表示。而A表示的透明度Alpha,通常來說在視頻的播放中透明度為1,所以我們這里不討論A。

如上圖所示,圖中的某個(gè)像素點(diǎn)是用RGB組成,假如一張圖片的尺寸為
1280 * 720,那么這個(gè)圖片的大小是多少呢?
RGB 圖像中,每個(gè)像素點(diǎn)都有紅、綠、藍(lán)三個(gè)原?,其中每種原?都占?8 bit,也就是?個(gè)字節(jié),那么?個(gè)像素點(diǎn)也就占? 24 bit,也就是三個(gè)字節(jié)。
那么這個(gè)圖片的小就是:
//圖片大小
1280 * 720 * 3 / 1024 / 1024 = 2.63 MB
竟然有2.63M,這還只是1幀,那么一個(gè)小時(shí)的電影,一秒有60幀沒,那么視頻將會(huì)占用無比巨大空間,所以用RGBA格式保存視頻是不可取的。
YUV顏色編碼
定義
YUV 顏?編碼采?的是 明亮度 和 ?度 來指定像素的顏?。其中,Y 表示明亮度(Luminance、Luma),? U 和 V 表示?度(Chrominance、Chroma)。??度?定義了顏?的兩個(gè)??:?調(diào)和飽和度。

和 RGB 表示圖像類似,每個(gè)像素點(diǎn)都包含 Y、U、V 分量。但是它的Y 和 UV 分量是可以分離的,如果沒有 UV 分量?樣可以顯示完整的圖像,只不過是??的。
4:4:4采樣格式
YUV 4:4:4采樣意味著 Y、U、V 三個(gè)分量的采樣?例相同,即每個(gè)像素點(diǎn)都會(huì)采樣Y、U、V分量

藍(lán)色的??代表Y分量,☆代表UV分量。
假如有A,B,C,D4個(gè)點(diǎn)像素為[Y0,U0,V0],[Y1,U1,V1],[Y2,U2,V2],[Y3,U3,V3]
那么最終還原的結(jié)果還是為[Y0,U0,V0],[Y1,U1,V1],[Y2,U2,V2],[Y3,U3,V3]
此時(shí)采樣的數(shù)據(jù)大小和RGB采樣方式的并沒有差別,所以我們一般不用4:4:4的采樣方式
4:2:2采樣格式
YUV 4:2:2 采樣,意味著 UV 分量是 Y 分量采樣的?半,Y 分量和 UV 分量按照 2 : 1 的?例采樣。如圖所示,假如一行有4個(gè)像素點(diǎn),那么Y分量則是4個(gè),而UV分量則是2個(gè),Y:UV = 2:1。

藍(lán)色的??代表Y分量,☆代表UV分量。
假如有A,B,C,D4個(gè)點(diǎn)像素為[Y0,U0,V0],[Y1,U1,V1],[Y2,U2,V2],[Y3,U3,V3]
那么按照YUV4:2:2 采樣的碼流為: Y0,U0,Y1,V1,Y2,U2,Y3,V3
那么最終還原的結(jié)果還是為[Y0,U0,V0],[Y1,U1,V1],[Y2,U2,V2],[Y3,U3,V3]
假如一張圖片的尺寸為1280 * 720,那么這個(gè)圖片的大小是多少呢?
//圖片大小
(1280 * 720 * 8 + 1280 * 720 * 0.5 * 8 * 2)/ 8 / 1024 / 1024 = 1.76 MB
可以看到比RGB采樣的方式節(jié)省了大約1/3的內(nèi)存,而且傳輸時(shí)的帶寬也能節(jié)省。
4:2:0采樣格式
YUV 4:2:0 采樣,并不是指只采樣 U 分量?不采樣 V 分量。?是指,在每??掃描時(shí),只掃描?種?度分量(U 或者 V),和 Y 分量按照 2 : 1 的?式采樣。?如,第??掃描時(shí),YU 按照 2 : 1 的?式采樣,那么第??掃描時(shí),YV 分量按照 2:1 的?式采樣。對于每個(gè)?度分量來說,它的?平?向和豎直?向的采樣和 Y 分量相?都是 2:1 。假設(shè)第??掃描了 U 分量,第??掃描了 V 分量,那么需要掃描兩?才能夠組成完整的 UV 分量。

如上圖所示,4:2:0的掃描方式,在第一行隔列掃描U點(diǎn),比如A點(diǎn)掃描U0,C點(diǎn)掃描U1點(diǎn);在第二行隔列掃描V點(diǎn),比如E點(diǎn)掃描V0,G點(diǎn)掃描V1點(diǎn)。所以ABEF點(diǎn)共用了U0、V0,CDGH共用了U1、V1。
假如原始像素點(diǎn)為[Y0 U0 V0],[Y1 U1 V1],[Y2 U2 V2],[Y3 U3 V3],[Y5 U5 V5],[Y6 U6 V6],[Y7 U7 V7],[Y8 U8 V8]
那么按照YUV4:2:2 采樣的碼流為: Y0,U0,Y1,Y2,U2,Y3,Y5,V5,Y6,Y7,V7,Y8
最后映射還原的像素點(diǎn)為: [Y0 U0 V5],[Y1 U0 V5],[Y2 U2 V7],[Y3 U2 V7],[Y5 U0 V5],[Y6 U0 V5],[Y7 U2 V7],[Y8 U2 V7]
假如一張圖片的尺寸為1280 * 720,那么這個(gè)圖片的大小是多少呢?
//圖片大小
(1280 * 720 * 8 + 1280 * 720 * 0.25 * 8 * 2)/ 8 / 1024 / 1024 = 1.32 MB
可以看到用4:2:0的方式,能節(jié)省更多的 內(nèi)存。
RGB與YUV之間的轉(zhuǎn)換
RGB 到 YUV 的轉(zhuǎn)換,就是將圖像所有像素點(diǎn)的 R、G、B 分量轉(zhuǎn)換到 Y、U、V 分量。
公式如下:
- RGB轉(zhuǎn)YUV
Y = 0.299 * R + 0.587 * G + 0.114 * B
U = -0.147 * R - 0.289 * G + 0.436 * B
V = 0.615 * R - 0.515 * G - 0.100 * B
- YUV轉(zhuǎn)RGB
R = Y + 1.14 * V
G = Y - 0.39 * U - 0.58 * V
B = Y + 2.03 * U
總結(jié)
通過實(shí)際的代碼,我們可以看到用YUV的編碼方式,從采集源頭做起,可以節(jié)省相當(dāng)可觀的內(nèi)存,這些節(jié)省的內(nèi)存不論是對存儲(chǔ)還是對傳輸都有相當(dāng)大的意義。