颜色空间转换

BT601和BT709

由于在处理相机实时图像数据时,需要将相机采集的YUV数据转换为RGB,根据GPUImage的源码看到是有三种转换矩阵用于将YUV数据转换成RGB数据,分别是

// BT.601, which is the standard for SDTV.
GLfloat kColorConversion601Default[] = {
1.164,  1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813,   0.0,
};
// BT.601 full range (ref:http://www.equasys.de/colorconversion.html)
GLfloat kColorConversion601FullRangeDefault[] = {
1.0,    1.0,    1.0,
0.0,    -0.343, 1.765,
1.4,    -0.711, 0.0,
};

// BT.709, which is the standard for HDTV.
GLfloat kColorConversion709Default[] = {
1.164,  1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533,   0.0,
};

可以看到其中两个比较奇特的关键字即601和709,同时还有FullRange

fullRange和videoRange

在apple关于图像pixelformat的定义中有关于yuv格式的420v和420f的定义

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v', 
/* Bi-Planar Component Y'CbCr 8-bit 4:2:0, video-range (luma=[16,235] chroma=[16,240]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange  = '420f', 
/* Bi-Planar Component Y'CbCr 8-bit 4:2:0, full-range (luma=[0,255] chroma=[1,255]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct *

而fullRange和videoRange本身的意义是YUV颜色空间中 亮度部分 Y 的取值范围,fullRange的取值范围为luma=[0,255] chroma=[1,255],而videoRange是luma=[16,235] chroma=[16,240],另外chroma(Cb,Cr)即色度部分与亮度部分不同,始终为fullRange

YUV

初识颜色空间时,YUV应该是除了大家从小耳濡目染的RGB之外,最让人不明觉历的颜色空间了,它高端大气的名字再加上YUV本身420,422,411这些不同变形 所显示的复杂度更容易让人望而却步。不过本着天下事有难易乎,为之则难者亦易矣,不为则易者亦难矣的态度,我们来对YUV进行一个简明的学习
YUV是将人眼的感知考虑进来的用于对颜色彩色图像进行编码的颜色空间,根据维基百科的说法简化来说,YUV与YCbCr这两个概念之间界限比较模糊且是有部分重叠的,因为YUV是用于电视系统中模拟颜色信息的编码,而YCbCr适用于对以MPEG及JPEG为代表的视频及静态图片的压缩及传输等场景下对颜色信息的数字编码。而现在YUV通常用于计算机工业中称呼使用YCbCr进行编码的文件格式。而一个小常识是YUV3个分量分别都并不是缩写,而只是对应于xyz的一种坐标系代号而已。

YUV和RGB之间的转换

SDTV with BT601

BT601是用数字格式编码交错的模拟视频信号的标准,定义于SDTV标准中

//Wr,Wg,Wb,Umax,Vmax均为对应于各BT标准的
Wr = 0.299
Wg = 1 - Wr - Wb = 0.587
Wb = 0.114
Umax = 0.436
Vmax = 0.615
HDTV with BT709

BT 709标准调整了

Wr = 0.2126
Wr = 0.0722
GPUImage框架中同款的YCbCr与RGB转换规则, 应用于数字颜色信息编码的YCbCr应用于SDTV时,标准为BT601
颜色空间转换_第1张图片
bt601 videorange ycbcr 420v to rgb.png

在这种videoRange格式中,亮度和色度空间都留有footroom和headroom,部分原因是为了与模拟视频设备结合的场景,而一般典型的比如JPEG图像使用如下的颜色格式full range


颜色空间转换_第2张图片
bt601 fullrange ycbcr 420f to rgb.png

而对于HDTV,标准为BT709,由于使用的参数不同,与SDTV一样留有headroom和footroom,


颜色空间转换_第3张图片
bt709 ycbcr to rgb .png

所以对于videorange和fullrange对应的转换为RGB的fragmentshader分别为

//fullrange
varying highp vec2 textureCoordinate;

uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;

void main()
{
 mediump vec3 yuv;
 lowp vec3 rgb;
 
 yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
 yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
 rgb = colorConversionMatrix * yuv;
 
 gl_FragColor = vec4(rgb, 1);
}

//video range
varying highp vec2 textureCoordinate;

uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;

void main()
{
 mediump vec3 yuv;
 lowp vec3 rgb;
 
 yuv.x = texture2D(luminanceTexture, textureCoordinate).r - (16.0/255.0);
 yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
 rgb = colorConversionMatrix * yuv;
 
 gl_FragColor = vec4(rgb, 1);
}

你可能感兴趣的:(颜色空间转换)