国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

YUV格式剖析以及與RGB的轉換實現 -- 視頻和圖像編程基礎之二

yanest / 3685人閱讀

摘要:因為分別代表不同顏色信號,所以直接使用與信號表示色度的。彩色圖像記錄的格式,常見的有等。主要的抽樣格式有和。的表示法稱為表示法表示完全取樣。表示的水平取樣,垂直采樣。格式則有一通道。

YUV和RGB詳解 前言

YUV,是一種顏色編碼方法。常使用在各個視頻處理組件中。 YUV在對照片或視頻編碼時,考慮到人類的感知能力,允許降低色度的帶寬。

YUV是編碼true-color時使用的顏色空間(color space)之一. 像Y"UV, YUV, YCbCr, YPbPr等都可以稱為YUV, 彼此之間有重疊。

Y: 明亮度(Luminace, Luma)

U: 色度(chrominance)

V: 濃度(chroma)

YUV和Y"UV: 通常用來編碼電視的模擬信號 (Y"表示伽瑪校正)
YCbCr: 用來描述數字的視頻信號,適合視頻與圖片壓縮以及傳輸,例如MPEG、JPEG

YUV Formats分成兩個格式:

緊湊格式(packed format): 依次將每個pixel的Y,U,V值存儲在一起,和RGB類似

平面格式(planar format): 將一幀畫面的Y放到一起, 然后再放所有的U,然后再放所有的V

緊湊格式對于YUV4:4:4比較適合,而平面格式適用于采樣,它有I420(4:2:0), YV12, IYUV等。

歷史

Y"UV的發明是由于彩色電視與黑白電視的過渡時期[1]。黑白視頻只有Y(Luma,Luminance)視頻,也就是灰階值。到了彩色電視規格的制定,是以YUV/YIQ的格式來處理彩色電視圖像,把UV視作表示彩度的C(Chrominance或Chroma),如果忽略C信號,那么剩下的Y(Luma)信號就跟之前的黑白電視頻號相同,這樣一來便解決彩色電視機與黑白電視機的兼容問題。Y"UV最大的優點在于只需占用極少的帶寬。

因為UV分別代表不同顏色信號,所以直接使用R與B信號表示色度的UV。 也就是說UV信號告訴了電視要偏移某象素的的顏色,而不改變其亮度。 或者UV信號告訴了顯示器使得某個顏色亮度依某個基準偏移。 UV的值越高,代表該像素會有更飽和的顏色。

彩色圖像記錄的格式,常見的有RGB、YUV、CMYK等。彩色電視最早的構想是使用RGB三原色來同時傳輸。這種設計方式是原來黑白帶寬的3倍,在當時并不是很好的設計。RGB訴求于人眼對色彩的感應,YUV則著重于視覺對于亮度的敏感程度,Y代表的是亮度,UV代表的是彩度(因此黑白電影可省略UV,相近于RGB),分別用Cr和Cb來表示,因此YUV的記錄通常以Y:UV的格式呈現。

YUV格式種類

為節省帶寬起見,大多數YUV格式平均使用的每像素位數都少于24位。主要的抽樣(subsample)格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和YCbCr 4:4:4。YUV的表示法稱為A:B:C表示法:

4:4:4表示完全取樣。

4:2:2表示2:1的水平取樣,垂直完全采樣。

4:2:0表示2:1的水平取樣,垂直2:1采樣。

4:1:1表示4:1的水平取樣,垂直完全采樣。

最常用Y:UV記錄的比重通常1:1或2:1,DVD-Video是以YUV 4:2:0的方式記錄,也就是我們俗稱的I420,YUV4:2:0并不是說只有U(即Cb), V(即Cr)一定為0,而是指U:V互相援引,時見時隱,也就是說對于每一個行,只有一個U或者V分量,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。至于其他常見的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等。

YUY2及常見表示方法

