HDR转SDR实践之旅(四)YUV转RGB矩阵推导

2,242 阅读5分钟

YUV和RGB的关系

HDR转SDR的第一步是解码出10位YUV纹理但是后续图像处理针对RGB,这个时候就需要YUV转RGB然而往往直接从网上复制的公式其实是错的,如下图所示用错公式会导致色差,本篇文章讲的就是如何根据YUV的色域、位深、范围推导出YUV格式转RGB(为了解决开发问题可以直接滑动到最后复制正确的公式)。如果你觉得有所收获,来给HDR转SDR开源代码点个赞吧,你的鼓励是我前进最大的动力。

image.png

YUV和RGB都是色彩模型(描述颜色的数学模型),如下图所示就是YUV和RGB的3D色彩模型,色彩模型包含了YUV和RGB的所有颜色。

Pasted Graphic 1.png

既然YUV和RGB都是色彩模型自然就可以相互转换啦,YUV是RGB的亮度和色度,下图展示了RGB和YUV相互转换时颜色通道的变化。

image.png

YUV转RGB流程

image.png

注意:

  1. YUV的范围不同转换流程是不一样的,上图中第一行没范围的YUV转换流程不需要位移缩放,第二行和第三行有范围限制的YUV(YCbCr)转换流程,YCbCr需要先位移缩放转换成YUV然后才能转换成RGB。
  2. YUV的位数不一样转换矩阵相同,但是YCbCr的位数不一样转换矩阵却不一样,因为YCbrCr位数不同导致范围也不一样。

YUV和RGB对应关系

对应关系

如下图所示YUV坐标系中里面有一个RGB的立方体,它表示了YUV和RGB的颜色对应关系。

Pasted Graphic 2.png

对应公式

那么YUV和RGB的对应关系具体是怎么样的?从YUV的定义中可知Y代表红绿蓝的比例混合,U代表蓝色与亮度Y的差量,V代表红色与亮度Y的差量,那么求RGB转YUV就是求混合比例,求YUV转RGB就是它的逆变化。如下图所示用公式展现了如何用混合比例实现RGB转YUV,其中KrKgKb就是RGB的混合比例。

image.png

注意:

  1. Kr+Kg+Kb=1使Y的范围归一化到[0,1]
  2. U在B-Y差量的基础上除以2*(1-kb)使U的范围归一化到 [-0.5,0.5] (V同理)
  3. UV归一化到[-0.5,0.5]而不是[0,1]是因为UV的中间值意味着无色度,无色度更适合用0表示,而[0,1]中间值是0.5,[-0.5,0.5]中间值是0,所以UV归一化到[-0.5,0.5]

那么用什么数值表示KrKgKb比例最合适呢?KrKgKb比例是为了从RGB算出亮度,而从后续的文章色域转换可知XYZ色彩空间的Y就代表了视觉亮度,那么RGB转换XYZ矩阵系数中间一行(RY, GY, BY)就是我们要找的KrKgKb比例,也是我们常见的RGB转灰度公式。

Pasted Graphic.png

YUV范围

电视机中的YUV又叫YCbCr(Cb是ColorBlue缩写,Cr是ColorRed缩写),YCbCr为了解决吉布斯现象对范围进行了调整,下图说明了正弦函数模拟原始信号时波形的峰值超过原始信号8.9%,需要缩小YCbCr的范围防止溢出,譬如8位YUV的范围是[0,255],那么8位YCbCr的范围就是Y[16,235]UV[16,240],25523523516=9.1\frac{255-235}{235-16}=9.1%略大于大于8.9%,1623516=7.3\frac{16}{235-16}=7.3%略小于8.9%。

GibbsPhenomenon_800.svg

YCbCr的范围又叫tv range、limit range,YUV的范围又叫full range、pc range,下图展示了YUV和YCbCr各种情况下的范围。

5e7eb9d9e1464faa95fa2500c73c3293_tplv-k3u1fbpfcp-zoom-1.png

注意:

  1. 10位YCbCr的范围是8位YCbCr的范围乘4,n位就是乘2n82^{n-8}
  2. 归一化YUV(0,0,0)代表黑色,8位YUV(0,0,0)却代表绿色,这也是为什么视频处理错误出现绿边而不是其他颜色的原因,默认值(0,0,0)就是绿色。

公式推导

虽然YUV转RGB公式内容略枯燥,但是如果不了解很容易用错公式导致颜色出现色差问题,其实理解了以后会发现YUV和RGB的转换挺有趣的,会有一种焕然大悟的感觉公式中每一个参数原来都是这么来的

