RGB与YUV相互转换—音视频基础知识
作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音
从前文已经知道,R,G,B,3个分量都跟 亮度密切相关,也就是 3个分量里面都有大量的亮度信息。
RGB 转 YUV 的过程实际上就是 把 RGB 3分量里面的亮度信息 提取出来,放到 Y 分量。再把 RGB 3分量里面的 色调 ,色饱和度 信息提取出来放到 U跟 V分量。
所以这是一个信息提取过程,需要经过大量的实验。
提取 Y 亮度信息的公式如下:
Y=Kr∗R+Kg∗G+Kb∗B
上面公式中的 K 是一个权重因子,Kr
代表 红色通道的权重,Kg
代表 绿色通道的权重,Kb
代表 蓝色通道的权重,这三个权重加起来等于 1,如下:
Kr+Kg+Kb=1
Cb
的定义是 B - Y 的差值,如下:
Cb=B−Y
Cr
的定义是 R - Y 的差值,如下:
Cr=R−Y
Cg
的定义是 G - Y 的差值,如下:
Cg=G−Y
上面的 Cb
就是 U 分量,Cr
是 V 分量。我们实际编码存储,或者传输的时候,是不需要用到 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
2. BT.709标准[2]——高清数字电视(HDTV)
Y=0.2126R+0.7152G+0.0722B
3. BT.2020标准[3]——超高清数字电视(UHDTV)
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
可以这么理解上面这个公式,Kr + Kg + Kb 一定是等于1的。上面这个公式认为,在 R 通道里面有 29.9% 的亮度信息,在 G通道 有 58.7% 的亮度信息,在 B通道 有 11.4% 的亮度信息。
所以 Cr
的计算过程如下:
Cr=R−Y
R−Y=R−0.299R−0.587G−0.114B
R−Y=0.701R−0.587G−0.114B
由于 R,G,B 的取值范围是 0 ~ 1,所以当 R = 1,G = 0,B = 0 时,R - Y 能得到最大的值,如下:
R−Y=0.701∗1−0.587∗0−0.114∗0
R−Y=0.701=max_value
当 R = 0,G = 1,B = 1时,R - Y 能得到最小的值,如下:
R−Y=0.701∗0−0.587∗1−0.114∗1
R−Y=−0.701=min_value
因此 Cr
的空间范围是 -0.701 ~ 0.701
,范围大小是 1.402,但是由于 Cr
需要跟 Y 一起传输,而 Y 的空间范围大小是 1。
所以 Cr = R - Y
要做归一化操作,就是除以 1.402。
所以就有下面的公式了:
Cr=(R−Y)/1.402
Cr=0.713∗(R−Y)
所以 Cb
的计算过程如下:
Cb=B−Y
B−Y=B−0.299R−0.587G−0.114B
B−Y=−0.299R−0.587G+0.886B
由于 R,G,B 的取值范围是 0 ~ 1,所以当 R = 0,G = 0,B = 1 时,B - Y 能得到最大的值,如下:
B−Y=−0.299∗0−0.587∗0+0.886∗1
B−Y=0.886=max_value
当 R = 1,G = 1,B = 0 时,B - Y 能得到最小的值,如下:
B−Y=−0.299∗1−0.587∗1+0.886∗0
B−Y=−0.886=min_value
因此 Cb
的空间范围是 -0.886 ~ 0.886
,范围大小是 1.772,但是由于 Cb
需要跟 Y 一起传输,而 Y 的空间范围大小是 1。
所以 Cb = B - Y
要做归一化操作,就是除以 1.772。
所以就有下面的公式了:
Cb=(B−Y)/1.772
Cb=0.564∗(B−Y)
扩展知识:YCbCr 的转换算法,其实是有近似算法的,为了计算速度,某些场景可以使用近似算法。
下面讲一下 如何 把 YCbCr
转成 RGB
。
Y
,Cr
跟 Cb
这 3个是已知值。
因为 Cr = 0.713 * (R - Y)
,所以换算一下,把R 弄到前面,如下:
R−Y=Cr/0.713
R=1/0.713∗Cr+Y
R=1.402∗Cr+Y
因为 Cb = 0.564 * (B - Y)
,所以换算一下,把 B 弄到前面,如下:
B=Cb/0.546+Y
B=1/0.564∗Cb+Y
B=1.772∗Cb+Y
至此, R 跟 B 已经求出来了。把R 跟 B 套进去以下公式:
Y=0.299R+0.587G+0.114B
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.114Y)
Y=0.419Cr+0.587G+0.202Cb+0.413Y
0.587Y=0.419Cr+0.587G+0.202Cb
推导到这里,把 G 弄到前面,如下:
0.587G=0.587Y−0.419Cr−0.202Cb
两边同时除以 0.587 ,如下:
G=Y−0.713Cr−0.344Cb
参考文章:
1,RGB转YUV及YUV格式
感谢 NETINT(镕铭微电子) 赞助《FFmpeg原理》免费版一书的服务器费用,下面是 VPU 产品介绍