YUY2(和YUYV)格式為像素保留Y,而UV在水平空間上相隔二個像素采樣一次(Y0 U0 Y1 V0),(Y2 U2 Y3 V2)…其中,(Y0 U0 Y1 V0)就是一個macro-pixel(宏像素),它表示了2個像素,(Y2 U2 Y3 V2)是另外的2個像素。 以此類推,再如:Y41P(和Y411)格式為每個像素保留Y分量,而UV分量在水平方向上每4個像素采樣一次。一個宏像素為12個字節,實際表示8個像素。圖像數據中YUV分量排列順序如下:(U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7)…

YVYU UYVY

YVYU, UYVY格式跟YUY2類似,只是排列順序有所不同。Y211格式是Y每2個像素采樣一次,而UV每4個像素采樣一次。AYUV格式則有一Alpha通道。

YV12

YV12格式與IYUV類似,每個像素都提取Y,在UV提取時,將圖像2 x 2的矩陣,每個矩陣提取一個U和一個V。YV12格式和I420格式的不同處在V平面和U平面的位置不同。在YV12格式中,V平面緊跟在Y平面之后,然后才是U平面(即:YVU);但I420則是相反(即:YUV)。NV12與YV12類似,效果一樣,YV12中U和V是連續排列的,而在NV12中,U和V就交錯排列的。

排列舉例: 2*2圖像YYYYVU; 4*4圖像YYYYYYYYYYYYYYYYVVVVUUUU

轉換 YUV與RGB的轉換公式

$$ Y = 0.299 imes R + 0.587 imes G + 0.114 imes B U = -0.169 imes R - 0.331 imes G + 0.5 imes B + 128 V = 0.5 imes R - 0.419 imes G - 0.081 imes B + 128 $$

YUV的取值范圍:

$$ Y in [0,255] U in [0,255] V in [0,255] $$

反過來,從YUV得到RGB,公式如下

$$ egin{align} &R = Y + 1.13983 imes (V-128) &G = Y - 0.39465 imes (U-128) - 0.58060 imes (V-128) &B = Y + 2.03211 imes (U-128) end{align} $$

用矩陣表示法,表示如下:

$$ egin{bmatrix} Y U V end{bmatrix}=egin{bmatrix} 0.299&0.587&0.114 -0.169&-0.331&0.5 0.5&-0.419&-0.081 end{bmatrix}egin{bmatrix} R G B end{bmatrix}+egin{bmatrix} 0 128 128 end{bmatrix} $$

$$ egin{bmatrix} R G B end{bmatrix}=egin{bmatrix} 1&-0.00093&1.401687 1&-0.3437&-0.71417 1&1.77216&0.00099 end{bmatrix}egin{bmatrix} Y U-128 V-128 end{bmatrix} $$

Y"UV與RGB轉換

SDTV(standard-definition television) with BT.601定義公式如下:

$$ egin{bmatrix} Y" U V end{bmatrix}=egin{bmatrix} 0.299&0.587&0.114 -0.14713&-0.28886&0.436 0.615&-0.51499&-0.10001 end{bmatrix}egin{bmatrix} R G B end{bmatrix} $$

$$ egin{bmatrix} R G B end{bmatrix}=egin{bmatrix} 1&0&1.13983 1&-0.39465&-0.58060 1&2.03211&0 end{bmatrix}egin{bmatrix} Y" U V end{bmatrix} $$

HDTV with BT.709定義公式如下:

$$ egin{bmatrix} Y" U V end{bmatrix}=egin{bmatrix} 0.2126&0.7152&0.0722 -0.09991&-0.33609&0.436 0.615&-0.55861&-0.05639 end{bmatrix}egin{bmatrix} R G B end{bmatrix} $$

$$ egin{bmatrix} R G B end{bmatrix}=egin{bmatrix} 1&0&1.28033 1&-0.21482&-0.38059 1&2.12798&0 end{bmatrix}egin{bmatrix} Y" U V end{bmatrix} $$

