RGB与YUV相互转换

从前文已经知道,R,G,B,3个分量都跟 亮度密切相关,也就是 3个分量里面都有大量的亮度信息。

RGB 转 YUV 的过程实际上就是 把 RGB 3分量里面的亮度信息 提取出来,放到 Y 分量。再把 RGB 3分量里面的 色调 ,色饱和度 信息提取出来放到 U跟 V分量。

所以这是一个信息提取过程,需要经过大量的实验。

提取 Y 亮度信息的公式如下: Y=KrR+KgG+KbB Y = Kr * R + Kg * G + Kb * B 上面公式中的 K 是一个权重因子,Kr 代表 红色通道的权重,Kg 代表 绿色通道的权重,Kb 代表 绿色通道的权重,而且 Kr + Kg + Kb = 1

Cb 的定义是 B - Y 的差值,如下: Cb=BY Cb = B - Y Cr 的定义是 R - Y 的差值,如下: Cr=RY Cr = R - Y Cg 的定义是 G - Y 的差值,如下: Cg=GY Cg = G - Y 上面的 Cb 就是 U 分量,V 是 Cr 分量。我们实际编码存储,或者传输的时候,是不需要用到 Cg 的。从上面的公式 可以看出,只需要知道 Y 跟 Cb 就能求 B 的值,知道 Y 跟 Cr 就能求 R 的值。知道 Y ,R 跟 B 就能根据第一条公式求到 G 的值。所以 Cg 没必要存储。Cr + Cb + Cg 其实是一个常量。



因为 K 权重因子是需要经过大量的实验才能得到,经过实验研究后发现,K 权重因子 会影响压缩率,所以产生了以下标准。

1. BT.601标准[1]——标清数字电视(SDTV) Y=0.299R+0.587G+0.114B Y = 0.299R + 0.587G + 0.114B 2. BT.709标准[2]——高清数字电视(HDTV) Y=0.2126R+0.7152G+0.0722B Y = 0.2126R + 0.7152G + 0.0722B 3. BT.2020标准[3]——超高清数字电视(UHDTV) Y=0.2627R+0.6780G+0.0593B Y = 0.2627R + 0.6780G + 0.0593B 因为某些原因,亮度这个信息,不能完完全全 从 RGB 里面提取出来,总会残留一些亮度信息在 RGB 里面没提取到。所以 K 权重因子 根据不同标准也是不同的。

BT.2020标准 生成的 YUV 数据在 编码系统里面的压缩率 是比 BT.709 小的,虽然现在还没开始进行编码压缩,但是确确实实,K权重因子会影响压缩效果。

本文主要讲解的是 BT.601 标准里面的计算公式。


根据 ITU BT.601 标准 的定义,Kb = 0.114 ,Kr = 0.299 ,所以 Kg = 0.587 ,Y 的计算公式如下: Y=0.299R+0.587G+0.114B Y = 0.299R + 0.587G + 0.114B 可以这么理解上面这个公式,Kr + Kg + Kb 一定是等于1的。上面这个公式认为,在 R 通道里面有 29.9% 的亮度信息,在 G通道 有 58.7% 的亮度信息,在 B通道 有 11.4% 的亮度信息。

这里贴 一个 601 文档的一个截图:

raw-yuv-to-rgb-1-1

我转述一下上图的意思,由于 Y 值 空间范围是 0 ~ 1,而 R - Y 的 空间范围是 -0.701 ~ +0.701 ,因为 R 值的空间范围大小 是 1.402 ,Y 的大小是 1 ,R的大小是 1.402 ,度量单位不一样不能相减,所以需要换算成一样的,就是以下的公式。 Cr=R/1.402Y/1 Cr = R/1.402 - Y/1

Cr=1/1.402RY Cr = 1/1.402 * R -Y

Cr=0.713(RY) Cr = 0.713 * (R - Y)

然后 B 值的空间范围大小是 1.772 ,不能直接减 Y,需要换一下: Cb=R/1.772Y/1 Cb = R/1.772 - Y/1

Cb=0.564(BY) Cb = 0.564 * ( B - Y ) 根据以上公式,就能把 RGB 转成 YCrCb。

扩展知识:YCrCb 的转换算法,其实是有近似算法的,为了计算速度,某些场景可以使用近似算法。


下面讲一下 如何 把 YCrCb 转成 RGB ,Y,Cr 跟 Cb 这 3个是已知值。

因为 Cr = 0.713 * (R - Y) ,所以换算一下,把R 弄到前面,如下: RY=Cr/0.713 R - Y = Cr /0.713

R=1/0.713Cr+Y R = 1/0.713 * Cr + Y

R=1.402Cr+Y R = 1.402 * Cr + Y

因为 Cb = 0.564 * (B - Y) ,所以换算一下,把 B 弄到前面,如下: B=Cb/0.546+Y B = Cb/0.546 + Y

B=1/0.564Cb+Y B = 1/0.564 * Cb + Y

B=1.772Cb+Y B = 1.772 * Cb + Y

至此, R 跟 B 已经求出来了。把R 跟 B 套进去以下公式: Y=0.299R+0.587G+0.114B Y = 0.299R + 0.587G + 0.114B

Y=0.299(1.402Cr+Y)+0.587G+0.114(1.772Cb+Y) Y = 0.299*( 1.402 * Cr + Y) + 0.587G + 0.114 * (1.772 * Cb + Y)

Y=(0.419Cr+0.299Y)+0.587G+(0.202Cb+0.202Y) Y = (0.419Cr + 0.299Y) + 0.587G + (0.202Cb + 0.202Y)

Y=0.419Cr+0.587G+0.202Cb+0.501Y Y = 0.419Cr + 0.587G + 0.202Cb + 0.501Y

0.499Y=0.419Cr+0.587G+0.202Cb 0.499Y = 0.419Cr + 0.587G + 0.202Cb

推导到这里,把 G 弄到前面,如下: 0.587G=0.499Y0.419Cr0.202Cb 0.587G = 0.499Y - 0.419Cr - 0.202Cb 两边同时除以 0.587 ,如下: G=0.850Y0.713Cr0.344Cb G = 0.850Y - 0.713Cr - 0.344Cb 最后算出来的公式就是上面那样,0.850 Y 减去 那两个东西,但是不知道为什么 很多技术书籍 跟实际工程代码中, G 的计算方式是 没有 前面那个 系数 0.850 的。如下: G=Y0.713Cr0.344Cb G = Y -0.713Cr - 0.344Cb 至于为什么 0.850 丢了,我也不知道,可能是允许这种误差吧,这里填个坑,后面埋。

补充 :讨论记录

参考文章:

1,RGB转YUV及YUV格式


版权所属 xianwanzhiyin.net 罗上文 2022 all right reserved,powered by Gitbook该文件修订时间: 2022-06-03 15:46:12

results matching ""

    No results matching ""