存档

‘Image’ 分类的存档

[Color]深入学习YCbCr色彩模型

2007年11月12日 Galaxy 没有评论

http://blog.csdn.net/zyl910/archive/2006/05/29/759535.aspx

[Color]深入学习YCbCr色彩模型

File:      StudyYCbCr.txt
Name:      深入学习YCbCr色彩模型
Author:    zyl910
Version:   V1.0
Updata:    2006-5-28

最近突然又对图形学有了兴趣,翻出了多年前学习图形学的笔记,感触良多。于是将它们整理好发了上来。

一、基础

  RGB转YCbCr的转换是这样的:
[Y ] = [ 0.299   0.587   0.114 ]   [R]   [  0]
[Cb] = [-0.1687 -0.3313  0.5   ] * [G] + [128]
[Cr] = [ 0.5    -0.4187 -0.0813]   [B]   [128]
  YCbCr转RGB的转换是这样的:
[R] = [1  0        1.402  ]   [  Y   ]
[G] = [1 -0.34414 -0.71414] * [Cb-128]
[B] = [1  1.772    0      ]   [Cr-128]

二、那些变换系数是如何推导出来的?

  看到“YCbCr转RGB”中计算R、B的那些零没有,把它们精简掉:
R = Y + 1.402*(Cr-128)
B = Y + 1.772*(Cb-128)

  利用“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.402*(Cr-128)] – 0.114*[Y + 1.772*(Cb-128)]} / 0.587
 = {Y – [0.299*Y + 0.299*1.402*(Cr-128)] – [0.114*Y + 0.114*1.772*(Cb-128)]} / 0.587
 = [(1 - 0.299 - 0.114)*Y - 0.299*1.402*(Cr-128) - 0.114*1.772*(Cb-128)] / 0.587
 = Y – (0.299*1.402 / 0.587)*(Cr-128) – (0.114*1.772 / 0.587)*(Cb-128)
 = Y – 0.714136*(Cr-128) – 0.344136*(Cb-128)
  现在只是不明白神奇的1.772、1.402了,将它们代入“RGB转YCbCr”看看:
Cb: 1.772 * [-0.1687 -0.3313  0.5   ] = [-0.2989364 -0.5870636  0.886    ] ≈ [ -0.299 -0.587 1-0.114]
Cr: 1.402 * [ 0.5    -0.4187 -0.0813] = [ 0.701     -0.5870174 -0.1139826] ≈ [1-0.299 -0.587  -0.114]

  0.5看起来很明了,我们用 0.5 与 0.299、0.587、0.114 可以推导出那两个常数:
Cb2b * 0.5 = 1-0.114
Cr2R * 0.5 = 1-0.299

Cb2b = 2*(1-0.114) = 1.772
Cr2R = 2*(1-0.299) = 1.402
  用矩阵计算“RGB转YCbCr”很慢,我们可根据“YCbCr转RGB”逆推:
Cb = (1 / 1.772)*(B – Y) + 128 = [1 / (2*(1-0.114))]*(B – Y) + 128 = (1/2)*[1 / (1-0.114)]*(B – Y) + 128
Cr = (1 / 1.402)*(R – Y) + 128 = [1 / (2*(1-0.299))]*(R – Y) + 128 = (1/2)*[1 / (1-0.299)]*(R – Y) + 128

  啊哈!现在理解 1-0.114、1-0.299 的由来了吧:当 B为1、R和G为0 时,(B-Y) 为 (1-0.114) = 0.886;当 B为0、R和G为1 时,(B-Y) 为 (0-0.886) = -0.886。所以需要除以(1-0.114)将结果缩放。
  但是,我们一般需要结果在 0~255 这样的字节范围内,所以需要乘以(1/2),再加上128

  所以YCbCr完全是根据 0.299、0.587、0.114 这几个常数推导出来的。
三、整数算法

  先将前面的成果列出来。
  RGB转YCbCr:
Y = 0.299*R + 0.587*G + 0.114*B
Cb = (1 / 1.772)*(B – Y) + 128
Cr = (1 / 1.402)*(R – Y) + 128

  YCbCr转RGB:
R = Y + 1.402*(Cr-128)
B = Y + 1.772*(Cb-128)
G = Y – (0.299*1.402 / 0.587)*(Cr-128) – (0.114*1.772 / 0.587)*(Cb-128)

  可以看出,Cb、Cr、R、B 的计算就是用乘法缩放数值,完全可以数组查表,甚至那个加减128可以在查表时优化掉。
  至于Y的计算,请参考《彩色转灰度算法彻底学习》
  唯一麻烦一点的是G,因为它有两个乘法,直接整数查表恐怕不精确。所以可以考虑将数值缩放65536倍(16位精度)。
  大概是这样:
Y = (R*19595 + G*38469 + B*7472) >> 16
Cb = YCbCr_B2Cb[0x100 + B - Y]
Cr = YCbCr_R2Cr[0x100 + R - Y]

