YUV2RGB

来源:互联网 发布:淘宝怎么找人代付款 编辑:程序博客网 时间:2024/05/16 00:35

3 YUV2RGB快速算法分析

        这里指的YUV实际是YcrCb了 8  ) YUV2RGB的转换公式本身是很简单的,但是牵涉到浮点运算,所以,如果要实现快速算法,算法结构本身没什么好研究的了,主要是采用整型运算或者查表来加快计算速度。
首先可以推导得到转换公式为:

        R = Y + 1.4075 *(V-128)
        G = Y – 0.3455 *(U –128) – 0.7169 *(V –128)
        B = Y + 1.779 *(U – 128)

3.1 整型算法

       要用整型运算代替浮点运算,当然是要用移位的办法了,我们可以很容易得到下列算法:

        u = YUVdata[UPOS] - 128;
        v = YUVdata[VPOS] - 128;

        rdif = v + ((v * 103) >> 8);
        invgdif = ((u * 88) >> 8) +((v * 183) >> 8);
        bdif = u +( (u*198) >> 8);

        r = YUVdata[YPOS] + rdif;
        g = YUVdata[YPOS] - invgdif;
        b = YUVdata[YPOS] + bdif;

为了防止出现溢出,还需要判错计算的结果是否在0-255范围内,做类似下面的判断。

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

        要从RGB24转换成RGB565数据还要做移位和或运算:

        RGBdata[1] =( (r & 0xF8)  | ( g >> 5) );
        RGBdata[0] =( ((g & 0x1C) << 3) | ( b >> 3) );

3.2 部分查表法

        查表法首先可以想到的就是用查表替代上述整型算法中的乘法运算。

        rdif = fac_1_4075[u];
        invgdif = fac_m_0_3455[u] + fac_m_0_7169[v];
        bdif = fac_1_779[u];

        这里一共需要4个1维数组,下标从0开始到255,表格共占用约1K的内存空间。uv可以不需要做减128的操作了。在事先计算对应的数组元素的值的时候计算在内就好了。

        对于每个像素,部分查表法用查表替代了2次减法运算和4次乘法运算,4次移位运算。但是,依然需要多次加法运算和6次比较运算和可能存在的赋值操作,相对第一种方法运算速度提高并不明显。

3.3 完全查表法

        那么是否可以由YUV直接查表得到对应的RGB值呢?乍一看似乎不太可能,以最复杂的G的运算为例,因为G与YUV三者都相关,所以类似 G=YUV2G[Y][U][V]这样的算法,一个三维下标尺寸都为256的数组就需要占用2的24次方约16兆空间,绝对是没法接受的。所以目前多数都是采用部分查表法。

        但是,如果我们仔细分析就可以发现,对于G我们实际上完全没有必要采用三维数组,因为Y只与UV运算的结果相关,与UV的个体无关,所以我们可以采用二次查表的方法将G的运算简化为对两个二维数组的查表操作,如下:

        G = yig2g_table[ y ][ uv2ig_table[ u ][ v ] ];

        而RB本身就只和YU或YV相关,所以这样我们一共需要4个8*8的二维表格,需要占用4乘2的16次方共256K内存。基本可以接受。但是对于手机这样的嵌入式运用来说,还是略有些大了。

        进一步分析,我们可以看到,因为在手机等嵌入式运用上我们最终是要把数据转换成RGB565格式送到LCD屏上显示的,所以,对于RGB三分量来说,我们根本不需要8bit这么高的精度,为了简单和运算的统一起见,对每个分量我们其实只需要高6bit的数据就足够了,所以我们可以进一步把表格改为4个6*6的二维表格,这样一共只需要占用16K内存!在计算表格元素值的时候还可以把最终的溢出判断也事先做完。最后的算法如下:

        y = (YUVdata[Y1POS] >> 2);
        u = (YUVdata[UPOS] >> 2);
        v = (YUVdata[VPOS] >> 2);

        r = yv2r_table[ y ][ v ];
        g = yig2g_table[ y ][ uv2ig_table[ u ][ v ] ];
        b = yu2b_table[ y ][ u ];
 
        RGBdata[1] =( (r & 0xF8)  | ( g >> 5) );
        RGBdata[0] =( ((g & 0x1C) << 3) | ( b >> 3) );

        这样相对部分查表法,我们增加了3次移位运算,而进一步减少了4次加法运算和6次比较赋值操作。

        在计算表格元素数值的时候,要考虑舍入和偏移等因数使得计算的中间结果满足数组下标非负的要求,需要一定的技巧。

        采用完全查表法,相对于第一种算法,最终运算速度可以有比较明显的提高,具体性能能提高多少,要看所在平台的CPU运算速度和内存存取速度的相对比例。内存存取速度越快,用查表法带来的性能改善越明显。在我的PC上测试的结果性能大约能提高35%。而在某ARM平台上测试只提高了约15%。

