YUYV422到YUV420PSEMI格式的转化

 

1.1  颜色空间说明

由于TI提供的H264编码器只支持YUV420PSEMI颜色空间的视频图像格式,而OV5642不支持输出这个格式,所以选用了与之比较接近的YUYV422格式,然后由ARM进行转换。

YUV420PSEMI的格式如下图所示。UV分量是交错的,与Y分量分开而单独存储在Y分量后面。整幅图像Y分量占2/3,UV分量占1/3。

 

YUYV422格式如下图所示。YUV三个分量是交错存储的。

 

1.2  Matlab代码实现颜色空间转换

为了实现YUYV422到YUV420PSEMI格式的转换,首先使用Matlab进行编程验证算法可行,然后再移植到视频编码的程序中。Matlab实现两种格式转换的核心代码如下所示。

 

fid = fopen('test_422.264', 'r' );

if fid == -1

    error('Cannot open file.');

end

hor = 640;

ver = 480;

for i=1:ver

    picture(i,:) = fread(fid, hor * 2, 'uint16');

end

fclose(fid);

picture = picture./4;

y = uint8(zeros(ver, hor));

u = uint8(zeros(ver, hor));

v = uint8(zeros(ver, hor));

for i = 1:ver

    for j = 1:4:hor * 2

        y(i, (j + 1)/2) = picture(i, j);

        u(i, (j + 1)/2) = picture(i, j + 1);

        u(i, (j + 3)/2) = picture(i, j + 1);

        y(i, (j + 3)/2) = picture(i, j + 2);

        v(i, (j + 1)/2) = picture(i, j + 3);

        v(i, (j + 3)/2) = picture(i, j + 3);

    end

end

% figure,imshow(y, [ ]);

frame(:, :, 1) = y;

frame(:, :, 2) = u;

frame(:, :, 3) = v;

rgb = ycbcr2rgb(frame);

figure,imshow(rgb);

 

% write 420 file

fid = fopen('test_420.264', 'w' );

if fid == -1

    error('Cannot open file.');

end

for i = 1:ver

    fwrite(fid, y(i,:), 'uint8');

end

for i = 1:2:ver

    for j = 1:2:hor

        fwrite(fid, u(i,j), 'uint8');

        fwrite(fid, v(i,j), 'uint8');

    end

end

fclose(fid);

 

取一幅原始的YUYV422格式的图像来进行处理,其原始图像如下所示。


经过Matlab转换之后的图像效果如下所示。


可以看出,经过该算法转换过后,图像质量变化不大,证明该算法是可行的,可以将其用到视频编码程序中。

1.3  C语言实现颜色空间转换

在视频编码程序中进行图像格式转换时,必须要注意OV5642传过来的数据时10-bit,而不是像TVP5150那样为8-bit。如果是8-bit数据,那么处理比较方便,因为在编码器支持的是8-bit格式,而且DMAI中的Buffer模块也是将像素点数据定义的8-bit模式。所以,在使用C语言对视频缓冲区数据进行格式转换时,需要对指向这些数据的指针进行强制类型转换,将Int8 *型转换为Int16 *型。使用C语言进行格式转换的代码如下所示。

 

Void YUYV10_to_YUV420PSEMI8(Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)

{

    BufferGfx_Dimensions srcDim;

    BufferGfx_Dimensions dstDim;

    UInt32 srcOffset, dstOffset;

    Int8 *src, *dst_Y, *dst_UV;

Int i, j;

 

    BufferGfx_getDimensions(hSrcBuf, &srcDim);

    BufferGfx_getDimensions(hDstBuf, &dstDim);

 

    src    = Buffer_getUserPtr(hSrcBuf);

    dst_Y  = Buffer_getUserPtr(hDstBuf);

    dst_UV = Buffer_getUserPtr(hDstBuf) + srcDim.width * srcDim.height;

 

    if (dst_Y != src) {

        for (i = 0; i < srcDim.height; i++) {

            if (i % 2 == 1) {

                for (j = 0; j < srcDim.width * 4; j += 8) {

                    *dst_Y = ((*((Int16 *)(src + 0))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_Y = ((*((Int16 *)(src + 4))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_UV = ((*((Int16 *)(src + 2))) / 4) & 0xff;

                    dst_UV ++;

                    *dst_UV = ((*((Int16 *)(src + 6))) / 4) & 0xff;

                    dst_UV ++;

                    src += 8;

                }

            }

            else {

                for (j = 0; j < srcDim.width * 4; j += 8) {

                    *dst_Y = ((*((Int16 *)(src + 0))) / 4) & 0xff;

                    dst_Y ++;

                    *dst_Y = ((*((Int16 *)(src + 4))) / 4) & 0xff;

                    dst_Y ++;

                    src += 8;

                }

            }

        }

    }

    Buffer_setNumBytesUsed(hDstBuf, srcDim.width * srcDim.height * 3 / 2);

}

 

使用该算法进行YUYV422到YUV420PSEMI颜色空间的转换,经过测试表明图像效果良好。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值