File: StudyYUV.txtName: 深入学习YUV色彩模型Author: zyl910Version: V1.1Updata: 2006-5-28
最近突然又对图形学有了兴趣,翻出了多年前学习图形学的笔记,感触良多。于是将它们整理好发了上来。
一、基础
RGB转YUV的转换是这样的:[Y] = [ 0.299 0.587 0.114] [R][U] = [-0.148 -0.289 0.437] * [G][V] = [ 0.615 -0.515 -0.100] [B]
YUV转RGB的转换是这样的:[R] = [1 0 1.140] [Y][G] = [1 -0.395 -0.581] * [U][B] = [1 2.032 0 ] [V]
二、那些变换系数是如何推导出来的?
最开始,我是想找一个RGB与YUV转换的快速算法,于是开始研究它的系数。
2.1 YUV转RGB
最先以YUV转RGB为突破口。注意在转换矩阵中有两个0,所以可以去掉一次乘法:B = Y + 2.032*UR = Y + 1.140*V
利用“Y = 0.299*R + 0.587*G + 0.114*B”这个事实来推导G:G = (Y - 0.299*R - 0.114*B) / 0.587
将B、R的计算公式代入并化简:G = [Y - 0.299*(Y + 1.140*V) - 0.114*(Y + 2.032*U)] / 0.587 = [Y - (0.299*Y + 0.299*1.140*V) - (0.114*Y + 0.114*2.032*U)] / 0.587 = [(Y - 0.299*Y - 0.114*Y)- 0.299*1.140*V - 0.114*2.032*U] / 0.587 = [(1 - 0.299 - 0.114)*Y - 0.299*1.140*V - 0.114*2.032*U] / 0.587 = (0.587*Y - 0.299*1.140*V - 0.114*2.032*U) / 0.587 = Y + (-0.299*1.140*V - 0.114*2.032*U) / 0.587 = Y - (0.299*1.140 / 0.587)*V - (0.114*2.032 / 0.587)*U = Y - (0.114*2.032 / 0.587)*U - (0.299*1.140 / 0.587)*V = Y - 0.394630*U - 0.580681*V
正好与YUV转RGB的系数符合。 完整的转换公式:B = Y + 2.032*UR = Y + 1.140*VG = Y - (0.114*2.032 / 0.587)*U - (0.299*1.140 / 0.587)*V
2.2 RGB转YUV 从分析YUV转RGB时,我们发现了两个关键系数——与U有关的2.032 和 与V有关的1.140。所以我们拿它们去乘RGB转YUV转换矩阵的系数试试:U: 2.032 * [-0.148 -0.289 0.437] = [-0.300736 -0.587248 0.887984]V: 1.140 * [ 0.615 -0.515 -0.100] = [ 0.701100 -0.587100 -0.114000]
观察这些系数,发现有两个特点: 1.那些负数系数与“彩色转灰度”系数(0.299、0.587、0.114)很相似。 2.那个正数系数 正好等于 两个负数系数之和的绝对值。
所以我们可以将U、V部分的转换矩阵看成这个样子:U: (1 / 2.032) * [ -0.299 -0.587 1-0.114]V: (1 / 1.140) * [1-0.299 -0.587 -0.114]
完整的转换公式:[Y] = [ 0.299 0.587 0.114 ] [R][U] = [( -0.299)/2.032 (-0.587)/2.032 (1-0.114)/2.032] * [G][V] = [(1-0.299)/1.140 (-0.587)/1.140 ( -0.114)/1.140] [B]
用矩阵计算“RGB转YUV”很慢,我们可根据“YUV转RGB”逆推:Y = 0.299*R + 0.587*G + 0.114*BU = (1 / 2.032)*(B-Y)V = (1 / 1.140)*(R-Y)
2.3 小结
所谓的YUV色彩模型是由0.299、0.587、0.114、2.032、1.140这五个数字定义出来的,非常简洁、精巧。但是这还不是最精巧的,YCbCr完全是由0.299、0.587、0.114这三个数字定义出来的,详见《深入学习Ycbcr色彩模型》。
三、整数算法
先将前面的成果列出来。 RGB转YUV:Y = 0.299*R + 0.587*G + 0.114*BU = (1 / 2.032)*(B-Y)V = (1 / 1.140)*(R-Y)
YUV转RGB:B = Y + 2.032*UR = Y + 1.140*VG = Y - (0.114*2.032 / 0.587)*U - (0.299*1.140 / 0.587)*V
可以看出,U、V、R、B 的计算就是用乘法缩放数值,完全可以数组查表。 至于Y的计算,请参考《彩色转灰度算法彻底学习》。 唯一麻烦一点的是G,因为它有两个乘法,直接整数查表恐怕不精确。所以可以考虑将数值缩放65536倍(16位精度)。 大概是这样:Y = (R*19595 + G*38469 + B*7472) >> 16U = YUV_B2U[0x100 + B - Y]V = YUV_R2V[0x100 + R - Y]
B = Y + YUV_U2B[0x100 + U]R = Y + YUV_V2R[0x100 + V]G = Y - ((YUV_U2G[0x100 + U] + YUV_V2G[0x100 + V]) >> 16)