将YUV4:4:4转换为YUV4:2:2图像 [英] Convert YUV4:4:4 to YUV4:2:2 images

查看:195
本文介绍了将YUV4:4:4转换为YUV4:2:2图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

互联网上有很多关于YUV4:4:4到YUV4:2:2格式之间差异的信息,但是,我找不到任何有关如何将YUV4:4:4转换为YUV4的信息: 2:2。由于这种转换是使用软件执行的,我希望应该有一些开发人员已经完成了它并且可以引导我到描述转换算法的源。当然,软件代码会很好,但是访问理论就足以编写我自己的软件了。具体来说,我想知道像素结构以及转换过程中字节的管理方式。

There is a lot of information on the internet about the differences between YUV4:4:4 to YUV4:2:2 formats, however, I can not find anything that tells how to convert the YUV4:4:4 to YUV4:2:2. Since such conversion is performed using software, I was hoping that there should be some developers that have done it and could direct me to the sources that describe the conversion algorithm. Of course, the software code would be nice to have, but having the access to the theory would be sufficient enough to write my own software. Specifically, I would like to know pixel structure and how the bytes are managed during conversion.

我发现了几个类似的问题,例如这个这个无法回答我的问题。另外,我在摄影论坛上发布了这个问题,他们认为这是一个软件问题。

I found several similar questions like this and this, however, could not get my question answered. Also, I posted this question on the Photography forum, and they considered it as a software question.

推荐答案

你之所以找不到具体的描述,是因为有很多方法要做到这一点。

让我们从维基百科开始: https: //en.wikipedia.org/wiki/Chroma_subsampling#4:2:2

The reason why you can't find specific description, is that there are many ways to do it.
Lets start from Wikipedia: https://en.wikipedia.org/wiki/Chroma_subsampling#4:2:2


4:4:4:< br>
三个Y'CbCr组件中的每一个都具有相同的采样率,因此没有色度子采样。此方案有时用于高端胶片扫描仪和电影后期制作。

4:4:4:
Each of the three Y'CbCr components have the same sample rate, thus there is no chroma subsampling. This scheme is sometimes used in high-end film scanners and cinematic post production.


4:2:2:

两个色度分量以亮度采样率的一半进行采样:水平色度分辨率减半。这会将未压缩视频信号的带宽减少三分之一,几乎没有视觉差异。

4:2:2:
The two chroma components are sampled at half the sample rate of luma: the horizontal chroma resolution is halved. This reduces the bandwidth of an uncompressed video signal by one-third with little to no visual difference.

注意:术语YCbCr和YUV是可互换使用。

https://en.wikipedia.org/wiki/YCbCr

Note: Terms YCbCr and YUV are used interchangeably.
https://en.wikipedia.org/wiki/YCbCr


Y'CbCr经常与YUV颜色空间混淆,通常术语YCbCr和YUV可互换使用,导致有些困惑;当提到视频或数字形式的信号时,术语YUV主要是指Y'CbCr。

Y′CbCr is often confused with the YUV color space, and typically the terms YCbCr and YUV are used interchangeably, leading to some confusion; when referring to signals in video or digital form, the term "YUV" mostly means "Y′CbCr".

数据存储器排序:

同样有多种格式。

英特尔 IPP 文档定义了两个主要类别:Pixel-Order Image Formats和Planar Image Formats。

这里有一个很好的文档: https://software.intel.com/en-us/node/503876

请参阅此处: http://www.fourcc.org/yuv.php#NV12 对于YUV像素排列格式。

参考此处: http://scc.ustc.edu.cn/zlsc/sugon/intel/ipp/ipp_manual/IPPI/ippi_ch6/ch6_image_downsa用于下采样描述的mpling.htm#ch6_image_downsampling

Data memory ordering:
Again there is more than one format.
Intel IPP documentation defines two main categories: "Pixel-Order Image Formats" and "Planar Image Formats".
There is a nice documentation here: https://software.intel.com/en-us/node/503876
Refer here: http://www.fourcc.org/yuv.php#NV12 for YUV pixel arrangement formats.
Refer here: http://scc.ustc.edu.cn/zlsc/sugon/intel/ipp/ipp_manual/IPPI/ippi_ch6/ch6_image_downsampling.htm#ch6_image_downsampling for downsampling description.

让我们假设一个平面格式:

Let's assume a planar format:

YUV 4:4:4 data order: Y0 U0 V0  Y1 U1 V1  Y2 U2 V2  
YUV 4:2:2 data order: Y0 U0     Y1 V0 Y2  U1 Y3 V1  

每个元素都是一个字节,Y0是内存中的低位字节。

Each element is a single byte, and Y0 is the lower byte in memory.

转换算法:


  1. Naive sub-sampling:

    抛出每秒U / V组件:

    取U0,抛出U1,取V0并抛出V1 ...

    来源:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2

    目的地:Y0 U0 Y1 V0 Y2 U2 Y3 V2

    我不推荐它,因为它导致别名工件。

平均每个U / V对:< br>
取目的地U0等于源(U0 + U1)/ 2,V0相同...

