常见视频原始数据格式分析 — YUV
1. YUV 简介
YUV 是比较常用的原始视频数据数据格式,视频采集芯片输出的码流大部分都是 YUV 数据流形式,而视频处理(如 H264、H265编码等),也是在原始 YUV 码流进行编码和解析。所以,了解熟悉 YUV 数据流对于做视频领域的人而言,至关重要。
YUV,分为三个分量,Y:表示明亮度(Luminance 或 Luma),也就是灰度值;而 U 和 V :表示的则是色度(Chrominance 或 Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。这样设计分开的主要原因是,人眼对色度的敏感程度要低于对亮度的敏感程度。
与我们熟知的 RGB 类似,YUV 也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有 UV 信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV 不像 RGB 那样要求三个独立的视频信号同时传输,所以用 YUV 方式传送占用极少的频宽。
2. YUV 采样方式
YUV 码流有多种不同的格式,要分析 YUV 码流,就必须搞清楚你面对的到底是哪一种格式,并且必须搞清楚这种格式的 YUV 采样和分布情况。
大分类:packed & planar
YUV 按像素分布规律被分为两大类,packed 打包格式和 plannar 平面格式,
- – 将 YUV 分量存放在同一数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel)
- – 将 YUV 分量分别存储在三个数组中,先连续存储所有像素点的 Y,紧接着存储所有像素点的 U,随后是所有像素点的 V
小分类:YUV444 & YUV422 & YUV420
目前比较主流的采样方式有:YUV444、YUV422、YUV420,下面会对这三种格式存储方式加以介绍,并说明如何根据其采样格式来从码流中还原每个点的 YUV 值。
常讲的的 YUV A:B:C 的意思一般是指基于 4 个象素来讲,其中 Y 采样了 A 次,U 采样了 B 次,V 采样了 C 次
下面的三个图可以直观的表示采集的方式,以黑点表示像素点的 Y 分量,以空心圆圈表示该像素点的 UV 分量。
先记住下面这句话,以后提取每个像素的 YUV 分量会用到。
YUV 4:4:4 采样,每一个 Y 对应一组 UV 分量,每像素 24 位YUV 4:2:2 采样,每两个 Y 共用一组 UV 分量,每像素 16 位YUV 4:2:0 采样,每四个 Y 共用一组 UV 分量,每像素 12 位
3. 存储方式
YUV 的优点之一是基于人眼对色度的敏感程度要低于对亮度的敏感程度,可以适当降低色度的采样率,同时不会明显降低视觉质量。因此,常见的 YUV422、YUV420 都适当降低了色度分量。
下面用图的形式给出常见的 YUV 码流的存储方式,其中,Cb、Cr 的含义等同于 U、V。
1) YUVY 格式(属于 YUV422)
YUYV 为 YUV422 采样方式的存储格式之一,相邻的两个 Y 分量共用其相邻的两个Cb、Cr,因此,对于像素点 Y’00、Y’01 而言,其 Cb、Cr 的值均为 Cb00、Cr00,其他的像素点的 YUV 取值依次类推。
2) UYVY 格式 (属于YUV422)
UYVY 格式也是 YUV422 采样方式的存储格式之一,只不过与 YUYV 不同的是 UV 的排列顺序不一样而已,还原其每个像素点的YUV值的方法与上面一样。
3) YUV422P(属于YUV422)
YUV422P 是一种 plannar 模式,即平面模式。与前面其他 YUV422 采访方式不同,它并不是将 YUV 数据交错存储,而是先存放所有的 Y 分量,然后存储所有的 U分量, 最后存储所有的 V 分量。
如上图所示。其每一个像素点的 YUV 值提取方法也是遵循 YUV422 格式的最基本提取方法,即两个 Y 共用一个 UV。比如, 对于像素点 Y’00、Y’01 而言,其 Cb、Cr 的值均为 Cb00、Cr00。
4) YV12,YU12格式(属于YUV420)
YU12 和 YV12 属于 YUV420 采样格 式之一,也是一种 plannar
模式,将 Y、U、V 分量分别打包,依次存储。
其每一个像素点的 YUV 数据提取遵循 YUV420 格式的提取方式,即 4 个 Y 分量共用一 组 UV,即上图中,Y’00、Y’01、Y’10、Y’11 共用 Cr00、Cb00,其他依次类推。
5) NV12、NV21(属于YUV420)
NV12 和 NV21 属于 YUV420 采样格式之一,也是一种 plannar 模式,但是与 YV12 不同的是,将 Y 和 UV 分为两个 plane,Y 连续存储,但是 UV 交错存储。
其提取方式与上一种类似,即 Y’00、Y’01、Y’10、Y’11 共用 Cr00、Cb00。
这种采样存储方式也被称为 YUV420SP,即 UV 交错存储,作为区分,上文 4) 介绍的存储方式被称为 YUV420P。
下面用一种表说明几种常见存储方式所占用的内存,以 w*h 大小的图像为例:
采样方式 | 占用 |
---|---|
YUV 4:4:4 | Y(w * h) + U(w * h) + V(W * h) = 3 * w * h |
YUV 4:2:2 | Y(w * h) + U(w * h * 1/2) + V(W * h * 1/2) = 2 * w * h |
YUV 4:2:0 | Y(w * h) + U(w * h * 1/4) + V(W * h * 1/4) = 1.5 * w * h |
4. 几种常见 YUV 视频像素处理
4.1 分离 YUV420P 像素数据中的 Y、U、V 分量
由于 YUV420P 各分量的连续存储性质,可以很方便快捷的直接提取出三个分量。
下面的程序将 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. * @param num Number of frames to process. * */
void 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);
}
从代码可以看出, 如果视频帧的宽和高分别为 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 分辨率 的 YUV420P 格式的像素数据文件分离成为三个文件:
output_420_y.y:纯 Y 数据,分辨率为 256x256
output_420_u.y:纯 U 数据,分辨率为 128x128
output_420_v.y:纯 V 数据,分辨率为 128x128
下面是一个运行实例:
输出原图:
程序输出三个分量:
1). output_420_y.y
2). output_420_u.y
3). output_420_v.y
4.2 将 YUV420P 像素数据的亮度减半
本程序中的函数可以通过将 YUV 数据中的亮度分量 Y 的数值减半的方法,降低图像的亮度。函数代码如下所示
/** * Halve Y value of YUV420P file * @param url Location of Input YUV file. * @param w Width of Input YUV file. * @param h Height of Input YUV file. * @param num Number of frames to process. */
int simplest_yuv420_halfy(char *url, int w, int h)
{ FILE *fp = fopen(url,"rb+"); FILE *fp1 = fopen("output_half.yuv", "wb+"); unsigned char *pic = (unsigned char*)malloc(w * h * 3 / 2); fread(pic, 1, w * h * 3 / 2, fp); //Half for (int j = 0; j < w * h; j++) { unsigned char temp = pic[j] / 2; pic[j] = temp; } fwrite(pic, 1, w * h * 3 / 2, fp1); free(pic); fclose(fp); fclose(fp1); return 0;
}
从代码可以看出,如果打算将图像的亮度减半,只要将图像的每个像素的 Y 值取出来分别进行除以 2 的工作就可以了。
输入原图:
处理后图片:
4.3 将 YUV420SP 图片旋转 90 度
void YUV420spRotate90(uchar *des, uchar *src, int width, int height)
{int wh = width * height;//旋转Yint k = 0;for (int i = 0; i < width; i++) {for (int j = 0; j < height; j++) {des[k] = src[width * j + i];k++;}}for (int i = 0; i < width; i += 2) {for (int j = 0; j < height / 2; j++) {des[k] = src[wh+ width * j + i];des[k+1] = src[wh + width * j + i + 1];k += 2;}}
}
其他待添加…
常见视频原始数据格式分析 — YUV相关推荐
- 入门视频采集与处理(学会分析YUV数据)
做视频采集与处理,自然少不了要学会分析YUV数据.因为从采集的角度来说,一般的视频采集芯片输出的码流一般都是YUV数据流的形式,而从视频处理(例如H.264.MPEG视频编解码)的角度来说,也是在原始 ...
- 【常见视频文件格式分析】
常见视频文件格式分析 先说大家目前常常在电脑上看的电影,其主要来源有两大类: A.从网络下载的视频文件.由于目前市面上所看到的视频,即电影,电视剧,MV等,有很多种不同格式,8 v9 Q2 J( v( ...
- 转:YUV RGB 常见视频格式解析
转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而Y ...
- Ffmpeg快速命令使用 Ffmpeg选项详解 Ffmepg格式详解 常见视频文件格式详解
http://www.ffmpeg.com.cn/index.php/%E9%A6%96%E9%A1%B5 Ffmpeg快速命令使用 From Ffmpeg工程组 Jump to: navigatio ...
- Tesla T4视频编码性能分析
Tesla T4视频编码性能分析 从开普勒开始的所有 NVIDIA GPUs 都支持完全加速的硬件视频编码: GPUs 支持完全加速的硬件视频解码.最近发布的图灵硬件提供了张量核心和更好的机器学习性能 ...
- 【转】Android权限获取机制与常见权限不足问题分析
转自:http://blog.csdn.net/linweig/article/details/6127488# Android系统是运行在Linux内核上的,Android与Linux分别有自己的一 ...
- 音视频开发常用分析工具介绍
综述 工欲善其事,必先利其器:兵马未到,粮草先行. 在音视频开发过程中,利用工具可以更方便.更直观.更快捷的分析音视频的数据,便于开发过程中分析.调试和解决问题. 现总结一些音视频开发过程中常用的分析 ...
- 【Arc GIS 零基础教学】这些常见的GIS数据格式你知道几个
Hi,我是胡学长!今天我们来学习一下常见的GIS数据格式:矢量数据.栅格数据. (一)什么是矢量数据 矢量数据(Vector Data)是用X.Y.Z坐标表示地图图形或地理实体位置的数据. 矢量数据一 ...
- FFmpeg4入门07:解码视频并保存为YUV格式文件
上一篇我们解码并保存了其中的几帧确保解码过程和结果是对的.本篇我们将解码整个视频并保存为标准的YUV格式(YUV格式具体信息详见YUV格式介绍),我们就选YUV420P(I420)作为输出格式. 保存 ...
最新文章
- Alibaba Sentinel限流功能
- 数字图像处理笔记一 - 图像采集(空间分辨率和幅度分辨率)
- Could not install packages due to an Environment Error: [Errno 13] Permission denied 解决方案
- php把数组转为字符串函数,php把数组转为字符串用什么函数
- Oracle存储过程编译卡死的解决方法
- wxWidgets:wxStatusBar 示例
- EL表达式 参考手册
- NgModule imports定义的运行时数据结构
- 《知识图谱》2020综述论文,18位作者, 130页pdf,547篇参考文献
- 尽量不要在viewWillDisappear:方法中移除通知
- 蘑菇街基于Docker的私有云实践
- CI框架redirect自动加上了index.php问题
- 数字化审图时代批量生成PDF或者DWF利器SmartBatchPlot
- 百万调音师—AU效果器基本应用
- STM32 FFT算法实现
- 数据传输完整性_数据集成:什么是数据完整性?
- 017 大数定律(车比学夫、辛钦)及中心极限定理
- windows开始菜单打不开,搜索打不开
- Html主要内容总结
- 想知道游戏建模师每天都在做什么吗?在工作中应具备哪些能力?
热门文章
- python词云图制作壮观天体照_超简单:快速制作一款高逼格词云图
- 数独用计算机控制比数学家还厉害,比数独更烧脑的数学游戏,让娃练就最强大脑!...
- 技术面试问题汇总第003篇:猎豹移动反病毒工程师part3
- 大学计算机专业学微积分难吗,大学哪些专业最容易挂科?快看看自己中枪了没?...
- 2021爱智先行者 - 自动化房屋能源控制核心
- OpenGL渲染模型 || 3. opengl 将模型成渲染图片
- 滴滴夜莺配置M3DB后transfer正常启动,但是端口监听失效,怎么解决?
- 【STM32+cubemx】0017 HAL库开发:usb HID鼠标设备实现
- 【目标检测】EfficientDet
- Python 递归 深入理解递归 Python递归剖析,绝对让你看懂!