视音频数据处理入门:RGB、YUV像素数据处理
===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB、YUV像素数据处理 视音频数据处理入门:PCM音频采样数据处理 视音频数据处理入门:H.264视频码流解析 视音频数据处理入门:AAC音频码流解析 视音频数据处理入门:FLV封装格式解析 视音频数据处理入门:UDP-RTP协议解析 ===================================================== 有段时间没有写博客了,这两天写起博客来竟然感觉有些兴奋,仿佛找回了原来的感觉。前一阵子在梳理以前文章的时候,发现自己虽然总结了各种视音频应用程序,却还缺少一个适合无视音频背景人员学习的“最基础”的程序。因此抽时间将以前写过的代码整理成了一个小项目。这个小项目里面包含了一系列简单的函数,可以对RGB/YUV视频像素数据、PCM音频采样数据、H.264视频码流、AAC音频码流、FLV封装格式数据、UDP/RTP协议数据进行简单处理。这个项目的一大特点就是没有使用任何的第三方类库,完全借助于C语言的基本函数实现了功能。通过对这些代码的学习,可以让初学者迅速掌握视音频数据的基本格式。有关上述几种格式的介绍可以参考文章《[总结]视音频编解码技术零基础学习方法》。 从这篇文章开始打算写6篇文章分别记录上述6种不同类型的视音频数据的处理方法。本文首先记录第一部分即RGB/YUV视频像素数据的处理方法。视频像素数据在视频播放器的解码流程中的位置如下图所示。
本文分别介绍如下几个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三个分量分离开来并保存成三个文件。函数的代码如下所示。调用上面函数的方法如下所示。 从代码可以看出,如果视频帧的宽和高分别为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格式的像素数据文件分离成为三个文件:
注:本文中像素的采样位数一律为8bit。由于1Byte=8bit,所以一个像素的一个分量的采样值占用1Byte。 程序输入的原图如下所示。 lena_256x256_yuv420p.yuv 程序输出的三个文件的截图如下图所示。在这里需要注意输出的U、V分量在YUV播放器中也是当做Y分量进行播放的。
?
output_420_y.y
?
output_420_u.y和output_420_v.y
(2)分离YUV444P像素数据中的Y、U、V分量本程序中的函数可以将YUV444P数据中的Y、U、V三个分量分离开来并保存成三个文件。函数的代码如下所示。从代码可以看出,如果视频帧的宽和高分别为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_y.y ? output_444_u.y ?
output_444_v.y
(3) 将YUV420P像素数据去掉颜色(变成灰度图)本程序中的函数可以将YUV420P格式像素数据的彩色去掉,变成纯粹的灰度图。函数的代码如下。调用上面函数的方法如下所示。 从代码可以看出,如果想把YUV格式像素数据变成灰度图像,只需要将U、V分量设置成128即可。这是因为U、V是图像中的经过偏置处理的色度分量。色度分量在偏置处理前的取值范围是-128至127,这时候的无色对应的是“0”值。经过偏置后色度分量取值变成了0至255,因而此时的无色对应的就是128了。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv420p.yuv的YUV420P格式的像素数据文件处理成名称为output_gray.yuv的YUV420P格式的像素数据文件。输入的原图如下所示。
?
处理后的图像如下所示。
? (4)将YUV420P像素数据的亮度减半本程序中的函数可以通过将YUV数据中的亮度分量Y的数值减半的方法,降低图像的亮度。函数代码如下所示。copy
? (5)将YUV420P像素数据的周围加上边框
本程序中的函数可以通过修改YUV数据中特定位置的亮度分量Y的数值,给图像添加一个“边框”的效果。函数代码如下所示。
从代码可以看出,图像的边框的宽度为border,本程序将距离图像边缘border范围内的像素的亮度分量Y的取值设置成了亮度最大值255。上述调用函数的代码运行后,将会把一张分辨率为256x256的名称为lena_256x256_yuv420p.yuv的YUV420P格式的像素数据文件处理成名称为output_border.yuv的YUV420P格式的像素数据文件。输入的原图如下所示。
处理后的图像如下所示。
(6) 生成YUV420P格式的灰阶测试图
本程序中的函数可以生成一张YUV420P格式的灰阶测试图。函数代码如下所示。
从源代码可以看出,本程序一方面通过灰阶测试图的亮度最小值ymin,亮度最大值ymax,灰阶数量barnum确定每一个灰度条中像素的亮度分量Y的取值。另一方面还要根据图像的宽度width和图像的高度height以及灰阶数量barnum确定每一个灰度条的宽度。有了这两方面信息之后,就可以生成相应的图片了。上述调用函数的代码运行后,会生成一个取值范围从0-255,一共包含10个灰度条的YUV420P格式的测试图。测试图的内容如下所示。 ?
(7)计算两个YUV420P像素数据的PSNR
PSNR是最基本的视频质量评价方法。本程序中的函数可以对比两张YUV图片中亮度分量Y的PSNR。函数的代码如下所示。
上述公式中mse的计算公式如下所示。
其中M,N分别为图像的宽高,xij和yij分别为两张图像的每一个像素值。PSNR通常用于质量评价,就是计算受损图像与原始图像之间的差别,以此来评价受损图像的质量。本程序输入的两张图像的对比图如下图所示。其中左边的图像为原始图像,右边的图像为受损图像。
经过程序计算后得到的PSNR取值为26.693。PSNR取值通常情况下都在20-50的范围内,取值越高,代表两张图像越接近,反映出受损图像质量越好。 (8) 分离RGB24像素数据中的R、G、B分量本程序中的函数可以将RGB24数据中的R、G、B三个分量分离开来并保存成三个文件。函数的代码如下所示。从代码可以看出,与YUV420P三个分量分开存储不同,RGB24格式的每个像素的三个分量是连续存储的。一帧宽高分别为w、h的RGB24图像一共占用w*h*3 Byte的存储空间。RGB24格式规定首先存储第一个像素的R、G、B,然后存储第二个像素的R、G、B…以此类推。类似于YUV420P的存储方式称为Planar方式,而类似于RGB24的存储方式称为Packed方式。上述调用函数的代码运行后,将会把一张分辨率为500x500的名称为cie1931_500x500.rgb的RGB24格式的像素数据文件分离成为三个文件: output_r.y:R数据,分辨率为256x256。 输入的原图是一张标准的CIE 1931色度图。该色度图右下为红色,上方为绿色,左下为蓝色,如下所示。
R数据图像如下所示。
G数据图像如下所示。
B数据图像如下所示。
(9)将RGB24格式像素数据封装为BMP图像BMP图像内部实际上存储的就是RGB数据。本程序实现了对RGB像素数据的封装处理。通过本程序中的函数,可以将RGB数据封装成为一张BMP图像。,'M'};??
通过代码可以看出,改程序完成了主要完成了两个工作: 1)将RGB数据前面加上文件头。 2)将RGB数据中每个像素的“B”和“R”的位置互换。 BMP文件是由BITMAPFILEHEADER、BITMAPINFOHEADER、RGB像素数据共3个部分构成,它的结构如下图所示。
其中前两部分的结构如下所示。在写入BMP文件头的时候给其中的每个字段赋上合适的值就可以了。 BMP采用的是小端(Little Endian)存储方式。这种存储方式中“RGB24”格式的像素的分量存储的先后顺序为B、G、R。由于RGB24格式存储的顺序是R、G、B,所以需要将“R”和“B”顺序作一个调换再进行存储。 下图为输入的RGB24格式的图像lena_256x256_rgb24.rgb。
下图分封装为BMP格式后的图像output_lena.bmp。封装后的图像使用普通的看图软件就可以查看。
(10)将RGB24格式像素数据转换为YUV420P格式像素数据
本程序中的函数可以将RGB24格式的像素数据转换为YUV420P格式的像素数据。函数的代码如下所示。
Y= 0.299*R+0.587*G+0.114*B
U=-0.147*R-0.289*G+0.463*B
V= 0.615*R-0.515*G-0.100*B 在转换的过程中有以下几点需要注意:1)?RGB24存储方式是Packed,YUV420P存储方式是Packed。 2)?U,V在水平和垂直方向的取样数是Y的一半 转换前的RGB24格式像素数据lena_256x256_rgb24.rgb的内容如下所示。
转换后的YUV420P格式的像素数据output_lena.yuv的内容如下所示。
(11)生成RGB24格式的彩条测试图
本程序中的函数可以生成一张RGB24格式的彩条测试图。函数代码如下所示。
生成的图像截图如下所示。 下载Simplest mediadata test SourceForge:https://sourceforge.net/projects/simplest-mediadata-test/ Github:https://github.com/leixiaohua1020/simplest_mediadata_test 开源中国: http://git.oschina.net/leixiaohua1020/simplest_mediadata_testCSDN下载地址: http://download.csdn.net/detail/leixiaohua1020/9422409 本项目包含如下几种视音频数据解析示例: ?(1)像素数据处理程序。包含RGB和YUV像素格式处理的函数。 ?(2)音频采样数据处理程序。包含PCM音频采样格式处理的函数。 ?(3)H.264码流分析程序。可以分离并解析NALU。 ?(4)AAC码流分析程序。可以分离并解析ADTS帧。 ?(5)FLV封装格式分析程序。可以将FLV中的MP3音频码流分离出来。 ?(6)UDP-RTP协议分析程序。可以将分析UDP/RTP/MPEG-TS数据包。 雷霄骅 (Lei Xiaohua) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |