音视频数据处理入门:yuv视频数据处理

本文详细介绍了YUV颜色编码在电视系统中的应用,以及如何通过代码分离YUV420p和YUV444格式图像的Y、U、V分量。还探讨了如何将YUV图像转换为灰度图、调整亮度、添加边框等图像处理技巧,并展示了处理过程中的效果对比。
摘要由CSDN通过智能技术生成

 YUV是电视系统所采用的一种颜色编码方法yuv属于像素层,它的原理是把亮度与色度分离,因为研究证明,人眼对亮度很敏感,对色度不是那么敏感。基于上述人眼视觉系统的特点,对不敏感的色度信息进行压缩,有效地节省了图像的数据量。


获取YUV格式图像

mp4转换yuv:ffmpeg -i test.mp4 out.yuv

注意打印信息:格式yuv420p,大小640x272(后面需要用到)
image-20210423215702399播放: ffplay -f rawvideo -video_size 680x272 out.yuv


YUV存储格式

YUV4:2:0指每4个Y分量采样,对应2个U采样、或2个V采样。

常见格式I420: YYYYYYYY UU VV => YUV420P
image-20210424230500732


1、分离yuv420p格式图像中的y、u、v分量

①代码:

void yuv420_split(char *yuvfile, int w, int h, int num) {
    FILE *fp = fopen(yuvfile, "r");
    FILE *fy = fopen("output_420_y.y", "w+");
    FILE *fu = fopen("output_420_u.y", "w+");
    FILE *fv = fopen("output_420_v.y", "w+");

    char framebuf[w*h*3/2];    // yuv420p
    for (int i = 0; i < num; i++) {
        fread(framebuf, 1, w*h*3/2, fp); //取一帧数据

        fwrite(framebuf, 1, w*h, fy);  // y
        fwrite(framebuf + w*h, 1, w*h/4, fu);  // u
        fwrite(framebuf + w*h + w*h/4 , 1, w*h/4, fv);  // v
    }
    
    fclose(fp);
    fclose(fy);
    fclose(fu);
    fclose(fv);
}

调用函数:yuv420_split("test_yuv420p.yuv", 640, 272, 1); // 取一帧图像


②查看分量图像

得到的output_420_u.y 、output_420_v.y 、output_420_y.y文件,使用YUV Player查看图片:
image-20210423225221390

注意

1、所有分量的图像都使用Y分量的格式播放

2、U,V分量的w和h都是Y分量的一半,即设为320,136

下图依次是Y,U,V分量的图像:
image-20210423224038014
image-20210423224632182
image-20210423224709738


2、分离yuv444格式图像中的y、u、v分量

image-20210423225827126

3、将YUV420图像的颜色设为灰色
for (int i = 0; i < num; i++) {
    fread(framebuf, 1, w*h*3/2, fp); //取一帧数据

    // y表示明亮度,u,v则是色度、浓度
    memset(framebuf + w*h, 128, w*h/2);
    fwrite(framebuf, 1, w*h*3/2, fgray);  
 } 

结果对比:
image-20210423232736362
image-20210423232940363


4、在灰度图基础上将亮度减为原来的一半

出现了一个问题:将y分量缩小后得到下面的图像

image-20210424220356144

原因:yuv分量数据是unsigned char类型的。从灰度图那(设置u,v分量为128)应该可以想到的。正确图像如下:
image-20210424220309274


5、给图像加边框

​ 函数void yuv420_border(char *yuvfile, int w, int h, int border, int num)核心代码:

	unsigned char framebuf[w*h*3/2]; 
    for (int i = 0; i < num; i++) {
        fread(framebuf, 1, w*h*3/2, fp); // 取一帧数据
        
        for (int j = 0; j < h; j++) {    // 行扫描
            for (int k = 0; k < w; k++) {// 列扫描
                if (j < border || j > h - border || \
                        k < border || k > w - border) 
                framebuf[j*w + k] = 255; // 白边框
            }
        }

        fwrite(framebuf, 1, w*h*3/2, fborder);  
    }

函数调用:yuv420_border("output_gray.yuv", 640, 272, 20, 1);

image-20210424222948943

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值