數值近似 studio swing for BT.601

$ Y" in [16,235]$
$ U/V in [16,240]$

step 1

$$ egin{bmatrix} Y" U V end{bmatrix}=egin{bmatrix} 66&129&25 -38&-74&112 112&-94&-18 end{bmatrix}egin{bmatrix} R G B end{bmatrix} $$

step 2

$$ Yt" = (Y" + 128) >> 8 Ut = (U + 128) >> 8 Vt = (V + 128) >> 8 $$

step 3

$$ Yu" = Yt" + 16 Uu = Ut + 128 Vu = Vt + 128 $$

Full swing for BT.601

$Y"/U/V in [0,255]$

step 1

$$ egin{bmatrix} Y" U V end{bmatrix}=egin{bmatrix} 77&150&29 -43&-84&127 127&-106&-21 end{bmatrix}egin{bmatrix} R G B end{bmatrix} $$

step 2

$$ Yt" = (Y" + 128) >> 8 Ut = (U + 128) >> 8 Vt = (V + 128) >> 8 $$

step 3

$$ Yu" = Yt" + 16 Uu = Ut + 128 Vu = Vt + 128 $$

Y"UV444 to RGB888

$$ Y" = 0.299 imes R + 0.587 imes G + 0.114 imes B U = -0.147 imes R - 0.289 imes G + 0.436 imes B V = 0.615 imes R - 0.515 imes G - 0.100 imes B $$

轉成定點:

$$ Y" = ((66 imes R + 129 imes G + 25 imes B +128) >> 8) + 16 U = ((-38 imes R - 74 imes G + 112 imes B +128) >> 8) + 128 V = ((112 imes R - 94 imes G - 18 imes B + 128) >> 8 ) +128 $$

RGB888 to Y"UV

定點方法:
clmap 表示限定值在[0,255]之間

$$ C = Y" - 16 D = U - 128 E = V - 128 R = clamp( (298 imes C + 408 imes E + 128) >> 8 ) G = clamp( (298 imes C - 100 imes D - 208 imes E +128) >> 8 ) B = clamp( (298 imes C + 516 imes D +128) >> 8 ) $$

Y"UV422 to RGB888

Y"UV422在內存中的存儲方式如下:

所以讀取4bytes, 輸出6bytes(2 pixels)

y0 = yuv[0];
u =  yuv[1];
y1 = yuv[2];
v = yuv[3];
rgb0 = Y"UV444toRGB888(y0, u, v);
rgb1 = Y"UV444toRGB888(y1, u, v);
Y"UV420p (I420) to RGB888

Y"UV420p的采樣方式如下:

獲取坐標為(x,y)像素點的y,u,v方法如下:

total_pixel = width * height;
y = yuv[y*width + x];
u = yuv[(y/2) * (width/2) + (x/2) + total_pixel]
v = yuv[(y/2) * (widith/2) + (x/2) + total_pixel + (total_pixel/4)]
rgb = Y"uv444toRGB(y,u,v)

Y"V12 和Y"UV420p相似,只是UV數據反轉, Y"后是V,然后是U。

代碼示例 RGB to Y"UV420p
//
// Created by         :  Harris Zhu
// Filename           :  rgb2I420.cpp
// Avthor             :  Harris Zhu
// Created On         :  2018-09-17 04:33:02
// Last Modified      :  2018-09-17 04:33:02
// Update Count       :  1
// Tags               :   
// Description        :  
// Conclusion         :  
//                      
//=======================================================================

#include 
#include 

