RGB、YUV像素数据处理

本文详细介绍了YUV420P和YUV444P格式的像素数据处理,包括分离YUV分量、转换为灰度图、减半亮度、添加边框、生成灰阶测试图以及RGB24到YUV420P的转换。提供了多个实用函数示例,并展示了处理前后的图像效果。此外,文章还提到了编译方法、YUV播放器的使用以及代码中的一些修正点。
摘要由CSDN通过智能技术生成

本文基本是转载自雷神的文章:

视音频数据处理入门:RGB、YUV像素数据处理_手机能看视频的原理是什么csdn-CSDN博客

指出了其中的一些问题,跟大家一同学习。

视频像素数据在视频播放器的解码流程中的位置如下图所示。

本文分别介绍如下几个RGB/YUV视频像素数据处理函数: 
 分离YUV420P像素数据中的Y、U、V分量 
 分离YUV444P像素数据中的Y、U、V分量 
 将YUV420P像素数据去掉颜色(变成灰度图) 
 将YUV420P像素数据的亮度减半 
 将YUV420P像素数据的周围加上边框 
 生成YUV420P格式的灰阶测试图 
 计算两个YUV420P像素数据的PSNR 
 分离RGB24像素数据中的R、G、B分量 
 将RGB24格式像素数据封装为BMP图像 
 将RGB24格式像素数据转换为YUV420P格式像素数据 
 生成RGB24格式的彩条测试图 
本文中的RGB/YUV文件需要使用RGB/YUV播放器才能查看。YUV播放器种类比较多,例如YUV Player Deluxe,或者开源播放器(参考文章《修改了一个YUV/RGB播放器》)等。

函数列表


(1) 分离YUV420P像素数据中的Y、U、V分量
本程序中的函数可以将YUV420P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示。 
/**
 * Split Y, U, V planes in YUV420P file.
 * @param url  Location of Input YUV file.
 * @param w    Width of Input YUV file.
 * @param h    Height of Input YUV file.
 *
 */
int simplest_yuv420_split(char *url, int w, int h){
    FILE *fp=fopen(url,"rb+");
    FILE *fp1=fopen("output_420_y.y","wb+");
    FILE *fp2=fopen("output_420_u.y","wb+");
    FILE *fp3=fopen("output_420_v.y","wb+");
 
    unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
 
    fread(pic,1,w*h*3/2,fp);
    //Y
    fwrite(pic,1,w*h,fp1);
    //U
    fwrite(pic+w*h,1,w*h/4,fp2);
    //V
    fwrite(pic+w*h*5/4,1,w*h/4,fp3);
 
    free(pic);
    fclose(fp);
    fclose(fp1);
    fclose(fp2);
    fclose(fp3);
 
    return 0;
}

调用上面函数的方法如下所示。 
simplest_yuv420_split("lena_256x256_yuv420p.yuv",256,256);
从代码可以看出,如果视频帧的宽和高分别为w和h,那么一帧YUV420P像素数据一共占用w*h*3/2 Byte的数据。其中前w*h Byte存储Y,接着的w*h*1/4 Byte存储U,最后w*h*1/4 Byte存储V。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv420p.yuv的YUV420P格式的像素数据文件分离成为三个文件:

output_420_y.y:纯Y数据,分辨率为256x256。

output_420_u.y:纯U数据,分辨率为128x128。
output_420_v.y:纯V数据,分辨率为128x128。

注:本文中像素的采样位数一律为8bit。由于1Byte=8bit,所以一个像素的一个分量的采样值占用1Byte。

程序输入的原图如下所示。


lena_256x256_yuv420p.yuv

编译方法:放虚拟机里,gcc simplest_mediadata_main.cpp simplest_mediadata_raw.cpp -lm,注意不加-lm会报错。但是还是会警告const *,不过不需要理会。

程序输出的三个文件的截图如下图所示。在这里需要注意输出的U、V分量在YUV播放器中也是当做Y分量进行播放的。

打开软件后,要调整分辨率,像素格式。

具体方法:打开yuvplayer.exe,把像素格式设为Y,分辨率设为128*128,把output_420_y.y拖拽进去即可


output_420_y.y

               
output_420_u.y和output_420_v.y

(2)分离YUV444P像素数据中的Y、U、V分量
本程序中的函数可以将YUV444P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示。 
/**
 * Split Y, U, V planes in YUV444P file.
 * @param url  Location of YUV file.
 * @param w    Width of Input YUV file.
 * @param h    Height of Input YUV file.
 *
 */
int simplest_yuv444_split(char *url, int w, int h){
    FILE *fp=fopen(url,"rb+");
    FILE *fp1=fopen("output_444_y.y","wb+");
    FILE *fp2=fopen("output_444_u.y","wb+");
    FILE *fp3=fopen("output_444_v.y","wb+");
    unsigned char *pic=(unsigned char *)malloc(w*h*3);
 
    fread(pic,1,w*h*3,fp);
    //Y
    fwrite(pic,1,w*h,fp1);
    //U
    fwrite(pic+w*h,1,w*h,fp2);
    //V
    fwrite(pic+w*h*2,1,w*h,fp3);
 
    free(pic);
    fclose(fp);
    fclose(fp1);
    fclose(fp2);
    fclose(fp3);
 
    return 0;
}

调用上面函数的方法如下所示。 
simplest_yuv444_split("lena_256x256_yuv444p.yuv",256,256);
从代码可以看出,如果视频帧的宽和高分别为w和h,那么一帧YUV444P像素数据一共占用w*h*3 Byte的数据。其中前w*h Byte存储Y,接着的w*h Byte存储U,最后w*h Byte存储V。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv444p.yuv的YUV444P格式的像素数据文件分离成为三个文件: 
output_444_y.y:纯Y数据,分辨率为256x256。 
output_444_u.y:纯U数据,分辨率为256x256。 
output_444_v.y:纯V数据,分辨率为256x256。
输入的原图如下所示。

输出的三个文件的截图如下图所示。

output_444_y.y

output_444_u.y

output_444_v.y

(3) 将YUV420P像素数据去掉颜色(变成灰度图)
本程序中的函数可以将YUV420P格式像素数据的彩色去掉,变成纯粹的灰度图。函数的代码如下。 
/**
 * Convert YUV420P file to gray picture
 * @param url     Location of Input YUV file.
 * @param w       Width of Input YUV file.
 * @param h       Height of Input YUV file.
 */
int simplest_yuv420_gray(char *url, int w, int h){
    FILE *fp=fopen(url,"rb+");
    FILE *fp1=fopen("output_gray.yuv","wb+");
    unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
 
    fread(pic,1,w*h*3/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值