2021年6月9日 / 442次阅读 / Last Modified 2021年6月9日
图像处理
YCbCr与RGB分别表示两种不同的颜色空间,即用什么方式来表示pixel的颜色数据。YCbCr来自YUV这个术语(有人说是用于模拟时代),现在这两个词我感觉基本上指同样的东西。YCbCr的出现(或者YUV是的出现),是为了彩色电视和黑白电视的兼容,Y表示luma,视频码流中的亮度分量,黑白电视只能显示这个;再加上两个颜色分量Cb和Cr,就是彩色的了。
现在计算机内,颜色的显示都是RGB模式,而视频编解码使用的大多都是YCbCr信号(YCbCr提供了最初的数据压缩,主流的420采样模式,直接就砍掉了一半的视频数据,参考学习YCbCr)。因此,就有了相互转换的需要。
下面的转换系数不太对,好晕!看wiki吧:https://en.wikipedia.org/wiki/YUV
有3个转换标准,BT470<BT601(SDTV)和BT709(HDTV)。
BT470:
Y = 0.299*R + 0.587*G + 0.114*B
Cb = 0.564*(B - Y)
Cr = 0.713*(R - Y)
R = Y + 1.402*Cr
G = Y - 0.344*Cb - 0.714*Cr
B = Y + 1.772*Cb
从这个计算公式可看出,Cb和Cr有可能是负数,网上有人通过+128来规避,在转回RGB的时候,在-128。其实没必要,统一看做8bit的unsigned char数据即可!
考虑到计算速度,用矩阵计算的方式来转换也是可以的:
>>> to_yuv
array([[ 0.299, 0.587, 0.114],
[-0.169, -0.331, 0.5 ],
[ 0.5 , -0.419, -0.08 ]])
>>>
>>> to_rgb
array([[ 1. , 0. , 1.402],
[ 1. , -0.344, -0.714],
[ 1. , 1.772, 0. ]])
>>>
>>> a = np.array((12,23,34))
>>> a
array([12, 23, 34])
>>> to_rgb @ to_yuv @ a
array([12.052486, 22.972402, 34.005148])
BT709与BT601,只是转换系数上有点不同:
这个计算有性能需求,基本思路就是想办法避免浮点数计算,避免乘法,或者采用查表的方法!
-- EOF --
本文链接:https://www.pynote.net/archives/3708
《YCbCr与RGB的转换》有5条留言
Ctrl+D 收藏本页
©Copyright 麦新杰 Since 2019 Python笔记
Y的范围是 16到235 UV的范围是 16到240 RGB的范围是 0到255 [ ]
关于YUV的公式,除了有BT601/BT709协议,还有BT2020 协议 。BT2020的YUV转换公式和BT601 BT709都是不同的,但是两者的取值范围是相同的,一般HD视频(1080p)使用BT601 转换, UHDTV(4k或8K)使用BT2020协议转换 , 若视频信号中无色域标志或者色彩转换矩阵 , 默认使用BT601即可, ffmpeg转rgb也是这样操作的。 [ ]
UV和RGB互转要考虑的东西有两个一个是Matrix,是BT601还是BT709,还是4K时代的BT2020,,Ycgco不同的matrix的色彩范围不一样 数值也有差第二个是range,YUV里TV和PC显示器的数值范围不一样8bit位深的情况下TVrange是16-235(Y)、16-240(UV)PCrange是0-255而RGB没有range之分,全是0-255! [ ]
https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion,本文python代码部分,对应的数据应该是BT601 [ ]
https://en.wikipedia.org/wiki/YUV,看这个!! [ ]