原文章网址 https://msdn.microsoft.com/zh-cn/library/ms867704.aspx
本页内容
简介
在 DirectShow 中标识 YUV 格式
YUV 采样
表面定义
颜色空间和色度采样率转换
其他信息
简介
-
在 DirectShow 中标识 YUV 格式 — 讲述了如何描述 Microsoft DirectShow® YUV 格式类型。
-
颜色空间和色度采样率转换 — 提供了一些在 YUV 和 RGB 格式之间进行转换的指南,以及在不同 YUV 格式之间进行转换的指南。
在 DirectShow 中标识 YUV 格式
本文讲述的每种 YUV 格式都指定了一个 FOURCC 码。FOURCC 码是一个 32 位、不带正负号的整数,它是通过串联四个 ASCII 字符创建而成的。
DWORD fccYUY2 = MAKEFOURCC('Y','U','Y','2'); DWORD fccYUY2 = FCC('YUY2');
只需通过调转字符的顺序,您还可以将 FOURCC 码直接声明为字符文本。例如:
DWORD fccYUY2 = '2YUY'; // Declares the FOURCC 'YUY2'
XXXXXXXX-0000-0010-8000-00AA00389B71
其中 XXXXXXXX 为 FOURCC 码。因此,YUY2 的子类型 GUID 为:
32595559-0000-0010-8000-00AA00389B71
FOURCCMap fccMap(FCC('YUY2')); GUID g1 = (GUID)fccMap; // Equivalent: GUID g2 = (GUID)FOURCCMap(FCC('YUY2'));
YUV 采样
YUV 的优点之一是,色度频道的采样率可比 Y 频道低,同时不会明显降低视觉质量。有一种表示法可用来描述 U 和 V 与 Y 的采样频率比例,这个表示法称为 A:B:C 表示法:
-
4:2:2 表示 2:1 的水平下采样,没有垂直下采样。对于每两个 U 样例或 V 样例,每个扫描行都包含四个 Y 样例。
-
4:1:1 表示 4:1 的水平下采样,没有垂直下采样。对于每个 U 样例或 V 样例,每个扫描行都包含四个 Y 样例。与其他格式相比,4:1:1 采样不太常用,本文不对其进行详细讨论。
图 1 显示了 4:4:4 图片中使用的采样网格。灯光样例用叉来表示,色度样例则用圈表示。
4:2:2 采样的这种主要形式在 ITU-R Recommendation BT.601 中进行了定义。图 2 显示了此标准定义的采样网格。
表面定义
本节讲述推荐用于视频呈现的 8 位 YUV 格式。这些格式可以分为几个类别:
推荐一个 4:4:4 格式,FOURCC 码为 AYUV。这是一个打包格式,其中每个像素都被编码为四个连续字节,其组织顺序如下所示。
两个都是打包格式,其中每个巨像素都是编码为四个连续字节的两个像素。这样会使得色度水平下采样乘以系数 2。
推荐两个 4:2:0 每像素 16 位格式,FOURCC 码如下:
两个 FOURCC 码都是平面格式。色度频道在水平方向和垂直方向上都要以系数 2 来进行再次采样。
此格式与 IMC1 相同,只是 U 和 V 平面进行了交换:
推荐四个 4:2:0 每像素 12 位格式,FOURCC 码如下:
在所有这些格式中,色度频道在水平方向和垂直方向上都要以系数 2 来进行再次采样。
此格式与 IMC2 相同,只是 U (Cb) 和 V (Cr) 行进行了交换:
颜色空间和色度采样率转换
Kr = 0.299 Kb = 0.114
第二个转换为 BT.709 中定义用于 60-Hz 的较新 YUV 格式,应该被视为用于高于 SDTV 的视频分辨率的首选格式。它的特征由下面两个不同的常量值来定义:
Kr = 0.2126 Kb = 0.0722
L = Kr * R + Kb * B + (1 – Kr – Kb) * G
Y = floor(2^(M-8) * (219*(L–Z)/S + 16) + 0.5) U = clip3(0, 2^M-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5)) V = clip3(0, 2^M-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5))
函数 floor(x) 返回大于或等于 x 的最大整数。函数 clip3(x, y, z) 的定义如下所示:
clip3(x, y, z) = ((z < x) ? x : ((z > y) ? y : z))
这些都是精确的公式,没有近似值。本文后面的所有内容均派生自这些公式。
在输入为计算机 RGB,输出为 8 位 BT.601 YUV 的情况下,我们相信前面一节中给出的公式可以按照下列公式进行合理近似计算:
Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16 U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128 V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128
这些公式使用精确度不大于 8 位(不带正负号)的系数计算出 8 位结果。中间结果需要最多 16 位的精确度。
从原始的 RGB 到 YUV 公式,您可以为 YUV 的 8 位 BT.601 定义派生出下列关系:
Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) + 16 U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128 V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128
C = Y - 16 D = U - 128 E = V - 128
将 YUV 转换为计算机 RGB 的公式可以按照下列方式进行派生:
R = clip( round( 1.164383 * C + 1.596027 * E ) ) G = clip( round( 1.164383 * C - (0.391762 * D) - (0.812968 * E) ) ) B = clip( round( 1.164383 * C + 2.017232 * D ) )
其中 clip() 表示剪辑为范围 [0..255]。这些公式可以由下列公式进行合理近似计算:
R = clip(( 298 * C + 409 * E + 128) >> 8) G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) B = clip(( 298 * C + 516 * D + 128) >> 8)
这些公式使用精确度必需大于 8 位的一些系数计算出每个 8 位结果,中间结果需要多于 16 位的精确度。
将 4:2:0 YUV 转换为 4:2:2 YUV 需要系数为 2 的垂直上转换。本节讲述了一个执行上转换的方法示例。该方法假设视频图片为逐行扫描。
注 4:2:0 到 4:2:2 隔行扫描转换过程会出现不常见的问题,难以实现。本文不会对转换从 4:2:0 到 4:2:2 的隔行扫描时出现的问题进行解决。
Cout[0] = Cin[0]; Cout[1] = clip((9 * (Cin[0] + Cin[1]) – (Cin[0] + Cin[2]) + 8) >> 4); Cout[2] = Cin[1]; Cout[3] = clip((9 * (Cin[1] + Cin[2]) - (Cin[0] + Cin[3]) + 8) >> 4); Cout[4] = Cin[2] Cout[5] = clip((9 * (Cin[2] + Cin[3]) - (Cin[1] + Cin[4]) + 8) >> 4); ... Cout[2*i] = Cin[i] Cout[2*i+1] = clip((9 * (Cin[i] + Cin[i+1]) - (Cin[i-1] + Cin[i+2]) + 8) >> 4); ... Cout[2*N-3] = clip((9 * (Cin[N-2] + Cin[N-1]) - (Cin[N-3] + Cin[N-1]) + 8) >> 4); Cout[2*N-2] = Cin[N-1]; Cout[2*N-1] = clip((9 * (Cin[N-1] + Cin[N-1]) - (Cin[N-2] + Cin[N-1]) + 8) >> 4);
注 用于处理边缘的等式在计算上可以进行简化。这些等式以这种形式显示,是为了说明图片边缘的附着效果。