BT709YUV转RGB

未命名文件 (9).jpg

BT709RGB转XYZ矩阵的第二行系数代入YUV转RGB公式中可得到BT709RGB转YUV矩阵

[YUV]=[0.2126000.7152000.0722000.1145720.3854280.5000000.5000000.4541530.045847][RGB]\begin{bmatrix} Y\\ U\\ V\\ \end{bmatrix} = \begin{bmatrix} 0.212600 & 0.715200 & 0.072200\\ -0.114572 & -0.385428 & 0.500000\\ 0.500000 & -0.454153 & -0.045847\\ \end{bmatrix} * \begin{bmatrix} R\\ G\\ B\\ \end{bmatrix}

BT709YUV转RGB矩阵只要求BT709RGB转YUV矩阵的逆矩阵

[RGB]=[1.0000000.0000001.5748001.0000000.1873240.4681241.0000001.8556000.000000][YUV]\begin{bmatrix} R\\ G\\ B\\ \end{bmatrix} = \begin{bmatrix} 1.000000 & -0.000000 & 1.574800\\ 1.000000 & -0.187324 & -0.468124\\ 1.000000 & 1.855600 & -0.000000\\ \end{bmatrix} * \begin{bmatrix} Y\\ U\\ V\\ \end{bmatrix}

BT2020YUV转RGB

未命名文件 (17).png BT2020RGB转XYZ矩阵的第二行系数代入YUV转RGB公式中可得到BT2020RGB转YUV矩阵

[YUV]=[0.2627000.6780000.0593000.1396300.3603700.5000000.5000000.4597860.040214][RGB]\begin{bmatrix} Y\\ U\\ V\\ \end{bmatrix} = \begin{bmatrix} 0.262700 & 0.678000 & 0.059300\\ -0.139630 & -0.360370 & 0.500000\\ 0.500000 & -0.459786 & -0.040214\\ \end{bmatrix} * \begin{bmatrix} R\\ G\\ B\\ \end{bmatrix}

BT2020YUV转RGB矩阵只要求BT2020RGB转YUV矩阵的逆矩阵

[RGB]=[1.0000000.0000001.4746001.0000000.1645530.5713531.0000001.8814000.000000][YUV]\begin{bmatrix} R\\ G\\ B\\ \end{bmatrix} = \begin{bmatrix} 1.000000 & -0.000000 & 1.474600\\ 1.000000 & -0.164553 & -0.571353\\ 1.000000 & 1.881400 & -0.000000\\ \end{bmatrix} * \begin{bmatrix} Y\\ U\\ V\\ \end{bmatrix}

YCbCr转RGB

未命名文件 (12).jpg

注意:

  1. 用位移矩阵把YCbCr移动到原点,8位YCbCr就是把原点(16,128,128)移动回(0,0,0),不同位数YCbCr再乘上2n82^{n-8}
  2. 用缩放矩阵把YCbCr缩放回原YUV大小,譬如8位YCbCr就是把长度(235-16,240-16,240-16)缩放回255,不同位数YCbCr再乘上2n82^{n-8}
  3. MyuvtorgbM_{yuvtorgb}就是YUV转RGB矩阵(full range)

归一化BT709YCbCr转RGB

未命名文件 (19).jpg

注意: YCbCr的范围是Y[0,1]UV[0.0627,0.9412],RGB的范围是[0,1]

8位BT709YCbCr转RGB

未命名文件 (11).jpg

注意: YCbCr的范围是Y[16,235]UV[16,240],RGB的范围是[0,255]

归一化BT2020YCbCr转RGB

未命名文件 (18).jpg

注意: YCbCr的范围是Y[0,1]UV[0.0627,0.9412],RGB的范围是[0,1]

10位BT2020YCbCr转RGB

image.png

注意: YCbCr的范围是Y[64,940]UV[16,960],RGB的范围是[0,1023]

所有YUV和RGB公式

在实际开发中,总不能每次都去算一遍,有没有已经计算好的资源可以参考?SKYUVMath中就有所有YUV和RGB转换矩阵,复制时注意里面的齐次矩阵是针对归一化的YUV和YCbCr。

问题思考

下面3个问题留给大家思考

  1. 为什么YCbCr的Y和CbCr范围不同?
  2. 为什么8位YCbCr的范围不直接用YUV[20,235]却用Y[16,235]CbCr[16,240]导致部分峰值小于吉布斯现象的8.9%呢?
  3. YUV转RGB推理过程中要用到的RGB转灰度公式是怎么算出来的?

系列文章

系列文章