void Rgb2Yuv420p(uint8_t *destination, uint8_t *rgb, size_t width, size_t height)
{
    size_t image_size = width * height;
    size_t upos = image_size;
    size_t vpos = upos + upos / 4;
    size_t i = 0;

    for( size_t line = 0; line < height; ++line )
    {
        if( !(line % 2) )
        {
            for( size_t x = 0; x < width; x += 2 )
            {
                uint8_t r = rgb[3 * i];
                uint8_t g = rgb[3 * i + 1];
                uint8_t b = rgb[3 * i + 2];
                uint8_t yt =  ((66*r + 129*g + 25*b + 128) >> 8) + 16;
                uint8_t ut =  (((-38*r) + (-74*g) + 112*b + 128) >> 8) + 128;
                uint8_t vt =  ((112*r + (-94*g) + (-18*b) + 128) >> 8) + 128;

                destination[i++] = yt;
                destination[upos++] = ut;
                destination[vpos++] = vt;

                r = rgb[3 * i];
                g = rgb[3 * i + 1];
                b = rgb[3 * i + 2];
                yt =  ((66*r + 129*g + 25*b + 128) >> 8) + 16;

                destination[i++] = yt;
            }
        }
        else
        {
            for( size_t x = 0; x < width; x += 1 )
            {
                uint8_t r = rgb[3 * i];
                uint8_t g = rgb[3 * i + 1];
                uint8_t b = rgb[3 * i + 2];
                uint8_t yt =  ((66*r + 129*g + 25*b + 128) >> 8) + 16;

                destination[i++] = yt;
            }
        }
    }
}

測試文件:

//
// Created by         :  Harris Zhu
// Filename           :  test.cpp
// Author             :  Harris Zhu
// Created On         :  2018-09-17 04:40:06
// Last Modified      :  2018-09-17 04:40:06
// Update Count       :  1
// Tags               :   
// Description        :  
// Conclusion         :  
//                      
//=======================================================================

#include 
#include 
#include "rgb2i420.h"
#include "i4202rgb.h"

int main(int argc, char**argv) {

    char * din = argv[1];
    char * dout = argv[2];
    int width = atoi(argv[3]);
    int height = atoi(argv[4]);
    
    size_t imagesize=width*height;


    uint8_t bufin[imagesize*3];
    uint8_t bufout[size_t(imagesize*1.5)];

    size_t nread;

    FILE * fin=fopen(din, "r");
    FILE * fout=fopen(dout, "w+");

    if(fin) {
        while((nread = fread(bufin, 1, sizeof(bufin), fin)) > 0) {
            Rgb2Yuv420p(bufout, bufin, width, height);
            fwrite(bufout, 1, sizeof(bufout), fout);
        }
    }


    fclose(fin);
    fclose(fout);
    return 0;


}

makefile文件:

GENFILE = yuv.in

b build: torgb toyuv

torgb:
    g++ -o torgb torgb.cpp -I./ -g

toyuv:
    g++ -o toyuv toyuv.cpp -I./ -g

g1 gen1:
    ./toyuv rgb.in yuv.out 60 40

g2 gen2:
    ./torgb yuv.in rgb.out 720 480

p1 play1:
    cat yuv.out| ffplay -i pipe:0 -f rawvideo -pix_fmt yuv420p -video_size 60x40

p2 play2:
    cat rgb.out | ffplay -i pipe:0 -f rawvideo -pix_fmt rgb24 -video_size 720x480

.PHONY: torgb toyuv

上面的makefile包含了下面yuv2rgb的部分

Y"uv420p to RGB
//
// Created by         :  Harris Zhu
// Filename           :  rgb2I420.cpp
// Avthor             :  Harris Zhu
// Created On         :  2018-09-17 04:33:02
// Last Modified      :  2018-09-17 04:33:02
// Update Count       :  1
// Tags               :   
// Description        :  
// Conclusion         :  
//                      
//=======================================================================

#include 
#include 

