打印

哪位大哥做过ARM处理视频的 速度可以吗?

[复制链接]
2828|7
手机看帖
扫描二维码
随时随地手机跟帖
沙发
S3C2440| | 2009-12-20 21:58 | 只看该作者
YUV转RGB

在整个视频行业中,定义了很多 YUV 格式,我以UYVY格式标准来说明,4:2:2 格式UYVY每像素占16 位,UYVY字节顺序如下图:



(图3 UYVY字节顺序)



其中第一个字节为U0,每二个字节为Y0,依次排列如下:

[U0,Y0,V0,Y1] [U1,Y2,V1,Y3] [U2,Y4,V2,Y5] ……

经过仔细分析,我们要实现RGB转YUV格式的话,一个像素的RGB占用三个节,而UYVY每像素占用两个字节,在演示中直接把UYVY字节信息保存到*.pal格式中(这是我自己写来测试用的^_^),*.pal格式字节顺序是先保存上场像素,接着保存下场像素,如果是720x576的一张图像转换为YUV格式并保存的话,文件大小应该是829,440字节(720*576*2)。您可以执行本文附带的程序 (功能菜单->转换并写入YUV两场) 查看转换过程。

关于YUV转换为RGB公式,我直接使用一篇**提供的公式,经过思考,我发觉要想实现准确无误的把YUV还原为原有的RGB图像很难实现,因为我从UYVY的字节顺序来分析没有找到反变换的方法(您找到了记得告诉我哟: liyingjiang@21cn.com ),例如我做了一个简单的分析,假设有六个像素的UYVY格式,要把这12个字节的UYVY要转换回18个字节的RGB,分析如下:



12个字节的UYVY排列方式:

[U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5]

完全转换为18个字节的RGB所需的UYVY字节排列如下:

[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y4 U4 V4] [Y5 U5 V5]

我们可以看到,12个字节的UYVY无法实现,缺少U3 V3 U4 V4。于是我抛开准确无误地把UYVY转换回RGB的想法,直接使用最近的UV来执行转换,结果发觉转换回来的RGB图像用肉眼根本分辩不出原有RGB图像与反变换回来的RGB图像差别,您可以执行本文附带的程序 (功能菜单->读取YUV并显示) 查看效果,下面是反变换公式和代码的实现:



// 反变换公式

R= 1.0Y + 0 +1.402(V-128)

G= 1.0Y - 0.34413 (U-128)-0.71414(V-128)

B= 1.0Y + 1.772 (U-128)+0



代码实现:

void CRGB2YUVView::YUV2RGB(byte *pRGB, byte *pYUV)

{

    byte y, u, v;

    y = *pYUV; pYUV++;

    u = *pYUV; pYUV++;

    v = *pYUV;



    *pRGB = static_cast<byte>(1.0*y + 8 + 1.402*(v-128));    pRGB++;                 // r

    *pRGB = static_cast<byte>(1.0*y - 0.34413*(u-128) - 0.71414*(v-128)); pRGB++;   // g

    *pRGB = static_cast<byte>(1.0*y + 1.772*(u-128) + 0);                            // b

}



// 读取PAL文件转换为RGB并显示

void CRGB2YUVView::OnReadPAL()

