欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

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

最编程 2024-08-15 15:57:33
...

最开始接触到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

推荐阅读