void Yuv420p2Rgb888(uint8_t *destination, uint8_t *yuv, size_t width, size_t height)
{
    size_t image_size = width * height;
    size_t upos = image_size;
    size_t vpos = upos + upos / 4;
    size_t i = 0;

    for( size_t line = 0; line < height; ++line )
    {
        for( size_t col = 0; col < width; col += 1 )
        {
            uint8_t y = yuv[line*width+col];
            uint8_t u = yuv[(line/2)*(width/2)+(col/2)+image_size];
            uint8_t v = yuv[(line/2)*(width/2)+(col/2)+image_size+(image_size/4)];

            int16_t C = y-16;
            int16_t D = u-128;
            int16_t E = v-128;

            int16_t rt =  (int16_t)((298*C+408*E+128)>>8);
            int16_t gt =  (int16_t)((298*C-100*D-208*E+128)>>8);
            int16_t bt =  (int16_t)((298*C+516*D+128)>>8);

            destination[i++] = rt>255?255:rt<0?0:rt;
            destination[i++] = gt>255?255:gt<0?0:gt;
            destination[i++] = bt>255?255:bt<0?0:bt;

        }
    }
}

測試用例:

//
// Created by         :  Harris Zhu
// Filename           :  test.cpp
// Author             :  Harris Zhu
// Created On         :  2018-09-17 04:40:06
// Last Modified      :  2018-09-17 04:40:06
// Update Count       :  1
// Tags               :   
// Description        :  
// Conclusion         :  
//                      
//=======================================================================

#include 
#include 
#include "rgb2i420.h"
#include "i4202rgb.h"

int main(int argc, char**argv) {

    char * din = argv[1];
    char * dout = argv[2];
    int width = atoi(argv[3]);
    int height = atoi(argv[4]);
    

    size_t imagesize=width*height;


    uint8_t bufin[(size_t)(imagesize*1.5)];
    uint8_t bufout[imagesize*3];

    size_t nread;

    FILE * fin=fopen("yuv.in", "r");
    FILE * fout=fopen(dout, "w+");

    if(fin) {
        while((nread = fread(bufin, 1, sizeof(bufin), fin)) > 0) {
            Yuv420p2Rgb888(bufout, bufin, width, height);
            fwrite(bufout, 1, sizeof(bufout), fout);
            fflush(fout);
        }
    }


    fclose(fin);
    fclose(fout);
    return 0;


}

注:以上代碼都可以在這里找到, 包括yuv和rgb文件

總結

YUV相比RGB的優點是和黑白兼容,而且它的變種容易壓縮帶寬,它被廣泛用于目前各種圖像和視頻編碼中。掌握它是開始圖像和視頻編程的基礎

注:本文大部分內容是來自YUV的wiki, 大家也可以自行查看原文。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11072.html

相關文章

  • 圖像格式PPM/PGM/PBM剖析及代碼實現 -- 視頻圖像編程基礎之一

    摘要:可移植像素圖格式,灰度圖格式,位圖格式的介紹簡介可移植像素圖格式,可移植灰度圖格式和可移植位圖格式是便于跨平臺的圖像格式。每個文件的開頭兩個字節碼作為文件描述符,指出具體格式和編碼形式。 可移植像素圖格式 PPM,灰度圖格式 PGM,位圖格式 PBM 的介紹 簡介 可移植像素圖格式(PPM),可移植灰度圖格式(PGM)和可移植位圖格式(PBM)是便于跨平臺的圖像格式。有時候也被統稱為 ...

    Zachary 評論0 收藏0
  • 一文讀懂 YUV 采樣格式

    摘要:接下來的不同采樣格式都是在一張圖像所有像素的轉換到基礎上進行的。采樣采樣,意味著分量是分量采樣的一半,分量和分量按照的比例采樣。基于采樣的格式基于采樣的格式主要有和兩種類型,每個類型又對應其他具體格式。YUV 是一種顏色編碼方法,和它等同的還有 RGB 顏色編碼方法。 RGB 顏色編碼 RGB 三個字母分別代表了 紅(Red)、綠(Green)、藍(Blue),這三種顏色稱為 三原色,將它們...

    tracy 評論0 收藏0

發表評論

0條評論

yanest

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<