多媒体基础知识之YUV数据

摘要:
此外,YUV不需要像RGB一样同时传输三个独立的视频信号,因此YUV传输占用的带宽非常小。YUV通常也称为YCbCr。Cb是蓝色色度分量,对应于U;Cr是对应于V的红色色度分量。平面YUV是合适的视频编码格式。这种YUV通常为4:2:0。例如:YYYYYYYYYYUVUVUVUV本例称为NV12格式。接下来,我将以图形的形式展示常见YUV码流的存储方法,并将每个像素的YUV数据采样方法附加到存储方法中。其中,Cb和Cr的含义与U和V相同。
1.什么是YUV格式

YUV,是一种颜色编码方法。Y表示明亮度(Luminance、Luma),也就是灰度值。U和V则是色度、浓度(Chrominance、Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。

与RGB格式相比,RGB格式用红绿蓝三个颜色分量来表示一个像素,YUV则是用一个亮度分量(Y)加两个色度分量来表示一个像素。YUV也经常被称为YCbCr,Cb为蓝色色度分量,对应U;Cr为红色色度分量,对应V。

2.YUV格式采样方式

YUV采样方式主要描述像素Y、U、V分量采样比例,即表达每个像素时,Y、U、V分量的数目,通常有三种方式:YUV4:4:4,YUV4:2:2,YUV4:2:0。

用三个图直观地表示采集的方式,以黑点表示采样该像点的Y分量,以空心圆圈表示采用该像素点的UV分量。

YUV4:4:4采样,每一个Y对应一组UV分量;YUV4:2:2采样,每两个Y共用一组UV分量;YUV4:2:0采样,每四个Y共用一组UV分量。

多媒体基础知识之YUV数据第1张

4:4:4表示没有色度通道的压缩采样。

4:2:2表示2:1水平压缩采样,无垂直压缩采样。 

4:2:0表示2:1水平压缩采样,2:1垂直压缩采样。

3.YUV格式的存储方式

YUV存储格式,主要描述像素的Y、U、V分量排列方式,分为两种格式:紧缩格式和平面格式。

紧缩格式(packed formats):将Y、U、V值储存成Macro Pixels阵列,和RGB的存放方式类似。每个像素点的Y,U,V是连续交差存储的。

这种YUV经常用在网络摄像机里,且大多是4:2:2的也就是只有在水平方向下采样。例如

UYVYUYVYUYVYUYVYUYVYUYVYUYVYUYVY

平面格式(planar formats):将Y、U、V的三个分量分别存放在不同的矩阵中。先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。

planar的YUV是比较合适视频编码的一种格式。像下面这样的4x4的图像

YYYYYYYYYYYYYYYY UUUU VVVV

这个例子所示的YUV常被称为YUV420P,其水平和竖直方向上均为每两个亮度分量才有一个色度分量,也就是每四个Y才需要一个U和V。除这种水平和竖直方向的色度分量都下采样的4:2:0,还有只有水平方向下采样的4:2:2格式,以及没有下采样的4:4:4格式。

上面的例子是按Y、U、V(YCbCr)的顺序存储的,如果改为Y、V、U(YCrCb),则称为YV12格式。

Semi-planar格式

这是Planar和Packed两种格式的混合体:Y分量单独一个plane,U和V则交叉存储。这种YUV一般都是4:2:0的。例如:

YYYYYYYYYYYYYYYY UVUVUVUV

这个示例称为NV12格式。如果交换UV的顺序,就成了NV21格式。NV21是Android系统中摄像头预览图片的默认格式。

下面我用图的形式给出常见的YUV码流的存储方式,并在存储方式后面附有取样每个像素点的YUV数据的方法,其中,Cb、Cr的含义等同于U、V。

(1) YUYV 格式 (属于YUV422   Packed format

Byte Order. Each cell is one byte.

start + 0:Y’00Cb00Y’01Cr00Y’02Cb01Y’03Cr01
start + 8:Y’10Cb10Y’11Cr10Y’12Cb11Y’13Cr11
start + 16:Y’20Cb20Y’21Cr20Y’22Cb21Y’23Cr21
start + 24:Y’30Cb30Y’31Cr30Y’32Cb31Y’33Cr31

Color Sample Location

 0 1 2 3
0YCY YCY
1YCY YCY
2YCY YCY
3YCY YCY

Packed format with ½ horizontal chroma resolution, also known as YUV 4:2:2

1/2水平色度分辨率采样的打包格式,也被称为YUV 4:2:2

In this format each four bytes is two pixels. Each four bytes is two Y’s, a Cb and a Cr. Each Y goes to one of the pixels, and the Cb and Cr belong to both pixels. As you can see, the Cr and Cb components have half the horizontal resolution of the Y component. V4L2_PIX_FMT_YUYV is known in the Windows environment as YUY2.

在这种格式中,每4个字节是两个像素,每4个字节上有两个Y分量,一个U和一个V分量。没个像素都有一个Y分量,两个像素共用一个U和一个V分量。

U和V分量在水平方向上的采样只有Y的一半,V4L2_PIX_FMT_YUYV在Windows环境中被称为YUY2。

(YUYV为YUV422采样的存储格式中的一种,相邻的两个Y共用其相邻的两个Cb、Cr,分析,对于像素点Y'00、Y'01 而言,其Cb、Cr的值均为 Cb00、Cr00,其他的像素点的YUV取值依次类推。)

(2) UYVY 格式 (属于YUV422   Packed format

Byte Order. Each cell is one byte.

start + 0:Cb00Y’00Cr00Y’01Cb01Y’02Cr01Y’03
start + 8:Cb10Y’10Cr10Y’11Cb11Y’12Cr11Y’13
start + 16:Cb20Y’20Cr20Y’21Cb21Y’22Cr21Y’23
start + 24:Cb30Y’30Cr30Y’31Cb31Y’32Cr31Y’33

Color Sample Location 

 0 12 3
0YCYYCY
1YCYYCY
2YCYYCY
3YCYYCY

Variation of V4L2_PIX_FMT_YUYV with different order of samples in memory

UYVY格式也是YUV422采样的存储格式中的一种,只不过与YUYV不同的是UV的排列顺序不一样而已,还原其每个像素点的YUV值的方法与上面一样。

(3) YUV422P(属于YUV422 Planar format)

Byte Order. Each cell is one byte.

start + 0:Y’00Y’01Y’02Y’03
start + 4:Y’10Y’11Y’12Y’13
start + 8:Y’20Y’21Y’22Y’23
start + 12:Y’30Y’31Y’32Y’33
start + 16:Cb00Cb01
start + 18:Cb10Cb11
start + 20:Cb20Cb21
start + 22:Cb30Cb31
start + 24:Cr00Cr01
start + 26:Cr10Cr11
start + 28:Cr20Cr21
start + 30:Cr30Cr31

Color Sample Location

 0 12 3
0YCYYCY
1YCYYCY
2YCYYCY
3YCYYCY

Format with ½ horizontal chroma resolution, also known as YUV 4:2:2. Planar layout as opposed to V4L2_PIX_FMT_YUYV

1/2水平色度分辨率采样,也称为YUV 4:2:2。 和V4L2_PIX_FMT_YUYV不同的是,它是平面布局的

This is a planar version of the YUYV format. The three components are separated into three sub-images or planes. The Y plane is first. The Y plane has one byte per pixel. The Cb plane immediately follows the Y plane in memory. The Cb plane is half the width of the Y plane (and of the image). Each Cb belongs to two pixels. For example, Cb0 belongs to Y’00, Y’01. Following the Cb plane is the Cr plane, just like the Cb plane.

这是YUYV格式的平面版本。 三个分量被分成三个子图像或平面,分别存放在三个不同的矩阵中。 首先存放Y分量。 每一个像素都有一个Y分量。 Cb分量紧跟着Y分量存储。 Cb分量是Y分量的宽度的一半。 每个Cb分量属于两个像素。 例如,Cb0属于Y'00,Y'01。 Cb分量之后是Cr分量,它和Cb分量一样。

(YUV422P也属于YUV422的一种,它是一种Planar模式,即平面模式,并不是将YUV数据交错存储,而是先存放所有的Y分量,然后存储所有的U(Cb)分量,最后存储所有的V(Cr)分量,如上图所示。其每一个像素点的YUV值提取方法也是遵循YUV422格式的最基本提取方法,即两个Y共用一个UV。比如,对于像素点Y'00、Y'01 而言,其Cb、Cr的值均为 Cb00、Cr00)

(4)YV12,YU12格式(属于YUV420 planar format)

Byte Order. Each cell is one byte. 

start + 0:Y’00Y’01Y’02Y’03
start + 4:Y’10Y’11Y’12Y’13
start + 8:Y’20Y’21Y’22Y’23
start + 12:Y’30Y’31Y’32Y’33
start + 16:Cr00Cr01
start + 18:Cr10Cr11
start + 20:Cb00Cb01
start + 22:Cb10Cb11

Color Sample Location 

 0 1 2 3
0Y Y Y Y
  C   C 
1Y Y Y Y
 
2Y Y Y Y
  C   C 
3Y Y Y Y

V4L2_PIX_FMT_YUV420 Planar formats with ½ horizontal and vertical chroma resolution, also known as YUV 4:2:0

V4L2_PIX_FMT_YUV420是1/2水平和垂直色度分辨率采样的平面格式,也称为YUV 4:2:0

V4L2_PIX_FMT_YVU420 (‘YV12’) and  V4L2_PIX_FMT_YUV420 (‘YU12’) are planar formats, as opposed to a packed format. The three components are separated into three sub- images or planes. The Y plane is first. The Y plane has one byte per pixel. For V4L2_PIX_FMT_YVU420, the Cr plane immediately follows the Y plane in memory. The Cr plane is half the width and half the height of the Y plane (and of the image). Each Cr belongs to four pixels, a two-by-two square of the image. For example, Cr0 belongs to Y’00, Y’01, Y’10, and Y’11. Following the Cr plane is the Cb plane, just like the Cr plane. V4L2_PIX_FMT_YUV420 is the same except the Cb plane comes first, then the Cr plane.

V4L2_PIX_FMT_YVU420 (‘YV12’) 和 V4L2_PIX_FMT_YUV420 (‘YU12’),是planar模式, 三个分量被分成三个子图像或平面,分别存放在三个不同的矩阵中。首先存放Y分量。 每一个像素都有一个Y分量,对于V4L2_PIX_FMT_YVU420格式,Cr分量紧跟着Y分量存储Cr分量的长度和宽度各是Y分量的一半,每个Cr分量属于4个像素(一个2x2的图像)例如,Cr0属于Y'00,Y'01,Y'10和Y'11。 Cr分量之后是Cb分量,它和Cr分量一样。V4L2_PIX_FMT_YUV420和V4L2_PIX_FMT_YVU420是相同的,只是在存储方式上Cb分量在前,然后是Cr分量。

(YU12和YV12属于YUV420格式,也是一种Planar模式,将Y、U、V分量分别打包,依次存储。其每一个像素点的YUV数据提取遵循YUV420格式的提取方式,即4个Y分量共用一组UV。注意,上图中,Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00,其他依次类推。)

(5)NV12、NV21(属于YUV420)

Byte Order. Each cell is one byte. 

start + 0:Y’00Y’01Y’02Y’03
start + 4:Y’10Y’11Y’12Y’13
start + 8:Y’20Y’21Y’22Y’23
start + 12:Y’30Y’31Y’32Y’33
start + 16:Cb00Cr00Cb01Cr01
start + 20:Cb10Cr10Cb11Cr11

Color Sample Location 

 0 12 3
0Y YY Y
  C  C 
1Y YY Y
 
2Y YY Y
  C  C 
3Y YY Y

V4L2_PIX_FMT_NV21 Formats with ½ horizontal and vertical chroma resolution, also known as YUV 4:2:0. One luminance and one chrominance plane with alternating chroma samples as opposed to V4L2_PIX_FMT_YVU420

V4L2_PIX_FMT_NV21是是1/2水平和垂直色度分辨率采样的平面格式,也称为YUV 4:2:0。与V4L2_PIX_FMT_YVU420不同的是,它具有交替的色度采样(即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane)

V4L2_PIX_FMT_NV12 (‘NV12’) and V4L2_PIX_FMT_NV21 (‘NV21’) are two-plane versions of the YUV 4:2:0 format. The three components are separated into two sub-images or planes. The Y plane is first. The Y plane has one byte per pixel. For V4L2_PIX_FMT_NV12, a combined CbCr plane immediately follows the Y plane in memory. The CbCr plane is the same width, in bytes, as the Y plane (and of the image), but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example, Cb0/Cr0 belongs to Y’00, Y’01, Y’10, Y’11. V4L2_PIX_FMT_NV21 is the same except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.

V4L2_PIX_FMT_NV12('NV12')和V4L2_PIX_FMT_NV21('NV21')是 YUV 4:2:0 的 two-plane 版, 三个分量分成两个子图像或平面。首先存放Y分量。 每一个像素都有一个Y分量 ,对于V4L2_PIX_FMT_NV12格式,组合的CbCr分量紧跟着Y分量存储。 CbCr分量与Y分量宽度相同(以字节为单位),但是像素的高度是Y分量的一半。 每个CbCr对都属于四个像素。 例如,Cb0 / Cr0属于Y'00,Y'01,Y'10,Y'11。 除了Cb和Cr字节被交换之外,V4L2_PIX_FMT_NV21是相同的,CrCb分量以Cr字节开头。

(NV12和NV21属于YUV420格式,是一种two-plane(Semi-planar)模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00)

4.YUV格式转换

4.1.YUV分量转换为NV12

void convertYUVpitchtoNV12(unsigned char *yuv_luma, unsigned char *yuv_cb, unsigned char *yuv_cr,
    unsigned char *nv12_luma, unsigned char *nv12_chroma,
    int width, int height, int srcStride, int dstStride)
{
    int y;
    int x;
    if (srcStride == 0)
        srcStride = width;
    if (dstStride == 0)
        dstStride = width;

    //内存地址中,前width * height 存Y分量
    //之后的width * height * 1/2 交叉着存U和V分量

    //拷贝Y分量
    for (y = 0; y < height; y++)
    {
        //第一次拷贝nv12_lume基地址,即第一行
        //第二次拷贝第二行 。。。。
        memcpy(nv12_luma + (dstStride*y), yuv_luma + (srcStride*y), width);
    }
    //拷贝UV分量
    for (y = 0; y < height / 2; y++)
    {
        //每次步进两个位置
        for (x = 0; x < width; x = x + 2)
        {
            //UV分量是交叉存的
            //nv12_chroma[0]存yuv_cb[0],nv12_chroma[1]存yuv_cr[0]
            //nv12_chroma[2]存yuv_cb[1],nv12_chroma[3]存yuv_cr[1]
            // ....
            nv12_chroma[(y*dstStride) + x] = yuv_cb[((srcStride / 2)*y) + (x >> 1)];
            nv12_chroma[(y*dstStride) + (x + 1)] = yuv_cr[((srcStride / 2)*y) + (x >> 1)];
        }
    }
}

4.2.YUY2转换为I420

#define uint8_t BYTE
void YUY2toI420(int inWidth, int inHeight, uint8_t *pSrc, uint8_t *pDest)
{
    int i, j;
    //首先对I420的数据整体布局指定
    uint8_t *u = pDest + (inWidth * inHeight);
    uint8_t *v = u + (inWidth * inHeight) / 4;
 
    for (i = 0; i < inHeight/2; i++)
    {
        /*采取的策略是:在外层循环里面,取两个相邻的行*/    
        uint8_t *src_l1 = pSrc + inWidth*2*2*i;//因为4:2:2的原因,所以占用内存,相当一个像素占2个字节,2个像素合成4个字节
         uint8_t *src_l2 = src_l1 + inWidth*2;//YUY2的偶数行下一行
         uint8_t *y_l1 = pDest + inWidth*2*i;//偶数行
         uint8_t *y_l2 = y_l1 + inWidth;//偶数行的下一行
         for (j = 0; j < inWidth/2; j++)//内层循环
         {
            // two pels in one go//一次合成两个像素
            //偶数行,取完整像素;Y,U,V;偶数行的下一行,只取Y
            *y_l1++ = src_l1[0];//Y
            *u++ = src_l1[1];//U
            *y_l1++ = src_l1[2];//Y
            *v++ = src_l1[3];//V
            //这里只有取Y
            *y_l2++ = src_l2[0];
            *y_l2++ = src_l2[2];
            //YUY2,4个像素为一组
            src_l1 += 4;
            src_l2 += 4;
         }
    }
}

参考:

https://linuxtv.org/downloads/v4l-dvb-apis-new/uapi/v4l/yuv-formats.html

http://wenzongliang.iteye.com/blog/1902608

免责声明:文章转载自《多媒体基础知识之YUV数据》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android 5兆芯 服务器 win2012/win7装机总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

每次都能让人头大的 Shader -- 从一次简单的功能说起

  最近有个功能, 要渲染从主相机视角看到的另一个相机的可视范围和不可见范围, 大概如下图 :    简单来说就是主相机视野和观察者相机视野重合的地方, 能标记出观察者相机的可见和不可见, 实现原理就跟 ShadowMap 一样, 就是有关深度图, 世界坐标转换之类的, 每次有此类的功能都会很悲催, 虽然它的逻辑很简单, 可是用Unity3D做起来很麻烦...

使用lockbits方法处理图像(转)

   许多图像处理任务即时是最简单的文件类型转换,例如从32位深度到8位深度的格式转化,直接获得像素阵列要比使用GetPixel和SetPixel等方法的效率高得多。         你可能会发现DotNet采用托管机制,大多数情况下微软会推荐你使用托管代码,理由是便捷和安全。实际应用中,直接操作内存中的数据块是很少见的,尽管如此,图像处理恰恰是这类为数...

字体单位大小对照换算表(字号、磅、英寸、像素)

字号“数值”越大,字就越小。   中文字号 英文字号(磅) 毫米 像素 1英寸 72pt 25.30mm 95.6px  大特号 63pt 22.14mm 83.7px 特号 54pt 18.97mm 71.7px  初号 42pt 14.82mm 56px 小初 36pt 12.70mm 48px 一号 26pt 9.17mm...

颜色空间模型 与 Opencv中的HSV模型范围

颜色空间总结 RGB、HSV、YUV 什么是颜色 Wiki是这样说的:颜色或色彩是通过眼、脑和我们的生活经验所产生的一种对光的视觉效应。嗯,简单点说,颜色就是人对光的一种感觉,由大脑产生的一种感觉。感觉是一个很主观的东西,你怎么确定你看到的红色和我看到的是一样的呢?这个视频解释的很不错。我们需要先假设正常人对于同一种光产生的感觉基本是一致的,讨论才能继...

OpenCV学习(13) 细化算法(1)

程序编码参考经典的细化或者骨架算法文章: T. Y. Zhang and C. Y. Suen, “A fast parallel algorithm for thinning digital patterns,” Comm. ACM, vol. 27, no. 3, pp. 236-239, 1984. 它的原理也很简单:       我们对一副二值图像...

图像处理之YUV编码

RGB颜色空间 最常用的用途就是显示器系统,通过RGB数字驱动RGB电子枪发射电子,并激发显示屏上的荧光粉发出不同亮度的光线,并通过混合产生各种颜色。在RGB颜色空间中,任意色光F都可以用R、G、B三色不同分量的相加混合而成 YUV编码系统 YUV是一种彩色编码系统,相比于RGB颜色空间(用红绿蓝三基色描述),设计YUV的目的就是为了编码、传输的方便,减少...