1. 程式人生 > >YUV格式分析詳解 轉

YUV格式分析詳解 轉

YUV格式分析詳解

 


一,YUV含義

     YUV格式通常有兩大類:打包(packed)格式和平面(planar)格式。前者將YUV分量存放在同一個陣列中,通常是幾個相鄰的畫素組成一個巨集畫素(macro-pixel);而後者使用三個陣列分開存放YUV三個分量,就像是一個三維平面一樣。

  在攝像頭之類程式設計經常是會碰到YUV格式,而非大家比較熟悉的RGB格式. 我們可以把YUV看成是一個RGB的變種來理解.

     如果只有Y訊號分量而沒有U、V分量,那麼這樣表示的影象就是黑白灰度影象。因此用YUV格式由彩色轉黑白訊號相當簡單. 在技術文件裡,YUV經常有另外的名字, YCbCr ,其中Y與YUV 中的Y含義一致,Cb , Cr 同樣都指色彩,,只是在表示方法上不同而已,Cb Cr 就是本來理論上的“分量/色差”的標識。C代表分量(是component的縮寫)Cr、Cb分別對應r(紅)、b(藍)分量訊號,Y除了g(綠)分量訊號,還疊加了亮度訊號。

     YUV的原理是把亮度與色度分離,研究證明,人眼對亮度的敏感超過色度。利用這個原理,可以把色度資訊減少一點,人眼也無法查覺這一點。YUV三個字母中,其中"Y"表示明亮度(Lumina nce或Luma),也就是灰階值;而"U"和"V"表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定畫素的顏色。用這個三個字母好象就是通道命令。
 

使用YUV的優點有兩個:
1,彩色YUV影象轉黑白YUV影象轉換非常簡單,這一特性用在於電視訊號上。
2,YUV是資料總尺寸小於RGB格式


二 幾大類YUV格式解析

•  4:4:4 表示色度頻道沒有下采樣。
•  4:2:2 表示 2:1 的水平下采樣,沒有垂直下采樣。對於每兩個 U 樣例或 V 樣例,每個掃描行都包含四個 Y 樣例。
•  4:2:0 表示 2:1 的水平下采樣,2:1 的垂直下采樣。
•  4:1:1 表示 4:1 的水平下采樣,沒有垂直下采樣。對於每個 U 樣例或 V 樣例,每個掃描行都包含四個 Y 樣例。與其他格式相比,4:1:1 取樣不太常用,本文不對其進行詳細討論。


取樣樣例:

圖片中使用的取樣網格。燈光樣例用叉來表示,色度樣例則用圈表示。  
圖 1 顯示了 4:4:4 圖片中使用的取樣網格。

圖 1. YUV 4:4:4 樣例位置


4:2:2 取樣的這種主要形式在 ITU-R Recommendation BT.601 中進行了定義。圖 2 顯示了此標準定義的取樣網格。

圖 2. YUV 4:2:2 樣例位置



4:2:0 取樣有兩種常見的變化形式。其中一種形式用於 MPEG-2 視訊,另一種形式用於 MPEG-1 以及 ITU-T recommendations H.261 和 H.263。圖 3 顯示了 MPEG-1 方案中使用的取樣網格,圖 4 顯示了 MPEG-2 方案中使用的取樣網格。


圖 3. YUV 4:2:0 樣例位置(MPEG-1 方案)



圖 4. YUV 4:2:0 樣例位置(MPEG-2 方案)






首先,您應該理解下列概念,這樣才能理解接下來的內容:
•  表面原點。對於本文講述的 YUV 格式,原點 (0,0) 總是位於表面的左上角。
•  跨距。表面的跨距,有時也稱為間距,指的是表面的寬度,以位元組數表示。對於一個表面原點位於左上角的表面來說,跨距總是正數。
•  對齊。表面的對齊是根據圖形顯示驅動程式的不同而定的。表面始終應該 DWORD 對齊,就是說,表面中的各個行肯定都是從 32 位 (DWORD) 邊界開始的。對齊可以大於 32 位,但具體取決於硬體的需求。
•  打包格式與平面格式。YUV 格式可以分為打包 格式和平面 格式。在打包格式中,Y、U 和 V 元件儲存在一個數組中。畫素被組織到了一些巨畫素組中,巨畫素組的佈局取決於格式。在平面格式中,Y、U 和 V 元件作為三個單獨的平面進行儲存。

