乐趣区

关于音视频:音视频开发进阶YUV与RGB的采样与存储格式

在上一篇文章中,咱们带大家理解了视频、图像、像素和色调之间的关系,还初步意识了两种罕用的色调空间,别离是大家比拟相熟的 RGB,以及更受视频畛域青眼的 YUV。明天,咱们将持续深刻学习 RGB、YUV 的相干内容,进一步理解它们的常见采样格局和存储格局。

色调的采样格局和存储格局影响咱们解决图像的形式,只有应用正确的形式,能力出现正确的图像成果。

RGB 的采样和存储

咱们曾经晓得,图像由像素组成,而像素通过记录色调空间各重量出现各种各样的色调。对于 RGB 色调空间,其三个重量 R(红)、G(绿)、B(蓝),它们之间具备相关性,对于色调的示意来说缺一不可。

所以,RGB 的每个像素都会残缺采样三个重量,采样比例为 1:1:1(指每个重量的采样数,而非每个重量的数值)。也正是因为这种采样要求,RGB 色彩空间在采集上不好进行数据压缩,不太实用于视频图像的编码、传输。

RGB 三个重量采样后,在内存中是顺次排列存储的。然而,它们的存储程序不肯定是字面形容的 R、G、B。不同的利用场景,因解决逻辑差别可能会应用不同的规定。比方,MATLAB 应用的存储程序为 R、G、B,而 OpenCV 则应用 B、G、R,如下图所示:

R、G、B 程序

B、G、R 程序

咱们把 RGB 字面形容的重量程序,称为 字面序 ,将其理论存储的重量程序,称为 字节序。确定好色调空间存储的字节序,是正确处理图像的前提,如果随便对各重量进行读取,可能会导致解决后的色彩出现异常。下图,即为应用 RGB 程序读取字节序为 BGR 的图片的成果,此时,因为将 B、R 重量混同了,失去了谬误的图片色彩。

左一:原图,存储格局为 BGR;左二:应用 RGB 格局进行读取

另外,大家还也会接触到 BGRA 这样的存储格局(比方在 iOS、MAC 上解决摄像头数据),其中的 A,示意在 RGB 三个通道根底上,减少了一个透明度通道 Alpha,用于调整色调的透明度,实现更丰盛的色调成果。对于减少了透明度的 RGB,同样须要注意其理论的存储程序,常见的有 BGRA、RGBA、ABGR 和 ARGB 等等。

总之,RGB 的采样格局、存储格局绝对比较简单,咱们也不做过多的开展。正如上篇文章所述,在视频解决畛域,YUV 色调空间才是配角,它的采样格局、存储格局绝对于 RGB 也更加简单

YUV 的采样和存储

1、YUV 的采样格局

大家曾经晓得,区别于 RGB 色调空间,YUV 色调空间的三个重量并非都参加色彩的示意,即使仅存在亮度重量 Y,也能出现黑白灰的图像轮廓。而人眼对于色度重量 U、V 不是特地敏感,缩小一些也不会太影响观感。这种个性体现到采样上,意味着 容许咱们少采集 U、V 重量、甚至于不采集 U、V 重量(黑白图像),从而在采集上实现可观的数据压缩。按 U、V 重量的采集形式不同,支流的 YUV 采样格局有:YUV 4:4:4,YUV 4:2:2 和 YUV 4:2:0 几种。

看到“YUV A:B:C”这种标识格局,大家是否很容易将其了解为“Y:U:V = A:B:C”?这种了解是合乎直觉的,但并不正确。实际上,“A:B:C” 格局并不是将 YUV 拆分为 3 个重量、而后按 A:B:C 的比例采集,而是基于一个“宽度为 A 个像素、高度为 2 个像素”的采样区域,将 UV 重量作为一个整体进行采样,而后形容 UV 重量组绝对于 Y 重量的采样率。

宽 A 个像素、高 2 个像素的区域