{

    // TODO: Add your command handler code here

    CDC *pDC = GetDC();

    CRect rect;

    CBrush brush(RGB(128,128,128));

    GetClientRect(&rect);

    pDC->FillRect(&rect, &brush);



    // PAL 720x576 : 中国的电视标准为PAL制

    int CurrentXRes = 720;

    int CurrentYRes = 576;

    int size        = CurrentXRes * CurrentYRes;

   

    // 分配内存

    byte *Video_Field0 = (byte*)malloc(CurrentXRes*CurrentYRes);

    byte *Video_Field1 = (byte*)malloc(CurrentXRes*CurrentYRes);



    // 保存内存指针

    byte *Video_Field0_ = Video_Field0;

    byte *Video_Field1_ = Video_Field1;



    // 初始化内存

    ZeroMemory(Video_Field0, CurrentXRes*CurrentYRes);

    ZeroMemory(Video_Field1, CurrentXRes*CurrentYRes);



    byte yuv_y0, yuv_u0, yuv_v0; // yuv_v1; // {y0, u0, v0, v1};

    byte r, g, b;

    byte bufRGB[3]; // 临时保存{R,G,B}

    byte bufYUV[3]; // 临时保存{Y,U,V}

   

    // 初始化数组空间

    memset(bufRGB,0, sizeof(byte)*3);

    memset(bufYUV,0, sizeof(byte)*3);

   

    char strFileName[MAX_PATH]="720bmp.pal";



    // 分配图片像素内存

    RGBTRIPLE *rgb;

    rgb = new RGBTRIPLE[CurrentXRes*CurrentYRes];



    memset(rgb,0, sizeof(RGBTRIPLE)*CurrentXRes*CurrentYRes); // 初始化内存空间



    CFile* f;

    f = new CFile();

    f->Open(strFileName, CFile::modeRead);

    f->SeekToBegin();

    f->Read(Video_Field0, CurrentXRes*CurrentYRes);

    f->Read(Video_Field1, CurrentXRes*CurrentYRes);



    // 上场 (1,3,5,7...行)

    for ( int i = CurrentYRes-1; i>=0; i--) {

        for ( int j = 0; j<CurrentXRes; j++) {

            if(!(i%2)==0)

            {

                // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节

                if ((j%2)==0)

                {

                    yuv_u0 = *Video_Field0;

                    Video_Field0++;

                }

                else

                {

                    yuv_v0 = *Video_Field0;

                    Video_Field0++;

                }

                yuv_y0 = *Video_Field0;      

                Video_Field0++;



                bufYUV[0] = yuv_y0; // Y

                bufYUV[1] = yuv_u0; // U

                bufYUV[2] = yuv_v0; // V



                // RGB转换为YUV

                YUV2RGB(bufRGB,bufYUV);

                r = bufRGB[0];   // y

                g = bufRGB[1];   // u

                b = bufRGB[2];   // v

                if (r>255) r=255; if (r<0) r=0;

                if (g>255) g=255; if (g<0) g=0;

                if (b>255) b=255; if (b<0) b=0;



                for (int k=0; k<1000; k++) ; //延时

                // 视图中显示

                pDC->SetPixel(j, CurrentYRes-1-i, RGB(r, g, b));



            }// end if i%2

        }

    }



    // 下场 (2,4,6,8...行)

    for ( int i_ = CurrentYRes-1; i_>=0; i_--) {

        for ( int j_ = 0; j_<CurrentXRes; j_++) {

            if((i_%2)==0)

            {

                // UYVY标准 [U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5] 每像素点两个字节,[内]为四个字节

                if ((j_%2)==0)

                {

                    yuv_u0 = *Video_Field1;

                    Video_Field1++;

                }

                else

                {

                    yuv_v0 = *Video_Field1;

                    Video_Field1++;

                }

                yuv_y0 = *Video_Field1;      

                Video_Field1++;



                bufYUV[0] = yuv_y0; // Y

                bufYUV[1] = yuv_u0; // U

                bufYUV[2] = yuv_v0; // V



                // RGB转换为YUV

                YUV2RGB(bufRGB,bufYUV);

                r = bufRGB[0];   // y

                g = bufRGB[1];   // u

                b = bufRGB[2];   // v

                if (r>255) r=255; if (r<0) r=0;

                if (g>255) g=255; if (g<0) g=0;

                if (b>255) b=255; if (b<0) b=0;



                for (int k=0; k<1000; k++) ; //延时

                // 视图中显示

                pDC->SetPixel(j_, CurrentYRes-1-i_, RGB(r, g, b));

            }

        }

    }

   

    // 提示完成

    char buffer[80];

    sprintf(buffer,"完成读取PAL文件:%s ", strFileName);

    MessageBox(buffer, "提示信息", MB_OK | MB_ICONINFORMATION);



    // 关闭PAL电视场文件

    f->Close();

   

    // 释放内存

    free( Video_Field0_ );

    free( Video_Field1_ );

    delete f;

    delete rgb;

}

使用特权

评论回复
板凳
S3C2440| | 2009-12-20 21:58 | 只看该作者
做视频的人必须用到的YUV2RGB  或者是RGB2YUV

使用特权

评论回复
地板
北京户口| | 2009-12-20 22:19 | 只看该作者

使用特权

评论回复
5
思行合一| | 2009-12-20 22:22 | 只看该作者
怎么看不到图

使用特权

评论回复
6
虎虎生威| | 2009-12-20 23:18 | 只看该作者
2楼的图3在哪……

使用特权

评论回复
7
虎虎生威| | 2009-12-20 23:18 | 只看该作者
不过解答的很详细,赞一个

使用特权

评论回复
8
北京户口| | 2009-12-21 09:12 | 只看该作者
最近正好在做视频这块的事情 刚把一些格式方面的知识搞明白, 分享一下 yuv色彩模型来源于rgb模型,

该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。

应用:basic color model used in analogue color TV broadcasting.




YCbCr模型来源于yuv模型。YCbCr is a scaled and offset version of the YUV color space.


应用:数字视频,ITU-R BT.601 recommendation

ycbcr与rgb格式的相互转换不是可逆的,而yuv与rgb之间的转换是可逆的。因此,yuv格式可以用于无损压缩。ycbcr一般用于有损压缩,因为y、cb、cr之间的相关性比y、u、v小的多,结合色度的采样可以进一步提高压缩效率。

这也可以更深入的了解视频压缩中图像采用ycbcr格式的原因。

一、和rgb之间换算公式的差异


yuv<-->rgb

Y'= 0.299*R' + 0.587*G' + 0.114*B'


U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')


V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')


R' = Y' + 1.140*V'


G' = Y' - 0.394*U' - 0.581*V'


B' = Y' + 2.032*U'














yCbCr<-->rgb

Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16


Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128


Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128


R' = 1.164*(Y’-16) + 1.596*(Cr'-128)


G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)


B' = 1.164*(Y’-16) + 2.017*(Cb'-128)














Note: 上面各个符号都带了一撇,表示该符号在原值基础上进行了gamma correction

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

500

帖子

1

粉丝