来源:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2

目的地:Y0(U0 + U1)/ 2 Y1(V0 + V1)/ 2 Y2(U2 + U3)/ 2 Y3(V2 + V3)/ 2

Average each U/V pair:
Take Destination U0 equals source (U0+U1)/2, same for V0...
Source: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2
Destination: Y0 (U0+U1)/2 Y1 (V0+V1)/2 Y2 (U2+U3)/2 Y3 (V2+V3)/2

使用其他插值方法对U和V进行下采样(例如双三次插值)。

通常,与简单平均值相比,您将看不到任何差异。

Use other interpolation method for down-sampling U and V (bi-cubic interpolation for example).
Usually you will not be able to see any differences compared to simple average.






C实施:

这个问题没有标记为C,但我认为以下C实现可能会有所帮助。

以下代码转换按像素排序的YUV 4:4 :4到像素排序的YUV 4:2:2平均每个U / V对:

The question is not tagged as C, but I think the following C implementation may be helpful.
The following code converts pixel-ordered YUV 4:4:4 to pixel-ordered YUV 4:2:2 by averaging each U/V pair:

//Convert single row I0 from pixel-ordered YUV 4:4:4 to pixel-ordered YUV 4:2:2.
//Save the result in J0.
//I0 size in bytes is image_width*3
//J0 size in bytes is image_width*2
static void ConvertRowYUV444ToYUV422(const unsigned char I0[],
                                     const int image_width,
                                     unsigned char J0[])
{
    int x;

    //Process two Y,U,V triples per iteration:
    for (x = 0; x < image_width; x += 2)
    {
        //Load source elements
        unsigned char y0    = I0[x*3];                  //Load source Y element
        unsigned int u0     = (unsigned int)I0[x*3+1];  //Load source U element (and convert from uint8 to uint32).
        unsigned int v0     = (unsigned int)I0[x*3+2];  //Load source V element (and convert from uint8 to uint32).

        //Load next source elements
        unsigned char y1    = I0[x*3+3];                //Load source Y element
        unsigned int u1     = (unsigned int)I0[x*3+4];  //Load source U element (and convert from uint8 to uint32).
        unsigned int v1     = (unsigned int)I0[x*3+5];  //Load source V element (and convert from uint8 to uint32).

        //Calculate destination U, and V elements.
        //Use shift right by 1 for dividing by 2.
        //Use plus 1 before shifting - round operation instead of floor operation.
        unsigned int u01    = (u0 + u1 + 1) >> 1;       //Destination U element equals average of two source U elements.
        unsigned int v01    = (v0 + v1 + 1) >> 1;       //Destination U element equals average of two source U elements.

        J0[x*2]     = y0;   //Store Y element (unmodified).
        J0[x*2+1]   = (unsigned char)u01;   //Store destination U element (and cast uint32 to uint8).
        J0[x*2+2]   = y1;   //Store Y element (unmodified).
        J0[x*2+3]   = (unsigned char)v01;   //Store destination V element (and cast uint32 to uint8).
    }
}


//Convert image I from pixel-ordered YUV 4:4:4 to pixel-ordered YUV 4:2:2.
//I - Input image in pixel-order data YUV 4:4:4 format.
//image_width - Number of columns of image I.
//image_height - Number of rows of image I.
//J - Destination "image" in pixel-order data YUV 4:2:2 format.
//Note: The term "YUV" referees to "Y'CbCr".

//I is pixel ordered YUV 4:4:4 format (size in bytes is image_width*image_height*3):
//YUVYUVYUVYUV
//YUVYUVYUVYUV
//YUVYUVYUVYUV
//YUVYUVYUVYUV
//
//J is pixel ordered YUV 4:2:2 format (size in bytes is image_width*image_height*2):
//YUYVYUYV
//YUYVYUYV
//YUYVYUYV
//YUYVYUYV
//
//Conversion algorithm:
//Each element of destination U is average of 2 original U horizontal elements
//Each element of destination V is average of 2 original V horizontal elements
//
//Limitations:
//1. image_width must be a multiple of 2.
//2. I and J must be two separate arrays (in place computation is not supported). 
static void ConvertYUV444ToYUV422(const unsigned char I[],
                                  const int image_width,
                                  const int image_height,
                                  unsigned char J[])
{
    //I0 points source row.
    const unsigned char *I0;    //I0 -> YUYVYUYV...

    //J0 and points destination row.
    unsigned char *J0;          //J0 -> YUYVYUYV

    int y;  //Row index

    //In each iteration process single row.
    for (y = 0; y < image_height; y++)
    {
        I0 = &I[y*image_width*3];   //Input row width is image_width*3 bytes (each pixel is Y,U,V).

        J0 = &J[y*image_width*2];   //Output row width is image_width*2 bytes (each two pixels are Y,U,Y,V).

        //Process single source row into single destination row
        ConvertRowYUV444ToYUV422(I0, image_width, J0);
    }
}

这篇关于将YUV4:4:4转换为YUV4:2:2图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