一.YUV簡介
YUV編碼採用明亮度和色度表示每個像素的顏色,Y表示亮度,UV表示色度,一個Y是1個字節,就是一個黑白像素,UV可以是多個Y共享。
YUV採樣的格式有很多,每種格式按存儲方式又還有比較細的區分,如YUV4:4:4,YUV 4:2:0,YUV 4:0:2,其中最常用的就是YUV420,而YUV420按存儲的方式又可以分爲YU12、YU21、NV12、NV21。
我們只需要看YUV420就行了,其中NV12和NV21是ios和安卓攝像頭的採樣格式,它們都是先存儲所有的Y分量,區別在於NV12是UV交替存儲,而NV21是VU交替存儲。
二.爲什麼需要YUV這種格式?
最最最重要的還是減少帶寬佔用。
如果是RGB,一張1280*720的圖片佔用大小:
1280 * 720 * 3 / 1024 / 1024 ≈ 2.64M
如果是YUV420格式,同樣大小的圖片只佔:
(1280 * 720 * 1 + 1280 * 720 * 0.5) / 1024 / 1024 ≈ 1.32M
是RGB大小的一半。
以前YUV格式作爲黑白電視和彩色電視的過渡,是非常好的辦法。
如果是黑白電視,因爲Y和UV是分離的,這樣黑白電視就可以只取出Y分量去播放了。
而彩色電視拿到YUV數據後,也要把YUV先轉換成RGB數據才能顯示圖像。
爲什麼要這麼做呢?如果採集到RGB數據,黑白電視直接作個灰度變換也是可以的。
我理解最關鍵的還是在省帶寬,畢竟現在還是以前帶寬都不便宜。
而且這裏還有個要點,如果RGB像素是我們希望看到的彩色圖像,而原始的YUV像素其實是被"壓縮"過的,而且是有損壓縮。相當於攝像頭採集到了YUV數據,而到顯示的時候轉換成RGB其實像素是被"放大"的(像上面舉例,圖片大小會變爲原來兩倍)。
這麼做難道不會讓畫面失真?這裏就要說到人類的視網膜了。
人類對顏色的感知程度低於對亮度的感知度,這是由人類的視網膜細胞決定的。視網膜主要包含視網膜杆細胞進和視網膜錐細胞,杆細胞的作用是識別亮度,錐細胞的作用是識別色度,而杆細胞的數量又多於錐細胞。
所以即便是YUV格式轉換過來的RGB像素,人類的眼睛也無法察覺,這也是現在攝像頭芯片採集到的數據都用YUV編碼的一個原因。
三.YUV的像素表示
上面說到採樣格式可以有多種:YUV4:4:4,YUV 4:2:2,YUV 4:2:0,用下面的圖可以直觀地表示,一個黑點是一個Y分量,白色圓圈是一組UV分量(一組UV分量包含U和V,佔2個字節):
所以爲什麼說YUV420是最主要的採樣格式,因爲**YUV家族裏它是最省帶寬的格式之一!**YUV444一個像素點和RGB一樣也佔3個字節,而YUV422是1個像素點佔用2個字節,YUV420是1個像素點佔用1.5個字節。
絕大部分場景使用YUV420足夠,因爲肉眼無法分辨,而YUV444那些是適合高分辨率採樣的場景。
說完採樣格式,我們再來說下存儲的格式。
YUV按存儲格式分有兩大類:planar和packed,平面式和壓縮式。
planar是先連續存儲所有像素點的Y,然後再存儲所有像素點的U,最後是存儲所有像素點的V。
packed是每個像素點的Y,U,V是連續交替存儲的,就像RGB。
packed更多用在YUV444這種,完全採樣的,planar更多用在YUV422、YUV420這種,也是方便一些黑白電視直接用Y分量。
我們用兩張圖來看下:
YV12,YU12格式(屬於YUV420)
先存儲所有的Y分量,再存儲Cr(V),最後是Cb(U),Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00,其他依次類推。
NV12、NV21(屬於YUV420)
也是先存儲所有的Y分量,但UV(CbCr)是交錯存儲,Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00,其他依次類推。