下面的解释可能比拟抽象,要了解 YUV A:B:C 的采样逻辑,咱们能够将其先进行拆解,整顿为清晰可参考的“规定”,再联合“规定”和理论案例进行剖析。对于采样格局 YUV A:B:C 相干“规定”的一种了解如下:

  • 对于一个宽度为 A 个像素、高度为 2 个像素的采样区域(两行四列)
  • 第一行须要采样 A 个亮度重量 Y,B 个色度重量组 UV
  • 第二行须要采样 A 个亮度重量 Y,C 个色度重量组 UV
  • 如果 C 为 0,则示意第二行不再从新采样 UV 重量,而是复用第一行的 UV 采样

接下来,咱们针对支流的 YUV 采样格局,根据上述规定作具体解析,来帮忙大家了解。

首先,咱们来看看 YUV 4:4:4 采样格局。参照上述“规定”,解析如下:

  • 对于一个宽度为 4 个像素、高度为 2 个像素的采样区域
  • 第一行须要采样 4 个亮度重量 Y,4 组色度重量 UV
  • 第二行须要采样 4 个亮度重量 Y,4 组色度重量 UV

除了文字解析外,咱们还能够联合图例来察看。如果用空心圆圈示意 Y 重量,实心圆(蓝色)示意 UV 重量,则 YUV 4:4:4 采样逻辑能够示意为下图(图例色彩不代表理论采样色彩):

YUV 4:4:4

参考下面的图文阐明,咱们发现,在 YUV 4:4:4 采样格局下,每采样一个 Y 重量、就要相应地采样一组 UV 重量。显然,此时 UV 重量组绝对于 Y 重量在宽度方向(程度)、高度方向(竖直)上均为等采样,不存在降采样的状况,也即 Y:UV = 1:1。这意味着,在 YUV 4:4:4 采样下,每个元素都蕴含独立、残缺的亮度重量和色度重量。

YUV 4:4:4 采样绝对还比较简单,大家必定都能了解,咱们再来看看 YUV 4:2:2。

参照“规定”,咱们将 YUV 4:2:2 采样解析如下:

  • 对于一个宽度为 4 个像素、高度为 2 个像素的采样区域
  • 第一行须要采样 4 个亮度重量 Y,2 组色度重量 UV
  • 第二行须要采样 4 个亮度重量 Y,2 组色度重量 UV

其对应的图例如下:

YUV 4:2:2

参考图例,YUV 4:2:2 采样中,UV 重量组绝对于 Y 重量在宽度方向有降采样,程度每两个 Y 重量将共用一个 UV 重量组,也即 Y : UV = 2 : 1。高度方向上未进行降采样,第二行应用与第一行雷同的采样逻辑,从新采样两组独立的 UV 重量。显然,因为宽度方向有降采样,YUV 4:2:2 对 UV 重量的采样比 YUV 4:4:4 更少。但基于 YUV 的个性,尽管少采样了局部 UV 重量,也不会太影响画面的色调,这就在色调保真的前提下,实现了采集数据的压缩。

以上,咱们利用“规定”,对 YUV 4:4:4 和 YUV 4:2:2 两种采样格局进行了解析。参考解析的论断,你可能会有一个疑难:目前探讨的两种采样格局,仿佛并没有颠覆 Y:U:V = A:B:C 的“猜想”?咱们是否误会了它?

当然不是,咱们还一个采样格局没有解析,那就是 YUV 4:2:0。

如果按 Y:U:V = A:B:C 的逻辑,YUV 4:2:0 即示意“仅对 Y、U 重量按 4:2 的比例采样,不采集 V 重量”。这是一个谬误的论断,YUV 4:2:0 采样中依然蕴含 YUV 三种重量,UV 重量并未脱离彼此。到底该怎么了解 YUV 4:2:0,问题越是蹊跷,咱们越是要沉着,无妨持续参照“规定”,对 YUV 4:2:0 进行拆解:

  • 对于一个宽度为 4 个像素、高度为 2 个像素的采样区域
  • 第一行须要采样 4 个亮度重量 Y,2 组色度重量 UV
  • 第二行须要采样 4 个亮度重量 Y,0 组色度重量 UV
  • 第二行须要复用第一行采样的色度重量组 UV

