为什么打开并查看一个YUV文件那么麻烦?

举报
黄生 发表于 2022/06/29 21:34:06 2022/06/29
【摘要】 最开始接触到YUV文件的时候,我就觉得要想把这个文件打开看看,真的是好麻烦。首先你得找到一个平时接触不到的软件,才可以打开它,并且在打开的时候,还要指定采样模式和宽高这些详细信息才能打开它的真面目,否则打开后的结果是一塌糊涂的。不得不说YUV文件的打开方法真的是很费劲。为什么会这样呢?在之前的博文里有说过ffmpeg的安装,那我们就用其中的工具ffplay来打开一个YUV文件看看先。ffpl...

最开始接触到YUV文件的时候,我就觉得要想把这个文件打开看看,真的是好麻烦。首先你得找到一个平时接触不到的软件,才可以打开它,并且在打开的时候,还要指定采样模式和宽高这些详细信息才能打开它的真面目,否则打开后的结果是一塌糊涂的。
不得不说YUV文件的打开方法真的是很费劲。为什么会这样呢?
在之前的博文里有说过ffmpeg的安装,那我们就用其中的工具ffplay来打开一个YUV文件看看先。
ffplay支持的格式非常多,用yuv420过滤一下,结果如下:

[root@ecs-d589 ~]# ffplay -pix_fmts -hide_banner |grep yuv420

Pixel formats:
I.... = Supported Input  format for conversion
.O... = Supported Output format for conversion
..H.. = Hardware accelerated format
...P. = Paletted format
....B = Bitstream format
FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL
\-----
IO... yuv420p                3            12
IO... yuv420p16le            3            24
IO... yuv420p16be            3            24
IO... yuv420p9be             3            13
IO... yuv420p9le             3            13
IO... yuv420p10be            3            15
IO... yuv420p10le            3            15
IO... yuv420p12be            3            18
IO... yuv420p12le            3            18
IO... yuv420p14be            3            21
IO... yuv420p14le            3            21
#其实下面的nv12 才对应的 YUV420 nv12
IO... nv12                   3            12
IO... nv21                   3            12
..... nv16                   3            16
..... nv20le                 3            20
..... nv20be                 3            20
IO... nv24                   3            24
IO... nv42                   3            24

执行这个ffplay命令,来看体验官任务里裁剪的600*800的图片:

ffplay -hide_banner -f rawvideo -pixel_format nv12 -video_size 600x800 -i dvpp_vpc_600x800_crop_nv12.yuv

image.png

再熟悉一下 基本概念:
YUV (Y'CbCr)是一种像素格式,见于视频编码与静态图像。与 RGB 格式不同,YUV 分别由一个称为 Y(相当于灰度)的“亮度”分量(Luminance or Luma)和两个称为 U(蓝色投影 Cb Color_blue?)和 V(红色投影 Cr Color_red?)的“色度”分量(Chrominance or Chroma)表示,由此得名。

如果只有亮度分量而没有色度分量,那就是黑白图片或小时候看的黑白电视。

YUV 在存储上通常分为平面格式(Planar),半平面格式(Semi-Planar)以及打包格式(Packed)。

平面格式有时也称为三面格式(Triplanar),即 Y, U, V 三个分量各自使用单独的数组保存,这种三平面分离的格式比较方便视频编码。

半平面格式具有两个平面,一个平面存储亮度(Y)分量,另一个平面存储两个色度(UV)分量。有时也将它们称为双平面格式(BiPlanar)。

我们看到体验官里面的YUV存储格式,基本上是半平面格式(Semi-Planar):

最后一种是 Packed 打包格式。打包格式通常只有一个平面,所有亮度(Y)和色度(UV)数据都交织在一起。有点类似于 RGB 格式,只是使用了不同的色彩空间。
打包格式在网络摄像头中较为常见。硬件设备使用多平面格式效率较低,因为每个像素需要多次内存访问。而打包格式由于仅一个平面,访问内存的开销较小。

好了,通过上面的概念介绍,可以看到同一个东西叫法太多了,对于初学者很不友好,容易弄晕。

再多了解一下体验官里用到的NV12格式:

NV12
4:2:0 Formats, 12 Bits per Pixel, 2 Planars
NV12 属于 YUV420SP 格式。两个平面,分别存储 Y 分量 和 UV 分量。其中 UV 分量共用一个平面并且以 U, V, U, V 的顺序交错排列。每四个 Y 分量共享一组 UV 分量。

UV 平面的 strides, width 与 Y 平面一样长,但 height 仅为 Y 平面的一半。因此一个像素 12 bits,内存排列如下图所示:
image.png

NV12 是 iOS 相机(AVCaptureOutput)可直接输出的两种视频帧格式之一,另外一种是 BGRA32(kCVPixelFormatType_32BGRA)。

NV21
4:2:0 Formats, 12 Bits per Pixel, 2 Planars
NV21 属于 YUV420SP,与 NV12 几乎一致,区别是 UV 平面中 U 与 V 的排列顺序颠倒,以 V, U, V, U 的顺序交错排列,内存排列如图所示:
image.png
NV21 是 Android 相机(Camera)默认的输出格式。

下面来看一下怎么计算YUV NV12文件的大小,这个和CANN的文档里申请内存大小的计算是一样的,

上图说的是内存大小=宽 * 高 * 3/2

手工计算呢,先算图片的像素的数量,就是 宽 * 高
然后前面说了YUV NV12的每个像素占用的大小是12bit
那么这个文件占用的大小就是 宽 * 高 * 12/8 Byte,这不就是和上面一样的吗?
好,来个例子算一下

[root@ecs-d589 ~]# ll dvpp_vpc_600x800_crop_nv12.yuv
-rw-r--r-- 1 root root 720000 Jun 28 21:48 dvpp_vpc_600x800_crop_nv12.yuv
[root@ecs-d589 ~]# echo $[600*800*3/2]
720000

果然手工计算的和实际大小是一样的,都是 720000.

然后我们也明白了,为什么正确打开查看一个YUV文件这么麻烦,需要提供宽高、格式等信息,完全不是我们原来熟悉的打开文件的样子的。

这是因为这个YUV文件里仅仅只是简简单单的纯粹的存储了图像的每个像素的信息。
而没有图片的尺寸、存储格式等信息,
所以需要你提供~

参考文档:
详解 YUV 格式(I420/YUV420/NV12/NV12/YUV422)
以及
Convert to YUV using FFmpeg and Playback Using ffplay - OTTVerse

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。