这是什么YUV格式?真的是YUV420SP吗?

Which YUV format is this? Really YUV420SP?

下面是假定的 YUV420SP 缓冲区的 RGB 输出。没有转换,我只是像显示 RGB 一样显示 YUV420SP,只是为了查看一些模式。

图像位于大小为 width*height*3 的单个 unsigned char* 缓冲区中。所以如果这确实是 YUV420SP,那么我应该将 Y 作为黑白图像,然后进行 UV 交错处理。我想我应该将 Y 视为黑白图像,但为什么它在我的图像中重复了 3 次?我应该在紫外线部分看到什么吗?

当然,我尝试将此缓冲区转换为 RGB。我使用 https://github.com/andrechen/yuv2rgb/blob/master/yuv2rgb.h#L70 但我只得到一个全黑的图像。

之前做过几个YUV渲染器

YUV 420 缓冲区应包含 Y 的 width*height 字节,然后是 U 的 (width*height)/4) 字节。还有另一个 (width*height)/4) 字节的 V。因此,如果您的 YUV 字节缓冲区应该大小包含 (width*height*3)/2 个字节。

只是为了看到您描述的灰度模式,您需要将 "Y" 字节转换为 24 位 RGB,如下所示:

像这样:

unsigned char* YUV_BYTES = < some buffer of size (width*height*3)/2 with bytes copied in>
unsigned char* RGB_BYTES = < some buffer of size width*height*3 >

const unsigned char* dst = RGB_BYTES;
for (unsigned int r = 0; r < height; r++)
{
    unsigned int row_offset = r*width;
    for (unsigned int c = 0; c < width; c++)
    {
        *dst[0] = YUV[row_offset + c];  // R
        *dst[1] = YUV[row_offset + c];  // G
        *dst[2] = YUV[row_offset + c];  // B
        dst += 3;
    }
}

我认为还有一个隐含的假设,即 YUV 图像的宽度和高度始终可以被 4 整除。根据您的图形库和平台,您的渲染器可能会颠倒绘制此图像。

格式类似于 I420 format(也称为 YV12)。

I420 是具有完全平面有序格式的 YUV 4:2:0 格式。
在YUV420中,Y颜色通道就是每个像素的Luma(亮度)。
U 和 V 是 Chroma(颜色)通道。
U 和 V 的分辨率在两个轴上都是 Y 的一半(在每个轴上以 0.5 的因子进行下采样)。

I420插图:

假设unsigned char* src是指向帧缓冲区的指针,分辨率为640x480:

src ->               YYYYYY  
                     YYYYYY  
                     YYYYYY  
                     YYYYYY  
src + 640*480     -> UUU  
                     UUU  
src + (320*240)*5 -> VVV  
                     VVV  

我使用 MATLAB 代码从您发布的图像中恢复 RGB 图像。

结果如下:


MATLAB代码(仅供参考):

I = imread('Test.png');
R = I(:,:,1);G = I(:,:,2);B = I(:,:,3);

T = zeros(size(R,1), size(R,2)*3, 'uint8');
T(:, 1:3:end) = R;T(:, 2:3:end) = G;T(:, 3:3:end) = B;
T = T';T = T(:);

Y = T(1:640*480);
U = T(640*480+1:640*480+640*480/4);
V = T(640*480+640*480/4+1:640*480+(640*480/4)*2);

Y = (reshape(Y, [640, 480]))';
U = (reshape(U, [320, 240]))';
V = (reshape(V, [320, 240]))';

U = imresize(U, 2);
V = imresize(V, 2);
YUV = cat(3, Y, U, V);
RGB = ycbcr2rgb(YUV);