3.4 进一步的思考

        实际上,上述算法:

        RGBdata[1] =( (r & 0xF8)  | ( g >> 5) );
        RGBdata[0] =( ((g & 0x1C) << 3) | ( b >> 3) );

        中的 (r & 0xF8) 和 ( b >> 3) 等运算也完全可以在表格中事先计算出来。另外,YU / YV的取值实际上不可能覆盖满6*6的范围,中间有些点是永远取不到的无输入,RB的运算也可以考虑用5*5的表格。这些都可能进一步提高运算的速度,减小表格的尺寸。

        另外,在嵌入式运用中,如果可能尽量将表格放在高速内存如SRAM中应该比放在SDRAM中更加能发挥查表法的优势。

4 RGB2YUV ?

        目前觉得这个是没法将3维表格的查表运算化简为2维表格的查表运算了。只能用部分查表法替代其中的乘法运算。

        另外,多数情况下,我们需要的还是YUV2RGB的转换,因为从Sensor得到的数据通常我们会用YUV数据,此外JPG和MPEG实际上也是基于YUV格式编码的,所以要显示解码后的数据需要的也是YUV2RGB的运算 8 )运气运气。

以下摘自:http://blog.csdn.net/CTeX/archive/2006/06/06/776951.aspx描述yuv422的存储yuy2,uyvy

注:经查msdn中文版里面关于YUV422格式的图表有误:原文如下所示

4:2:2 格式,每像素 16 位

支持两个 4:2:2 格式,FOURCC 码如下:

YUY2

UYVY

两个都是打包格式,其中每个巨像素都是编码为四个连续字节的两个像素。这样会使得色度水平下采样乘以系数 2。

YUY2

在 YUY2 格式中,数据可被视为一个不带正负号的 char 值组成的数组,其中第一个字节包含第一个 Y 样例,第二个字节包含第一个 U (Cb) 样例,第三个字节包含第二个 Y 样例,第四个字节包含第一个 V (Cr) 样例,如图 6 所示。


图 6. YUY2 内存布局

如果该图像被看作由两个 little-endian WORD 值组成的数组,则第一个 WORD 在最低有效位 (LSB) 中包含 Y0,在最高有效位 (MSB) 中包含 U。第二个 WORD 在 LSB 中包含 Y1,在 MSB 中包含 V。

YUY2 是用于 Microsoft DirectX® Video Acceleration (DirectX VA) 的首选 4:2:2 像素格式。预期它会成为支持 4:2:2 视频的 DirectX VA 加速器的中期要求。

UYVY

此格式与 YUY2 相同,只是字节顺序是与之相反的 — 就是说,色度字节和灯光字节是翻转的(图 7)。如果该图像被看作由两个 little-endian WORD 值组成的数组,则第一个 WORD 在 LSB 中包含 U,在 MSB 中包含 Y0,第二个 WORD 在 LSB 中包含 V,在 MSB 中包含 Y1。


图 7. UYVY 内存布局

正确的应该是:

¨ YUY2(和YUYV)格式为每个像素保留Y分量,而UV分量在水平方向上每两个像素采样一次。一个 
宏像素为4个字节,实际表示2个像素。(4:2:2的意思为一个宏像素中有4Y分量、2U分量和2 
V分量。)图像数据中YUV分量排列顺序如下: 
Y0 U0 Y1 V0    Y2 U2 Y3 V2 … 
(Sep.06) 

 YUV与RGB相互转换的公式如下(RGB取值范围均为0-255):

Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
原创粉丝点击