记录一下学习视频编码的过程和自己的理解
视频
数字图像在计算机中的表示:二维矩阵,或三维矩阵(彩色)。
矩阵中的每个点为像素,数值的大小反应色彩的强度,颜色深度需要使用一定数据空间存储,每个色彩平面(RGB)常用为8bit,范围是0~255,那颜色深度就是24(8*3)bit。
分辨率:每英寸图像内有多少个像素点,分辨率主要包括:320 x 240、640 x 400、640 x 480、800 x 600、1024 x 768 1280 x 720(720P标清)、 1600 x 1200、1920 x 1080 (1080P全高清)
视频是单位时间内连续的n帧,n是帧率,单位是秒时等同于fps(frame per second)
播放一段视频每秒所需的数据量就是比特率(码率)单位是kb/s或Mb/s
比特率 = 宽 x 高 x 颜色深度 x 帧每秒
例如一段每秒30帧,分辨率是480x240的RGB视频,如果不做任何压缩,那码率为82944000(30x480x240x24)比特每秒。
一般来说同样分辨率下,视频的码率越大,说明表示像素的比特数越大,比特数大了就可以用来表示更细腻的颜色或画面信息,因此视频的压缩比越小,画面质量越高
巨大的数据量导致需要寻找一种方法保证人眼观感的同时尽可能压缩视频。
人眼的视觉特性:对亮度比色度更佳敏感
这张图能中的A B区域能反应人眼的视觉特性。
视觉特性
除了RGB颜色模型,还有其他模型,其中YCbCr可以将亮度(luma)和色度(chroma)分离,其中Y为亮度,Cb和Cr分别是蓝色色度和红色色度。
亮度色度分离
分离亮度和色度之后,可以将色度部分进行压缩。称为色度子采样,表示为 a❌y
- a: 水平采样参考,一般为4
- x:第一行的色度样本数
- y:第二行的色度样本数
常用的方案有:4:4:4(没有子采样),4:2:2, 4:2:0 等。如果使用4:2:0采样,可以减少一半的视频大小。
视频中连续的帧之间存在很强的相关性,也就是说当前帧中的很多部分与上一帧中的部分有重叠,这样的冗余为时间冗余。消除时间冗余是有条件的,连续的几帧中要有关键帧,剩下的帧可以参考关键帧来消除冗余,因此我们需要对帧分类。
帧类型
I帧(关键帧):I帧是自足的帧,不需要其他任何信息渲染,它与静态图像相似,因此第一帧通常是I帧,I帧一般会定期被插入到帧序列中。
P帧(预测帧):P帧可以利用之前的帧渲染,比如连续两帧中只有一小部分发生了运动,那我们只需知道当前帧和前一帧的差值,就能重建当前帧。
B帧(双向预测):B帧相比P帧预测原理一样,只是B帧可以参考前向和后向的帧。
通常情况下,占用比特大小:I帧 > P帧 > B帧
帧间预测
用来去除时间上的冗余
假设有两帧图像
用0减去1,就可以得到残差,这样传输残差比直接传输图像本身的数据量要小的多。
但是整帧之间的残差还是比较大的,所以更好的方法是将图像分块
分块之后我们尝试匹配0和1中的块。
假设我们找到了匹配块,就是球会从(0, 25)移动到(7, 26),那么x,y的值也称运动矢量,类似于传输整帧的残差,我们可以只传输运动矢量x=(7-0),y=(26-25),可以进一步压缩。
例子
帧内预测
消除了帧间的冗余,帧内还是有冗余信息,比如这部分体现在图像内相同的颜色区域,或者重复出现的内容。
帧内可以使用块中左上侧的所有像素来预测
例子
假设我们预测出块中的颜色在垂直方向上保持一致,那我们就可以根据垂直方向的最上方一行的像素推测整个块中的像素值。这种方法可能会出错,所以我们还是利用残差信息,用 预测值-实际值=残差,来减少数据量。
编解码器
通俗讲就是用于压缩或解压 视频音频的软件或硬件,因为我们需要在有限的带宽或存储空间中提高视频的质量。
标准是指人们为了统一数字视频流传输,制定的将原始视频转换为另一种视频格式的规则
通用工作流程
1. 分块
首先要将帧分为很多宏块(Macro Blocks),分块是有依据的,在静态背景使用较大的块,而在复杂的部分使用更加细小的划分方式。
通常编码器会将分区组织成片(Slice),宏块(MB)和子分区
例子
2. 预测
根据上面所说的两种方法压缩,帧间预测需要传运动矢量和残差,帧内预测需要传送预测方向和残差。
3. 转换
得到残差后,还可以进一步去除部分像素而不影响整体质量,最常用的方法是离散余弦变换(DCT),这种变换可以分离数据高频和低频的部分,其中大部分能量集中在低频,因此丢掉部分高频信息就能减少数据量,但不会牺牲很多图像的质量。
4. 量化
量化是将连续的值转为有限的离散值,一个最简单的例子是均匀量化,取一个MB,将所有像素都除以10,那么块中的像素值都会减小,小的数意味着可以用更少的比特表示,但量化并不是无损的,由于除法运算之后会使用取整,会引入量化噪声。
这只是最简单的例子,并没有考虑系数的重要性,因此实际编码器中的量化一般表示为量化矩阵。
5. 熵编码
我们得到量化后的块之后,还可以继续编码,此时块中非零系数集中在低频部分,高频系数大部分是0。使用zig-zag扫描将kuai中的二维数据转换为一维,也就是一串非零值集中在前面,0集中在后面的数字。有两种编码方式
-
CAVLC
-
CABAC
6. 比特流格式
完成上述步骤后,就可以传输压缩后的数据了,其中包含了一些信息,比如,颜色深度,分辨率,块划分方式,运动矢量,帧内预测方向,档次,级别,帧率,帧类型,帧号等重要信息。在H.264中规定信息将在宏帧内传输,称为NAL层,此时的数据就是一大堆十六进制数,每个部分分别代表着原始视频在压缩过程中的信息
总结
视频编码的目的是为了在有限的带宽中提升视频质量,为了达到这一目的,编码器负责分析原始视频,去除视频中的冗余,其中包括帧内预测和帧间预测,原理是利用残差和关键帧的信息就可以恢复原始图像,之后使用DCT将数据转换到频域去除高频部分,此时视频已经变成使用小数值表示的,包含非0和0值的二维矩阵。最后使用熵编码得到十六进制的比特流,传输时将比特流和编码器使用的压缩方法一起传输,解码器根据比特流和不同的模式解码原始视频。