YUV碼流的儲存格式其實與其取樣的方式密切相關,主流的取樣方式有三種, YUV4:4:4,YUV4:2:2 ,YUV4:2:0,關於其詳細原理,可以通過網上其它文章瞭解,這裡我想強調的是如何根據其取樣格式來從碼流中還原每個畫素點的 YUV值,因為只有正確地還原了每個畫素點的 YUV值,才能通過 YUV與 RGB的轉換公式提取出每個畫素點的 RGB值,然後顯示出來。

    用三個圖來直觀地表示採集的方式吧, 以黑點表示取樣該畫素點的 Y分量,以空心圓圈表示採用該畫素點的 UV分量。

  先記住下面這段話,以後提取每個畫素的 YUV分量會用到。

  1. YUV 4:4:4 取樣,每一個 Y對應一組UV分量。
  2. YUV 4:2:2 取樣,每兩個 Y共用一組UV分量。  
  3. YUV 4:2:0 取樣,每四個 Y共用一組UV分量。  


三,YUV格式與RGB格式的換算

RGB取值範圍均為0~255,Y=0~255,U=-122~+122,V=-157~+157
以下是經過簡化的公式,運算量比上述公式要小一些。

RGB轉YUV
Y = 0.299R + 0.587G + 0.114B
U'= (BY)*0.565
V'= (RY)*0.713

YUV轉RGB
R = Y + 1.403V'
G = Y - 0.344U' - 0.714V'
B = Y + 1.770U'



四.YUV的儲存格式---Packed(打包) / planar(平面)
 
    RGB格式中,一個24bpp畫素要佔用4位元組空間。在YUV格式中,可以對於UV分量的資料壓縮,但是對影象整體質量影響不大,這樣YUV所佔的空間就比RGB要小一些.不過RGB中 16bpp的 565格式每一個點只佔2個位元組,從這一點看也沒有省多少。不過視訊應用都是清一色的YUV應用。因此YUV的處理還是一個比較重要課題。

   YUV的儲存中與RGB格式最大不同在於,RGB格式每個點的資料是連繼儲存在一起的。即R,G,B是前後不間隔的儲存在2-4byte空間中。而YUV的資料中為了節約空間,U,V分量空間會減小。每一個點的Y分量獨立儲存,但連續幾個點的U,V分量是儲存在一起的.這幾個點合起來稱為macro-pixel, 這種儲存格式稱為Packed(打包)格式。
  另外一種儲存格式是把一幅影象中Y,U,V分別用三個獨立的陣列表示。這種模式稱為planar(平面)模式。此模式中,YUV檔案中YUV420又是怎麼儲存的呢? 在常見H264測試的YUV序列中,例如CIF影象大小的YUV序列(352*288),在檔案開始並沒有檔案頭,直接就是YUV資料,先存第一幀的Y資訊,長度為352*288個byte, 然後是第一幀U資訊長度是352*288/4個byte, 最後是第一幀的V資訊,長度是352*288/4個byte, 因此可以算出第一幀資料總長度是352*288*1.5,即152064個byte, 如果這個序列是300幀的話, 那麼序列總長度即為152064*300=44550KB,這也就是為什麼常見的300幀CIF序列總是44M的原因.

YUV420 Planar :




    YUV有packed format和planar format兩種。Packed format和planner format的區別在於,packed  format中的YUV是混合在一起的,因此就有了UYVY、YUYV等等,他們在碼流中排列的方式有所不同。而對於planner format每一個Y分量,U分量和V分量都是以獨立的平面組織的,也就是說所有的U分量都在Y分量之後出現,而V分量在所有的U分量之後。就像三個大色塊一樣。如下:




 

下面我用圖的形式給出常見的 YUV碼流的儲存方式 ,並在儲存方式後面附有取樣每個畫素點的 YUV資料的方法,其中 ,Cb、 Cr的含義等同於 U、 V。