先从文字说明上了解,YUV 4:2:0 的采样逻辑绝对于 YUV 4:2:2 的不同在于,它不仅在宽度方向上做了降采样,在高度方向上也做了“手脚”。采样区域的第二行,将不再采集独立的 UV 重量组,而是复用第一行的采样后果。

当初,咱们再来看看图例:

YUV 4:2:0

从图例上看,YUV 4:2:0 在宽度方向、高度方向综合起来,每 4 个 Y 重量(2 X 2 的采样区域)将共用一个 UV 重量。

当初,你必定对 YUV 4:2:0 采样有了更清晰的意识,也明确了为什么“Y:U:V = A:B:C”是一个谬误的“猜想”。同时,参考对 YUV 4:2:2 的剖析,咱们还能够推断,因为 YUV 4:2:0 进一步升高了对 UV 重量的采样,其采样数据量绝对于 YUV 4:2:2 更少,数据失去进一步压缩。

除了以上三种支流的采样格局,YUV 采样格局还有诸如 YUV 4:1:1 等模式,咱们就不做开展了。大家只有了解了“A:B:C”的规定逻辑,就能触类旁通、融汇贯通。尽管 YUV 采样格局泛滥,但其模型的共性可总结为:每个像素都会采样亮度重量 Y,但 N 个像素可能会共用一组色度重量 UV,后者的差别也带来了采样数据量的差别。

对于 YUV 的采样格局咱们就先理解到这里,确定采样格局对于正确处理 YUV 图像是至关重要的,如果采样格局断定谬误,会读取到异样的图像。

如下,为基于 YUV444 采样格局读取 YUV420 格局图片的一种异样成果:

左一:原图,YUV420;左二:基于 YUV444 读取 YUV420

理解采样格局后,就须要思考如何进行存储,YUV 的存储格局也有好几类,并且一种采样格局还能够抉择不同的存储格局,不同采样格局搭配不同的存储格局,失去了不同的 YUV 类型,这些常识综合起来还是有肯定了解和记忆难度的,大家跟着我的思路持续往下学习。

2、 YUV 的存储格局

在论述 RGB 色调空间的存储格局时,咱们重点关注了各个重量存储时的“排列形式”,根据排列的程序不同失去了 RGB 和 BGR 两种存储格局。在学习 YUV 的存储时,咱们也能够借鉴这个思路。

比拟非凡的是,咱们当初要引入数组,来示意 YUV 的一种存储构造 :立体(Plane)。咱们应用一个数组示意一个存储“立体”,N 个不同的数组即为 N 个立体。基于立体的概念,再按 YUV 存储时的各重量的排列程序不同、应用的立体数量不同,咱们能够 将 YUV 存储格局分为三大类:打包模式(Packed)、立体模式(Planar)和 半立体模式(Semi-Planar)。**

咱们先理解下各个模式的规定概述:

  • 打包模式(Packed):应用一个立体进行存储。在立体 1 上,将每个像素的 Y、U、V 重量打包后间断、交织存储;
  • 立体模式(Planar):应用三个立体进行存储。在立体 1 上,先间断存储所有像素点的 Y 重量;而后在立体 2 上,存储所有像素点的 U 重量;最初在立体 3 上,存储所有像素点的 V 重量(U 和 V 的程序能够替换);
  • 半立体模式(Semi-Planar):应用两个立体进行存储。在立体 1 上,先间断存储所有像素点的 Y 重量;而后在立体 2 上,间断、交织存储所有像素点的 U、V 重量(U 和 V 的程序能够替换)。

