YUV和RGB格式分析


  做嵌入式項目的時候,涉及到YUV視頻格式到RGB圖像的轉換,雖然之前有接觸到RGB到都是基於opencv的處理,很多東西並不需要我們過多深入的去探討,現在需要完全拋棄現有的算法程序,需要從內存中一個字節一個字節的處理,這就涉及到各個視頻格式和圖片格式是如何存儲的。看了網上的很多資料,一下資料幫助蠻大。

YUV資料整理:

http://www.fourcc.org/yuv.php    YUV和RGB的分析

http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html  對YUV的分析

http://ticktick.blog.51cto.com/823160/568928  顯示YUV數據

http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html

 YUV

  做視頻采集與處理,自然少不了要學會分析YUV數據。因為從采集的角度來說,一般的視頻采集芯片輸出的碼流一般都是YUV數據流的形式,而從視頻處理(例如H.264、MPEG視頻編解碼)的角度來說,也是在原始YUV碼流進行編碼和解析,所以,了解如何分析YUV數據流對於做視頻領域的人而言,至關重要。YUV是指亮度參量和色度參量分開表示的像素格式,而這樣分開的好處就是不但可以避免相互干擾,還可以降低色度的采樣率而不會對圖像質量影響太大。

      人眼對色度的敏感程度要低於對亮度的敏感程度。

      YUV,分為三個分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定像素的顏色。與我們熟知的RGB類似,YUV也是一種顏色編碼方法,主要用於電視系統以及模擬視頻領域,它將亮度信息(Y)與色彩信息(UV)分離,沒有UV信息一樣可以顯示完整的圖像,只不過是黑白的,這樣的設計很好地解決了彩色電視機與黑白電視的兼容問題。並且,YUV不像RGB那樣要求三個獨立的視頻信號同時傳輸,所以用YUV方式傳送占用極少的頻寬。

      YUV碼流有多種不同的格式,要分析YUV碼流,就必須搞清楚你面對的到底是哪一種格式,並且必須搞清楚這種格式的YUV采樣和分布情況。

  YUV格式有兩大類:planar和packed。
  對於planar的YUV格式,先連續存儲所有像素點的Y,緊接着存儲所有像素點的U,隨后是所有像素點的V。
  對於packed的YUV格式,每個像素點的Y,U,V是連續交叉存儲的。

1.  采樣方式   

    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分量,每像素32位

  2. YUV 4:2:2采樣,每兩個Y共用一組UV分量,每像素16位

  3. YUV 4:2:0采樣,每四個Y共用一組UV分量,每像素16位 

平常所講的YUV A:B:C的意思一般是指基於4個象素來講,其中Y采樣了A次,U采樣了B次,V采樣了C次. 

YUV 格式可以分為打包格式packed format和平面格式planar format。打包格式將YUV分量存放在同一個數組中,通常是幾個相鄰的像素組成一個宏像素(macro-pixel);而平面格使用三個數組分開存放YUV三個分量,就像是一個三維平面一樣。Packed format和planner format的區別在於,packed format中的YUV是混合在一起的,因此就有了UYVY、YUYV等等,他們在碼流中排列的方式有所不同。而對於planner format每一個Y分量,U分量和V分量都是以獨立的平面組織的,也就是說所有的U分量都在Y分量之后出現,而V分量在所有的U分量之后。就像三個大色塊一樣。

2.  存儲方式

    下面用圖的形式給出常見的YUV碼流的存儲方式,並在存儲方式后面附有取樣每個像素點的YUV數據的方法,其中,Cb、Cr的含義等同於U、V。因為我們在實驗中芷使用到YUV422的格式,這里只介紹這個,其他的可以去其他博文了找。

(1) YUYV 格式 (屬於YUV422)

YUYV(YUY2)為YUV422采樣的存儲格式中的一種,相鄰的兩個Y共用其相鄰的兩個Cb(U)、Cr(V),分析,對於像素點Y'00、Y'01 而言,其Cb、Cr的值均為 Cb00、Cr00,其他的像素點的YUV取值依次類推。YVYU(YVY2)也一樣,只是UV的位置調換了一下,先V后U。

(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。

以YUV420 planar數據為例, 以720×480大小圖象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分量。

這里Y分量其實就是我們常說的灰度值,所以需要對圖片進行灰度處理的話,可以直接提取出圖片的Y分量。這點對我們后面的處理很重要。

YUV4:4:4  

下面的四個像素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]

存放的碼流為: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3

映射出像素點保持原樣

YUV4:2:2

每個色差信道的抽樣率是亮度信道的一半,所以水平方向的色度抽樣率只是4:4:4的一半。對非壓縮的8比特量化的圖像來說,每個由兩個水平方向相鄰的像素組成的宏像素需要占用4字節內存。  
下面的四個像素為:[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]

YUV 4:1:1 

