zshuangyan / blog

我的个人博客
2 stars 0 forks source link

视频压缩技术 #37

Open zshuangyan opened 5 years ago

zshuangyan commented 5 years ago

背景知识

我们看到的视频是由一个个图片组成的,当这些图片快速地在我们眼前切换时,在我们的大脑中就形成了动态幻觉,可以参考flash动画原理。根据统计,人的视觉反应大概0.04s左右,每秒播放25个以上的画面,人类很难发现其中的差异,因此一般视频播放的速率在30帧每秒(一帧就是一个图片)。

现代视频支持的清晰度主要包括:4k, 1080p, 720p等。它们对应的分辨率大小分别为2048×1080,1920×1080,1280×720。分辨率把图片划分为一个个的小格子,每个小格子对应一个像素,表示这个位置的颜色。

像素的颜色可以有多种表示方法,最常用的是RGB颜色模型。在小学的美术课上,老师教过我们可以使用红,绿,蓝三种颜色来绘制其他色彩,通过调节红,绿,蓝三种颜色的深度,得到不同的颜色,这其实就是RGB的原理。一般情况下,我们使用0~255范围内的数值(即8bit)来表示一个颜色中红色,绿色或者蓝色的深度,因此一共需要8×3bit位来表示一个颜色值,24bit的存储空间一共可以表达16,777,216种颜色。

如果不对视频进行压缩,那么一个1080p的视频,每秒需要传输30×(1920×1080)×24bit,大约为1.39GB,目前我使们用电信的百兆带宽最多也只能达到12.5MB/s的下载速度,中间相差100个数量级,并且我们的计算机上的其他进程可能也会占用一部分带宽,因此对视频进行压缩传输是非常有必要的。

压缩技术

色度子采样

颜色的表示除了RGB模式外,还支持YCbCr模式,YCbCr把颜色分解为明亮度和色彩两部分,Y表示明亮度,Cb和Cr分别表示蓝色色度和红色色度。

从 RGB 到 YCbCr 的转换,我们将使用 ITU-R 小组建议的标准 BT.601 中的系数。

Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)

我们人类对颜色的感知敏感度远远低于对于明亮度的敏感度,利用这一点我们可以在保留明亮度的分辨率的基础上,降低色彩的分辨率,来达到减少颜色储存空间的目的。例如2×2个像素构成的像素块,我们保留这四个像素的明亮度,但是每行只保留一个像素的颜色

原本需要4×24=96bit来表示4个像素,现在只需要4×8 + 2×(8+8) = 64bit来表示4个像素,节约了1/3的空间。

在YCbCr中一般使用三个比例数a:x:y来表示采样的方法,a表示横向的像素个数,x表示第一行色度采样数,y表示第二行色度采样数。我们上面的例子对应的比例数为2:1:1,在YCbCr中惯例把a设置为4,那么采样其实是对4×2个像素组成的像素块进行采样,常用的采样比例为4:4:4,4:2:2,4:2:0,4:1:1,对应的采样方法如下图所示:

image

4:2:0模式的采样,可以节省1/2的存储空间,计算过程如下:

原本需要4×2×24=192bit 采样后需要4×2×8 + 2×(8+8) = 96bit 节省空间 (192-96) / 192 = 1/2

隔行扫描

在早期,为了节省每帧传输的数据量,采用了交叉传输每一帧的基数行和偶数行像素的方法,每一帧渲染时使用上一帧的像素数据和当前帧的像素数据进行叠加,就得到一个完整帧,不过这种方式的图像放大后可以看到断层。 image

这种技术目前已经很少使用了。

帧间压缩

帧间压缩利用了相邻帧之间的连续性来压缩整个视频的大小,以小球运动为例: image image image image

这四个连续帧里的背景都没有发生变化,只有球的位置发生了变化,我们只需要第一帧的所有像素,以及后面连续几帧相对于第一帧的发生变化的像素,就能够表示出这四帧,由于小球占用的像素个数相对于整个图片来说非常小,因此视频压缩到只有原来的1/4。

另外一个帧间压缩的例子: 每一帧都独立编码 image

一组帧中只保留某一帧和所有其他帧相对于某一帧的变化 image

帧类型

如果一个视频里边都是I帧的话,视频的跳转会非常快,如果一个视频里边都是P帧的话,视频的跳转会比较慢,原因在于当前帧要依赖起始帧进行计算。

帧内压缩

和帧间压缩相似,帧内压缩利用了相邻像素之间的连续性来减少编码的像素占用的空间。