音视频开发:RGB与YUV相互转换问题

本文档描述了RGB与YUV两个颜色空间的相互转换问题。

很多书在讲YUV颜色空间或YUV模型时,一般直接给出RGB与YUV的相互转换公式,比如这样:

(1)RGB转换成YUV

Y = 0.299R + 0.587G + 0.114B
U = 0.567(B - Y)
V = 0.713(R - Y)

值得注意的是,Y值范围为[0, 1.0]、UV值范围都是[-0.5, 0.5],在Accelerate框架的vImage_CVUtilities.h有描述。

(2)YUV转换成RGB

R = Y + 1.402V
G = Y - 0.344U - 0.714V
B = Y + 1.772U

对于JPEG图片,这两组公式的计算结果往往是正确的。然而,对于视频,这只处理了一种情况,即,这只是BT.601 Full Range转换矩阵。实际上,据我所知,还存在多个转换矩阵,部分转换矩阵可在GPUImage源码中找到应用。值得注意的是,GPUImage使用列矩阵存储。其中,ITU BT.601对应于标准分辨率电视(SDTV)、ITU BT.709对应于高分辨率电视(HDTV),几个常见的颜色转换矩阵分别是:

  • ITU BT.601 Full Range转换矩阵

    ITU BT.601 Full Range

GLfloat kColorConversion601FullRangeDefault[] = {
1.0, 1.0, 1.0,
0.0, -0.343, 1.765,
1.4, -0.711, 0.0,
};


- ITU BT.601默认转换矩阵

  ![ITU BT.601默认转换矩阵](http://upload-images.jianshu.io/upload_images/1613657-c90e9ab3f9d8d8d9.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

GLfloat kColorConversion601Default[] = {
1.164, 1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813, 0.0,
};


- ITU BT.709默认转换矩阵

  ![ITU BT.709默认转换矩阵](http://upload-images.jianshu.io/upload_images/1613657-dad726961c0f76d3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

GLfloat kColorConversion709Default[] = {
1.164, 1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533, 0.0,
};


- ITU BT.709 Full Range转换矩阵

  留空

由于OpenGL ES着色器中mat系列数据结构以列优先存储,意味着,**数据上传到着色器端将按列优先规则构造矩阵**,故GPUImage在保存转换矩阵时也以列矩阵表示。因此,在片段着色器中的计算为:

yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;


以ITU BT.601 Full Range为例,kColorConversion601FullRangeDefault * yuv可得到:

R = Y + 1.4V
G = Y - 0.343U - 0.711V
B = Y + 1.765U


基本等于文档开始提及的转换公式,个别小数部分内容不太一样,怀疑是舍入或大家相互抄袭导致书写错误。

其中,阐明了BT.601与BT.709的区别,这在很多书上是不作说明的,为刚接触视频开发的开发人员提供了参考。
full range我之前了解是[0, 255],video range把人眼察觉不到的范围给去掉了


**参考:**

- 数字图像处理与机器视觉——Visual C++与Matlab实现(第二版)

**推荐阅读:**

- [YCbCr](https://en.wikipedia.org/wiki/YCbCr)
- [R-REC-BT.709](https://www.itu.int/rec/R-REC-BT.709)

你可能感兴趣的:(音视频开发:RGB与YUV相互转换问题)