(1 ) YUVY 格式 (屬於YUV422)

    YUYV為YUV422 取樣的儲存格式中的一種,相鄰的兩個 Y共用其相鄰的兩個 Cb、 Cr,分析,對於畫素點 Y'00、 Y'01 而言,其 Cb、 Cr的值均為 Cb00、 Cr00,其他的畫素點的 YUV取值依次類推。   (2) UYVY 格式 (屬於 YUV422)   UYVY格式也是YUV422 取樣的儲存格式中的一種 ,只不過與YUYV不同的是 UV的排列順序不一樣而已,還原其每個畫素點的 YUV值的方法與上面一樣。   (3) YUV422P(屬於YUV422)   YUV422P也屬於YUV422 的一種,它是一種 Plane模式,即平面模式,並不是將 YUV資料交錯儲存,而是先存放所有的 Y分量,然後儲存所有的 U( Cb)分量,最後儲存所有的 V( Cr)分量,如上圖所示。其每一個畫素點的 YUV值提取方法也是遵循 YUV422格式的最基本提取方法,即兩個 Y共用一個 UV。比如,對於畫素點 Y'00、 Y'01 而言,其 Cb、 Cr的值均為 Cb00、 Cr00。   (4) YV12,YU12 格式(屬於 YUV420)   YU12和 YV12屬於YUV420 格式,也是一種 Plane模式,將 Y、 U、 V分量分別打包,依次儲存。其每一個畫素點的 YUV資料提取遵循 YUV420格式的提取方式,即4個 Y分量共用一組 UV。注意,上圖中, Y'00、 Y'01、 Y'10、 Y'11共用 Cr00、 Cb00,其他依次類推。   (5)NV12、NV21(屬於YUV420)

   NV12和NV21屬於YUV420格式,是一種two-plane模式,即Y和UV分為兩個Plane,但是UV(CbCr)為交錯儲存,而不是分為三個plane。其提取方式與上一種類似,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00 YUV420 planar資料.    以720×488大小圖象YUV420 planar為例,其儲存格式是: 共大小為(720×480×3>>1)位元組,分為三個部分:Y,U和V
Y分量    :(720×480)個位元組   U(Cb)分量:(720×480>>2)個位元組
V(Cr)分量:(720×480>>2)個位元組
三個部分內部均是行優先儲存,三個部分之間是Y,U,V 順序儲存。
即YUV資料的0-720×480位元組是Y分量值, 720×480-720×480×5/4位元組是U分量, 720×480×5/4-720×480×3/2位元組是V分量。


4 :2: 2 和4:2:0 轉換:
最簡單的方式:
YUV4:2:2 ---> YUV4:2:0  Y不變,將U和V訊號值在行(垂直方向)在進行一次隔行抽樣。  YUV4:2:0 ---> YUV4:2:2  Y不變,將U和V訊號值的每一行分別拷貝一份形成連續兩行資料。

在YUV420中,一個畫素點對應一個Y,一個4X4的小方塊對應一個U和V。對於所有YUV420影象,它們的Y值排列是完全相同的,因為只有Y的影象就是灰度影象。YUV420sp與YUV420p的資料格式它們的UV排列在原理上是完全不同的。420p它是先把U存放完後,再存放V,也就是說UV它們是連續的。而420sp它是UV、UV這樣交替存放的。(見下圖) 有了上面的理論,我就可以準確的計算出一個YUV420在記憶體中存放的大小。 width * hight =Y(總和) U = Y / 4   V = Y / 4


所以YUV420 資料在記憶體中的長度是 width * hight * 3 / 2,
假設一個解析度為8X4的YUV影象,它們的格式如下圖:
YUV420sp格式如下圖
            YUV420p資料格式如下圖
  
旋轉90度的演算法:
public static void rotateYUV240SP(byte[] src,byte[] des,int width,int height)
{
    
  int wh = width * height;
  //旋轉Y
  int k = 0;
  for(int i=0;i<width;i++) {
   for(int j=0;j<height;j++) 
   {
               des[k] = src[width*j + i];   
         k++;
   }
  }
  
  for(int i=0;i<width;i+=2) {
   for(int j=0;j<height/2;j++) 
   { 
               des[k] = src[wh+ width*j + i]; 
               des[k+1]=src[wh + width*j + i+1];
         k+=2;
   }
  }
  
  
}

YV12和I420的區別    
     一般來說,直接採集到的視訊資料是RGB24的格式,RGB24一幀的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,如果是I420(即YUV標準格式4:2:0)的資料量是 size=width×heigth×1.5 Bit。           在採集到RGB24資料後,需要對這個格式的資料進行第一次壓縮。即將影象的顏色空間由RGB2YUV。因為,X264在進行編碼的時候需要標準的YUV(4:2:0)。但是這裡需要注意的是,雖然YV12也是(4:2:0),但是YV12和I420的卻是不同的,在儲存空間上面有些區別。如下: 