以上规定的形容,还是比拟清晰的,咱们上面联合具体的采样格局,看看不同采样格局、在不同存储格局下的具体表现。为便于了解,咱们依然基于“宽度为 4 个像素、高度为 2 个像素”的采样区域作讲述。

2.1 YUV 4:4:4 的存储格局

YUV 4:4:4 采样格局比较简单,相应的,其对应的存储格局也比拟好了解。YUV 4:4:4 应用打包模式(Packed)进行存储时,4×2 像素采样区域的存储图示如下:

打包模式仅应用一个立体即可,咱们能够将这个存储立体视为一个 12×2 的数组。

YUV 4:4:4 如果应用立体模式(Planar)进行存储,如下图:

能够看到,从打包模式变为立体模式,存储立体减少了两个。YUV 各重量别离存储在不同的立体,每个立体均为一个 4×2 的数组。在 YUV 4:4:4 采样、立体模式存储下,如果按先 Y、再 U、最初 V 的顺序存储,咱们称这种 YUV 类型为 I444。如果调整存储程序为先 Y、再 V、最初 U,失去 YUV 类型为 YV24。

最初,咱们再来看看 YUV 4:4:4 应用半立体模式(Semi-Planar)存储的成果:

半立体模式下,存储立体为两个,别离存储 Y 重量和 UV 重量。其中存储 Y 重量的立体为 4 x 2 的数组,存储 UV 重量的立体为 8 x 2 的数组。YUV 4:4:4 采样、半立体模式存储下,如果第二个立体按 U、V 的顺序存储,对应的 YUV 类型为 NV24。若应用 V、U 的顺序存储,则为 NV42。

以上,即为 YUV 4:4:4 采样在不同存储格局的体现,以及各种采样格局、存储格局搭配失去的不同 YUV 类型。接下来,依照雷同的思路,咱们看看 YUV 4:2:2、YUV 4:2:0 的体现。

2.2 YUV 4:2:2 的存储格局

YUV 4:2:2 下各个重量的采样逻辑曾经探讨过,联合上文,可简要概括为“Y 重量全采集,宽度方向每两个 Y 重量共用一组 UV 重量,高度方向每行独立采集 UV 重量”,如果你对此不是很了解,能够回到 2.1 节再温习一下。

YUV 4:2:2 应用打包模式(Packed)存储,成果如下图(浅蓝色填充的每组 UV 重量,属于左右两个 Y 重量共用的采样):

YUV 4:2:2 打包模式存储下,惟一立体为 8×2 的数组,每个 Packed 外部的程序为 Y U V Y,并且遵循两个 Y 共用一组 UV 的特色,其失去的 YUV 格局为 YUVY(和 Packed 内程序统一)。相似的,依照 Packed 内各重量程序不同,还能够失去 YUV 类型 VYUY 和 UYVY。

YUV 4:2:2 应用立体模式(Planar)存储,成果如下:

YUV 4:2:2 立体模式存储下,三个立体别离为 4×2、2×2、2×2 的数组,若后两个立体先存 U 后存 V,则失去 YUV 类型 I422。若先存 V 后存 U,则失去 YUV 类型 YV16。

YUV 4:2:2 应用半立体模式(Semi-Planar)存储,成果如下:

YUV 4:2:2 半立体模式存储下,两个立体均为 4×2 的数组,第二个立体内,若按 U、V 程序交织存储,则失去 YUV 类型 NV16。若按 V、U 程序交织存储,则失去 YUV 类型 NV61。

2.3 YUV 4:2:0 的存储格局

以上,YUV 4:4:4 和 YUV 4:2:2 的次要存储格局已介绍结束,最初咱们再来看看最罕用的采样格局 YUV 4:2:0 的存储。YUV 4:2:0 次要应用立体模式(Planar)和 半立体模式(Semi-Planar)。

