yuv 与 rgb 的转换 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各
样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确
的满足各自的需求,就出现了各种各样的色彩空间模型来量化的描述颜色。我们比较常接触到的就包括 RGB / CMYK /
YIQ / YUV / HSI 等等。 对于数字电子多媒体领域来说,我们经常接触到的色彩空间的概念,主要是 RGB , YUV 这两
种(实际上,这两种体系包含了许多种具体的颜色表达方式和模型,如 sRGB, Adobe RGB, YUV422, YUV420 …),
RGB 是按三基色加光系统的原理来描述颜色,而 YUV 则是按照 亮度,色差的原理来描述颜色。 即使只是 RGB YUV
这两大类色彩空间,所涉及到的知识也是十分丰富复杂的,自知不具备足够的相关专业知识,所以本文主要针对工程
领域的应用及算法进行讨论。 2 YUV 相关色彩空间模型 2.1 YUV 与 YIQ YcrCb 对于 YUV 模型,实际上很多时候,我
们是把它和 YIQ / YCrCb 模型混为一谈的。 实际上,YUV 模型用于 PAL 制式的电视系统,Y 表示亮度,UV 并非任何单
词的缩写。 YIQ 模型与 YUV 模型类似,用于 NTSC 制式的电视系统。YIQ 颜色空间中的 I 和 Q 分量相当于将 YUV 空
间中的 UV 分量做了一个 33 度的旋转。 YCbCr 颜色空间是由 YUV 颜色空间派生的一种颜色空间,主要用于数字电视
系统中。从 RGB 到 YCbCr 的转换中,输入、输出都是 8 位二进制格式。 三者与 RGB 的转换方程如下: RGB ->
YUV : 实 际 上 也就是 : Y=0.30R+0.59G+0.11B , U=0.493(B -Y) , V=0.877(R -Y) RGB -> YIQ : RGB ->
YCrCb: 从公式中,我们关键要理解的一点是,UV / CbCr 信号实际上就是蓝色差信号和红色差信号,进而言之,实
际上一定程度上间接的代表了蓝色和红色的强度,理解这一点对于我们理解各种颜色变换处理的过程会有很大的帮助 。
我们在数字电子多媒体领域所谈到的 YUV 格式,实际上准确的说,是以 YcrCb 色彩空间模型为基础的具有多种存储
格式的一类颜色模型的家族(包括 YUV444 / YUV422 / YUV420 / YUV420P 等等)。并不是传统意义上用于 PAL 制模
拟电视的 YUV 模型。这些 YUV 模型的区别主要在于 UV 数据的采样方式和存储方式,这里就不详述。 而在 Camera
Sensor 中,最常用的 YUV 模型是 YUV422 格式,因为它采用 4 个字节描述两个像素,能和 RGB565 模型比较好的兼
容。有利于 Camera Sensor 和 Camera controller 的软硬件接口设计。 3 YUV2RGB 快速算法分析 这里指的 YUV 实际
是 YcrCb 了,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