YV12 : 亮度(行×列) + U(行×列/4) + V(行×列/4)
I420 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
可以看出,YV12和I420基本上是一樣的,就是UV的順序不同。
繼續我們的話題,經過第一次資料壓縮後RGB24->YUV(I420)。這樣,資料量將減少一半,為什麼呢?呵呵,這個就太基礎了,我就不多寫了。同樣,如果是RGB24->YUV(YV12),也是減少一半。但是,雖然都是一半,如果是YV12的話效果就有很大損失。然後,經過X264編碼後,資料量將大大減少。將編碼後的資料打包,通過RTP實時傳送。到達目的地後,將資料取出,進行解碼。完成解碼後,資料仍然是YUV格式的,所以,還需要一次轉換,這樣windows的驅動才可以處理,就是YUV2RGB24。
YUY2  是 4:2:2  [Y0 U0 Y1 V0]

yuv420p 和 YUV420的區別 在儲存格式上有區別
yuv420p:yyyyyyyy uuuuuuuu vvvvv 
yuv420 :yuv yuv yuv
       YUV420P,Y,U,V三個分量都是平面格式,分為I420和YV12。I420格式和YV12格式的不同處在U平面和V平面的位置不同。在I420格式中,U平面緊跟在Y平面之後,然後才是V平面(即:YUV);但YV12則是相反(即:YVU)。
YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12與NV21類似,U 和 V 交錯排列,不同在於UV順序。
I420: YYYYYYYY UU VV    =>YUV420P
YV12: YYYYYYYY VV UU    =>YUV420P
NV12: YYYYYYYY UVUV     =>YUV420SP
NV21: YYYYYYYY VUVU     =>YUV420SP       
五, 取樣格式說明
   表示YUV格式,一般用Y,U,V三者的比率來表示不同格式,比如YUV444 表示三者是比值此是 4:4:4
   即一個點資料點,Y,U,V的空間都是一樣大小。目前主要有如下比例,注意所有格式中Y比值都是4,佔一個位元組,表示沒有減少採樣。不同格式中,減小隻是UV的取樣值.

• 4:4:4  表示色度值(UV)沒有減少採樣。即Y,U,V各佔一個位元組,加上Alpha通道一個位元組,總共佔4位元組.這個格式其實就是24bpp的RGB格式了。
• 4:2:2  表示UV分量取樣減半,比如第一個畫素取樣Y,U,第二個畫素取樣Y,V,依次類推,這樣每個點佔用2個位元組.二個畫素組成一個巨集畫素.  
• 4:2:0  這種取樣並不意味著只有Y,Cb而沒有Cr分量,這裡的0說的U,V分量隔行才取樣一次。比如第一行取樣 4:2:0 ,第二行取樣 4:0:2 ,依次類推...在這種取樣方式下,每一個畫素佔用16bits或10bits空間.
• 4:1:1  可以參考4:2:2分量,是進一步壓縮,每隔四個點才採一次U和V分量。一般是第0點採Y,U,第1點採Y,第3點採YV,第四點採Y,依次類推。
除了4:4:4取樣,其餘取樣後訊號重新還原顯示後,會丟失部分UV資料,只能用相臨的資料補齊,但人眼對UV不敏感,因此總體感覺損失不大。

4:2:2示例
原來四個畫素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的碼流為:    Y0 U0      Y1    V1   Y2 U2      Y3    V3
映射出畫素點為:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]

4:1:1示例
原來四個畫素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的碼流為:    Y0 U0    , Y1      ,  Y2    V2 , Y3
還原出畫素點為:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]

4:2:0示例
八個畫素    : [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y5 U5 V5] [Y6 U6 V6] [Y7 U7 V7] [Y8 U8 V8]
存放的碼流為:  Y0 U0   ,  Y1,        Y2 U2,     Y3 ,       Y5 V5,     Y6,        Y7 V7,     Y8
映射出畫素點: [Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7] [Y5 U0 V5] [Y6 U0 V5] [Y7 U2 V7] [Y8 U2 V7]
4:2:0並不意味著只有Y,Cb而沒有Cr分量。它指得是對每行掃描線來說,只有一種色度分量以2:1的抽樣率儲存。相鄰的掃描行儲存不同的色度分量,也就是說,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。