R = Y + YCbCr_Cr2R[Cr]
B = Y + YCbCr_Cb2B[Cb]
G = Y – ((YCbCr_Cr2G[Cr] + YCbCr_Cb2G[Cb]) >> 16)

[Color]深入学习YUV色彩模型 V1.1

2007年11月12日 Galaxy 没有评论

http://blog.csdn.net/zyl910/archive/2006/05/25/753814.aspx

[Color]深入学习YUV色彩模型 V1.1  

File:      StudyYUV.txt
Name:      深入学习YUV色彩模型
Author:    zyl910
Version:   V1.1
Updata:    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*U
R = 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*U
R = Y + 1.140*V
G = 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*B
U = (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*B
U = (1 / 2.032)*(B-Y)
V = (1 / 1.140)*(R-Y)

  YUV转RGB:
B = Y + 2.032*U
R = Y + 1.140*V
G = 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) >> 16
U = 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)

[Color]彩色转灰度算法彻底学习

2007年11月12日 Galaxy 没有评论

http://blog.csdn.net/zyl910/archive/2006/05/22/749752.aspx

[Color]彩色转灰度算法彻底学习  

File:      StudyRGB2Gray.txt
Name:      彩色转灰度算法彻底学习
Author:    zyl910
Version:   V1.0
Updata:    2006-5-22

一、基础

  对于彩色转灰度,有一个很著名的心理学公式:
Gray = R*0.299 + G*0.587 + B*0.114

二、整数算法

  而实际应用时,希望避免低速的浮点运算,所以需要整数算法。
  注意到系数都是3位精度的没有,我们可以将它们缩放1000倍来实现整数运算算法:
Gray = (R*299 + G*587 + B*114 + 500) / 1000

  RGB一般是8位精度,现在缩放1000倍,所以上面的运算是32位整型的运算。注意后面那个除法是整数除法,所以需要加上500来实现四舍五入。
  就是由于该算法需要32位运算,所以该公式的另一个变种很流行:
Gray = (R*30 + G*59 + B*11 + 50) / 100

  但是,虽说上一个公式是32位整数运算,但是根据80×86体系的整数乘除指令的特点,是可以用16位整数乘除指令来运算的。而且现在32位早普及了(AMD64都出来了),所以推荐使用上一个公式。

三、整数移位算法

  上面的整数算法已经很快了,但是有一点仍制约速度,就是最后的那个除法。移位比除法快多了,所以可以将系数缩放成 2的整数幂。
  习惯上使用16位精度,2的16次幂是65536,所以这样计算系数:
0.299 * 65536 = 19595.264 ≈ 19595
0.587 * 65536 + (0.264) = 38469.632 + 0.264 = 38469.896 ≈ 38469
0.114 * 65536 + (0.896) =  7471.104 + 0.896 = 7472

  可能很多人看见了,我所使用的舍入方式不是四舍五入。四舍五入会有较大的误差,应该将以前的计算结果的误差一起计算进去,舍入方式是去尾法:

  写成表达式是:
Gray = (R*19595 + G*38469 + B*7472) >> 16

  2至20位精度的系数:
Gray = (R*1 + G*2 + B*1) >> 2
Gray = (R*2 + G*5 + B*1) >> 3
Gray = (R*4 + G*10 + B*2) >> 4
Gray = (R*9 + G*19 + B*4) >> 5
Gray = (R*19 + G*37 + B*8) >> 6
Gray = (R*38 + G*75 + B*15) >> 7
Gray = (R*76 + G*150 + B*30) >> 8
Gray = (R*153 + G*300 + B*59) >> 9
Gray = (R*306 + G*601 + B*117) >> 10
Gray = (R*612 + G*1202 + B*234) >> 11
Gray = (R*1224 + G*2405 + B*467) >> 12
Gray = (R*2449 + G*4809 + B*934) >> 13
Gray = (R*4898 + G*9618 + B*1868) >> 14
Gray = (R*9797 + G*19235 + B*3736) >> 15
Gray = (R*19595 + G*38469 + B*7472) >> 16
Gray = (R*39190 + G*76939 + B*14943) >> 17
Gray = (R*78381 + G*153878 + B*29885) >> 18
Gray = (R*156762 + G*307757 + B*59769) >> 19
Gray = (R*313524 + G*615514 + B*119538) >> 20

  仔细观察上面的表格,这些精度实际上是一样的:3与4、7与8、10与11、13与14、19与20
  所以16位运算下最好的计算公式是使用7位精度,比先前那个系数缩放100倍的精度高,而且速度快:
Gray = (R*38 + G*75 + B*15) >> 7

  其实最有意思的还是那个2位精度的,完全可以移位优化:
Gray = (R + (WORD)G<<1 + B) >> 2

  由于误差很大,所以做图像处理绝不用该公式(最常用的是16位精度)。但对于游戏编程,场景经常变化,用户一般不可能观察到颜色的细微差别,所以最常用的是2位精度。

阅读全文…

Locations of visitors to this page