联合上文,YUV 4:2:0 采样可简要概括为“Y 重量全采集,宽度方向和高度方向每四个 Y 重量共用一组 UV 重量,即第二行复用第一行的 UV 采样”,如果你对此不是很了解,能够再回到 2.1 温习一下。

YUV 4:2:0 应用立体模式(Planar)存储:

YUV 4:2:0 立体模式存储下,三个立体别离为 4×2、2×1、2×1 的数组,若后两个立体先存 U 后存 V,则失去 YUV 类型 I420。若先存 V 后存 U,则失去 YUV 类型 YV12。

YUV 4:2:0 应用半立体模式(Semi-Planar)存储:

YUV 4:2:0 半立体模式存储下,两个立体别离为 4×2、4×1 的数组,第二个立体若按 U、V 程序交织存储,则失去 YUV 类型 NV12。若按 V、U 程序交织存储,则失去 YUV 类型 NV21。

以上,即为 YUV 支流采样格局在不同存储模式下的体现,以及各种组合搭配失去的不同 YUV 类型。值得一提的是,在诸多 YUV 类型中,NV21 是 Android 零碎相机应用的类型,而 NV12 被 iOS、MAC 零碎相机应用(后面提到,iOS 和 MAC 也会应用 BGRA),大家今后会常常遇到它们,能够优先相熟相熟。

与 RGB 一样,咱们只有确认了 YUV 图像的存储格局,能力对其进行正确地解决,应用谬误的格局会导致色彩异样。

如下,原图为应用立体模式存储、先存 U 立体、再存 Y 立体的 YUV420 图像(I420),如果按 YV12 格局读取(立体模式存储、先存 V 立体、再存 U 立体)将失去图 2。

左一:原图,I420;左二:基于 YV12 读取 I420

为不便查阅,咱们再将下面提及的,不同采样格局、存储模式、UV 存储程序以及 YUV 类型的匹配关系,通过表格整顿一下:

总结

不得不说,相较于 RGB,YUV 的采样格局和存储格局还是比较复杂的,组合失去的 YUV 类型也是目迷五色,你此时或者已云里雾里。这么多格局和类型,该如何去记忆呢?

答案是:无需死记硬背某种具体格局、类型的细节,当咱们须要用到的时候,再查阅材料即可。咱们须要重点把握的,是对“采样格局”、“存储格局”概念规定的了解,在了解概念规定的根底上,对于任何⼀种 YUV 类型,咱们都能够按 “确认采样格局 → 确认存储格局 → 确认 UV 存储程序” 的思路进行剖析,如后面所说,做到死记硬背方可触类旁通。

最初,咱们通过一个思维导图,梳理一下本篇文章的常识脉络:

本期思考题

请参照 YUV 采样格局的“规定”,阐明 YUV 4:1:1 的采样逻辑?

(🤫下期揭秘)

上期思考题 揭秘 ⬇️

问:

RGB 色彩空间也能示意黑红色和黑白,为什么还须要 YUV 来解决黑白电视和彩色电视之间的兼容互通问题呢?

答:

在黑白电视向彩色电视的过渡期,两种类型的电视零碎须要共存互通。RGB 色调空间能够满足彩色电视的显示需要,也齐全能胜任黑白画面的显示工作,然而如果对立应用 RGB 色调空间,会存在如下问题:

1、RGB 即便只示意黑白,也须要存储三个重量,只不过各重量的值均是 0 或 1。而黑白电视作为旧零碎,只能解决一个亮度重量,无奈向前兼容 RGB;

2、RGB 必须应用三个通道,会极大减少传输带宽的压力。

而 YUV 很好地解决了上述问题:

1、黑白电视能够仅接管 Y 信号、疏忽 U、V 信号,向后兼容;

2、YUV 能够与 RGB 无损转换,向前兼容;

3、YUV 能够对 UV 重量进行降采样,升高数据量同时色调保真,节俭带宽。

退出移动版