YUV,是一种颜色编码方法,是编译true-color颜色空间(color space)的种类,Y’UV, YUV, YCbCr,YPbPr等专有名词都可以称为YUV,彼此有重叠。“Y”表示明亮度(Luminance、Luma),“U”和“V”则是色度、浓度(Chrominance、Chroma),Y’UV, YUV, YCbCr, YPbPr常常有些混用的情况,其中YUV和Y’UV通常用来描述模拟信号,而相反的YCbCr与YPbPr则是用来描述数位的影像信号,例如在一些压缩格式内MPEG、JPEG中,但在现今,YUV通常已经在电脑系统上广泛使用。
YUV Formats分成两个格式:
- 紧缩格式(packed formats):将Y、U、V值储存成Macro Pixels阵列,和RGB的存放方式类似。
- 平面格式(planar formats):将Y、U、V的三个分量分别存放在不同的矩阵中。
紧缩格式(packed format)中的YUV是混合在一起的,对于YUV4:4:4格式而言,用紧缩格式很合适的,因此就有了UYVY、YUYV等。平面格式(planar formats)是指每Y份量,U份量和V份量都是以独立的平面组织的,也就是说所有的U份量必须在Y分量后面,而V份量在所有的U份量后面,此一格式适用于采样(subsample)。平面格式(planar format)有I420(4:2:0)、YV12、IYUV等。
以下代码实现将YV12格式的视频帧转换为opencv IplImage结构(BGR排列方式)。
void Yv12ToImg(uchar *pin, IplImage* img)
{
uchar y, cb, cr;
int ySize = img->width * img->height;
int uSize = ySize / 4;
uchar *pY = pin;
uchar *pU = pY + ySize;
uchar *pV = pU + uSize;
uchar r, g, b;
int iheight = img->height;
int iwidth = img->width;
int hwidth = iwidth / 2;
uchar* p = (uchar*)(img->imageData);
for (int h = 0; h < iheight; h++)
{
for (int w = 0; w < iwidth; w++)
{
y = pY[h*iwidth + w];
int offuv = h/2 * hwidth + w/2;
cb = pU[offuv];
cr = pV[offuv];
b = uchar(bet(0, 255,(y + 1.772*(cb - 128))));
g = uchar(bet(0, 255, (y - 0.344*(cb - 128) - 0.714*(cr - 128))));
r = uchar(bet(0, 255, (y + 1.402*(cr - 128))));
int offw = w * 3;
p[offw] = b;
p[offw + 1] = g;
p[offw + 2] = r;
}
p += img->widthStep;
}
}