4:1:1的色度抽樣,是在水平方向上對色度進行4:1抽樣。對於低端用戶和消費類產品這仍然是可以接受的。對非壓縮的8比特量化的視頻來說,每個由4個水平方向相鄰的像素組成的宏像素需要占用6字節內存。  
原來四個像素為: [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] 

用6個YUV分量描述了原來的12個YUV分量,因此壓縮比為1/2,平均來講,就是用了12bit表示了一個象素點,原來YUV(8bit*3)是24bit。

 

YUV4:2:0 
4:2:0並不意味着只有Y,Cb而沒有Cr分量。它指得是對每行掃描線來說,只有一種色度分量以2:1的抽樣率存儲。相鄰的掃描行存儲不同的色度分 量,也就是說,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。對每個色度分量來說,水平方向和豎直方向的抽樣率 都是2:1,所以可以說色度的抽樣率是4:1。對非壓縮的8比特量化的視頻來說,每個由2x2個2行2列相鄰的像素組成的宏像素需要占用6字節內存。  
下面八個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y5 U5 V5] [Y6 U6 V6] [Y7U7 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] [Y7U2 V7] [Y8 U2 V7] 

 

RGB

  計算機彩色顯示器顯示色彩的原理與彩色電視機一樣,都是采用R(Red)、G(Green)、B(Blue)相加混色的原理:通過發射出三種不同強度的電子束,使屏幕內側覆蓋的紅、綠、藍磷光材料發光而產生色彩。這種色彩的表示方法稱為RGB色彩空間表示(它也是多媒體計算機技術中用得最 多的一種色彩空間表示方法)。根據色度學的介紹,不同波長的單色光會引起不同的彩色感覺,但相同的彩色感覺卻可以來源於不同的光譜成分組合。自然界中幾乎所有的顏色都能用三種基本彩色混合配出,在彩色電視技術中選擇紅色、綠色、和藍色作為三基色。其他的顏色都可以用紅色、綠色和藍色按照不同的比例混合而成。所選取的紅色、綠色和藍色三基色空間。簡稱為RGB顏色空間。

RGB565    每個像素用16位表示,RGB分量分別使用5位、6位、5位

RGB555    每個像素用16位表示,RGB分量都使用5位(剩下1位不用)

RGB24    每個像素用24位表示,RGB分量各使用8位

RGB32    每個像素用32位表示,RGB分量各使用8位(剩下8位不用)

ARGB32    每個像素用32位表示,RGB分量各使用8位(剩下的8位用於表示Alpha通道值)

RGB565(我們使用的格式)

使用16位表示一個像素,這16位中的5位用於R,6位用於G,5位用於B。

程序中通常使用一個字(WORD,一個字等於兩個字節)來操作一個像素。當讀出一個像素后,這個字的各個位意義如下:      

高字節              低字節 

R R R R R G G G     G G G B B B B B 

可以組合使用屏蔽字和移位操作來得到RGB各分量的值:  

#define RGB565_MASK_RED    0xF800 

#define RGB565_MASK_GREEN  0x07E0 

#define RGB565_MASK_BLUE   0x001F 

R = (wPixel & RGB565_MASK_RED) >> 11;   // 取值范圍0-31 

G = (wPixel & RGB565_MASK_GREEN) >> 5;  // 取值范圍0-63 

B =  wPixel & RGB565_MASK_BLUE;         // 取值范圍0-31

#define RGB(r,g,b) (unsigned int)( (r|0x08 << 11) | (g|0x08 << 6) | b|0x08 )

#define RGB(r,g,b) (unsigned int)( (r|0x08 << 10) | (g|0x08 << 5) | b|0x08 )

該代碼可以解決24位與16位相互轉換的問題

RGB555

是另一種16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。

使用一個字讀出一個像素后,這個字的各個位意義如下:     

 高字節             低字節 

X R R R R G G       G G G B B B B B       (X表示不用,可以忽略)  

RGB24使用24位來表示一個像素,RGB分量都用8位表示,取值范圍為0-255 

RGB32使用32位來表示一個像素,RGB分量各用去8位,剩下的8位不用

RGB24

RGB24使用24位來表示一個像素,RGB分量都用8位表示,取值范圍為0-255。注意在內存中RGB各分量的排列順序為:BGR BGR BGR…。通常可以使用RGBTRIPLE數據結構來操作一個像素,它的定義為:

typedef struct tagRGBTRIPLE {

BYTE rgbtBlue; // 藍色分量

BYTE rgbtGreen; // 綠色分量

BYTE rgbtRed; // 紅色分量

} RGBTRIPLE;

RGB32

RGB32使用32位來表示一個像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是帶Alpha通道的RGB24。)注意在內存中RGB各分量的排列順序為:BGRA BGRA BGRA…。通常可以使用RGBQUAD數據結構來操作一個像素,它的定義為:

typedef struct tagRGBQUAD {

BYTE rgbBlue; // 藍色分量

BYTE rgbGreen; // 綠色分量

BYTE rgbRed; // 紅色分量

BYTE rgbReserved; // 保留字節(用作Alpha通道或忽略)

} RGBQUAD。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM