视频编码那些事儿

这是我大四的一个专业选修课的结课作业,写了点关于视频编码的相关知识点的汇总,由于本身也不是做这个方向的,水平不够,所有内容基本都来自于书籍、博客和课上知识。我没有去查看和实现源代码,也没有去看官方的标准手册,所以有些地方肯定说得有点问题。发这篇博客的原因是,希望能够给一些不知道视频编码为何物的人参考参考,大致的思路应该还是可以看看的。内容有什么不对的地方可以在底下评论,谢谢!

 

 

前言

现在的时代是一个信息流的时代,人类接收信息的方式,已经更多的来自于手机、电脑、电视这些电子产品。你没事的时候看个电影,在直播平台给你喜欢的主播刷个小礼物,在B站上看看视频,都在使用着视频编码技术。不仅如此,现在的社会是一个数字的社会,你在你的手机、电脑、电视上看的东西,都是由一个个离散的数字值组合而成。因此,为了满足人民日益增长的对视频信息摄取的渴望,科学家们想出了一个又一个办法,来使得视频传输的效率越高、速度越快、显示更清晰等等,简而言之就是,以更小的带宽、更高的效率、更快的速度给人以更舒服的观看体验。

 

不过对于一个不是这个专业的小白同学,就会有各种疑问了,这篇文章就是写给这些小白们,让他们对视频编码有一个直观清晰的认识。

 

 

第一部分:视频和图像的关系

小白:老师老师,我想问一下,什么是视频啊?视频和图像有啥关系吗?

:很多学生在刚接触视频这块知识的时候,都会有这样的疑问。其实我们在电影院看电影的时候,荧幕上放的东西并不是一个连续的画面,而是一幅幅快速闪过的图像,那我们为什么看到的是正常的连续视频,而不是卡来卡去的翻页PPT呢?这就不得不提一下什么是视觉暂留了!人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这就是“视觉暂留”了,也就是说你看过的一个画面,并不会立刻消失,而是会在你的大脑中留下一点“余辉”。所以你看到的视频,都只是一幅一幅独立的快速闪过的图像组成。只要闪得足够快,你就以为那是连续的视频,不会有卡的效果啦!

小白:哇!这么神奇!那,那个闪得足够快具体是多快呢?

:你真是个喜欢提问的小白呢!人的视觉暂留大概能维持0.1s到0.4s的时间,以0.1s来算的话,也就是在视频播放中,一秒至少要放10个图像,才让人不会觉得卡。当然不同人的敏感程度也不同,为了一个更好的效果,现在电影院中的电影一般都是一秒放24帧图像,电视的话,咱国家是每秒25帧图像,美国加拿大那边是约每秒30帧。

小白:诶?咋我国和美国那边还不一样呢?

:哈哈,你真仔细,其实很简单,因为我们国家的用电体系是50Hz,美国那边是60Hz,视频每秒帧数正好是发电频率(也叫工频)的一半,你可以理解为是为了视频显示和用电的步调一致(一个正弦波周期对应一个波峰、一个波谷,也正好对应两帧的图像显示时间),这样的一致原则,更有利于信号的传输吧!

小白:哦…原来是这样。

我:其实这就是最简单,也是最需要明白的一件事,“视频是由图像构成的”。所以说,对视频进行编码(为了使得一个视频占用的空间大小更小,却又不会很影响观看质量),最应该想到的一个方法就是先对每一幅静态的图像进行编码,每一帧图像都能够做到很好的压缩,视频自然就能很好的压缩了。

由此,JPEG诞生啦!

第二部分:JPEG是啥?

小白:老师老师,我明白了视频是由一帧帧快速闪过的图像构成的,视频编码首先就要考虑对图像编码。那么咋对图像进行编码呢?

我:嘿嘿嘿,我来介绍一下什么是JPEG吧!小白,你自己用电脑查看图像的时候,细心的话是不是发现,图像的文件名后面都有个后缀,比如什么.jeg、.jpeg、.png、.bmp等等。前两个就是我们今天的主角。.jeg和.jpeg其实是一个东西,都是遵循jpeg标准的图像格式,只是因为DOS、Windows 95等早期系统采用的8.3命名规则只支持最长3字符的扩展名,为了兼容采用了.jpg。

小白:嗯..也就是说jpeg标准就是一种可以将图像进行压缩的算法标准,对吧?

我:对对对。怎么对图像进行压缩呢?首先,我们有过一点信号的知识的同学都知道,我们可以从时域和频域两个角度去分析一个信号,而jpeg标准压缩其实是对图像的频域进行压缩的。

小白:将信号从时域转换为频域用傅里叶变换,这我知道,为啥图像也能有频域???

我:图像当然有时域和频域咯,你知道的那个傅里叶变换是将一个一维信号转换到频域的方法吧。图像其实你可以理解为一个二维信号,而且是一个二维的数字信号,是离散的。我们可以通过DCT变换来得到一个图像的频域信号。DCT变换其实就是二维信号的离散傅里叶变换的实部部分。比如一张8×8的图像信号,通过DCT变换之后,频域也是8×8的信号。同时在频域部分,左上角显示的是低频分量,右下角显示的高频分量。记住高低频的位置,接下来会涉及到。

小白:诶?很奇怪啊,为什么非要把图像转换到频域进行压缩呢?

我:这个问题问得好!因为一幅图像中占比较多的部分往往是低频分量,也就是说,图像中的像素点的变化往往是缓慢的,相邻两个像素点往往是有很大相关的。辣么!如果我们将一幅图像变换到频域,往往是左上角低频部分的数值较大,而右下角的高频数值较小(因为图像高频分量少)。在实际中,左上角的值可以达到几百的数量级,而右下角的数值几乎接近于0 。

所以当我们将图像变换到频域之后,我们再对频域信号进行量化。相比于直接对时域信号量化,这种方法的好处是,在量化之后,往往高频部分,即右下角部分的值全部为0了,仅仅保留了低频部分的量化值。以Lena的照片举个例子:

 

将Lena图像中取出一个8×8的小块进行DCT变换,得到的频域值如下:

 

此处注意,jpeg压缩的时候是一块一块进行压缩的,不是整个图一起压缩。

 

 

我们可以很明显地发现,频域部分的左上角低频分量的值较大,,直流分量甚至达到235.6,而右下角高频分量的值接近于0 。

接着我们对频域信号进行量化。我们直接将频域图像除以一个量化矩阵。量化矩阵中的值就是不同位置的点的量化阶梯,量化矩阵是:

 

 

比方说,最左上角的直流分量是235.6,量化阶梯式16,则最终的量化值就是235.6/16 = 14.725(向上取整为15)。所以最终的量化结果如下:

 

 

小白:哇!太神奇了,没想到一幅这么复杂的图像,在频域进行量化之后,竟然变得这么简单。而且我看到,量化后的矩阵右下角部分都是0了,我们怎么利用这一个特性进行压缩呢?肯定有什么好方法吧!哈哈!

我:小白真聪明!如果在一个码流中,总是有一大串相同的数字出现,我们完全可以只记一个数字的值和这个数字出现的次数,比如有15个连续0,我们就记(0,15)。也就是我们仅仅只用两个数字,就可以代替这么多的0了,这个压缩比可是相当相当的大啊!!!这种方法就叫做“游程编码”。

而且由于图像的频域部分由低到高的方向是向右下角的,所以在编码的过程中,采用的z字形走位(zigzag编码)。

 

 

所以编码的时候大致的顺序就是:15,0,-2,-1,-1,-1,0,0,-1,0,0,0……这样就可以使得高频分量集中在序列的后面,使得更多的0可以集中在一起。

小白:天哪!太厉害了吧!不过老师,我发现你刚刚有一点没说,你看你看,你之前那个量化矩阵,不同点的量化阶梯是不一样的。而且我发现整体趋势是低频分量量化阶梯较小,高频量化阶梯较大,这……你得给我解释解释。

 

 

我:你你你…你确定你是小白,而不是作者内心的想象出来的托?行叭,既然你发现了,那我就说一下吧。

人的眼睛往往对低频分量更敏感,可以想象如果低频分量的量化阶梯过高,那图像中那种渐变的趋势就被抹去了,图像就像有了斑块的感觉。高频分量往往是描述突变的部分,比如边缘部分,只要超过一个量化阶梯后,便可以恢复出来。所以这样处理不仅对图像不会造成过大的失真,而且能够使更多的连续0出现,提高压缩比。

不仅如此,如果是彩色图像的话,图像如果在亮色空间(YCbCr空间),由于人眼对亮度和颜色的敏感程度不同,所以量化的时候,亮度通道和色差通道使用的量化矩阵还有不同!

小白:诶?亮色空间是啥?你好像没说过这个概念。

我:嗯,彩色图像可以用RGB(红绿蓝)三个通道描述,也可以用YUV或者YCbCr的亮度分量+两个色差分量描述(Y指亮度分量)。这几种描述方式都是可以互相转换的。大致这么理解就行了。

小白:哦哦。我有点明白了。

我:其实呢,在jpeg编码标准中,我们在图像中的某一块量化之后的结果,DC分量和AC分量是分开编码的!还是上面的结果举例。

DC(直流分量)就是最左上角的那个点,AC分量就是除了DC那个点剩下的所有点。为什么要分开编码呢?因为一幅图像中,相邻的编码块的DC分量,即整体的亮度信息或者色差平均值是很接近的。所以AC分量依旧按照上述的z字形(zigzag编码)游程编码,而DC分量是跨块的增量编码,比如一幅图像的连续小块的DC分量分别是15,13,14,12,15,16。则我们就编码15,-2,1,-2,3,1。通过这种增量编码,很好地利用了相邻块之间的DC分量缓变的冗余信息,来提高了编码效率!

小白:我似乎明白了jpeg的大致思想呢!将图像变换到频域,再量化,因为图像的频率分量大多集中在低频,所以会出现很多连续0,可以通过游程编码提高编码效率。同时还可以利用相邻块的直流分量的缓变特性,用增量编码来提高DC分量的编码效率。

我:emmmm,不错不错,看来你已经掌握本质了!接下来我们就开始介绍视频编码部分吧!

小白:嗯!上面是先修知识,老师好棒棒啊!

 

 

第三部分:视频编码的前世今生

小白:之前老师说过,视频就是由一帧帧图像组合而成,所以我们对视频编码,就是要先对其中每一帧图像编码。那现在不就可以了吗?还能再提高编码效率吗?

我:嘿嘿嘿!小白啊,当我们在考虑如何提高编码效率时候,就应该考虑我们的编码对象存在着哪些冗余信息!这点很重要!那我们想一个视频有哪些冗余呢?

小白:之前那个jpeg编码算是一种冗余吗?

我:是的,之前我们通过对每一帧图像压缩编码,就是降低视频编码中的空间冗余。所谓空间冗余,就是像素之间存在一定的相关性,利用这种相关性,我们便可以用更少的码字来(近似)描述原来的信息。那有空间冗余,在我的提示下,小白你还能想出什么冗余呢?

小白:额。。。难道是时间冗余?

我:哈哈,是的呢!那什么是时间冗余呢?

小白:是不是在时间维度上,前后帧的相关性产生的冗余呢?

我:是的!小白,一看你就不是小白,一定是作者精神分裂的产物!

小白:是不是你心里不知道吗?

我:好吧,言归正传。我们之前说视频是由一帧帧快速闪过的图像组成的,在这么快的闪动速度下,前一帧和后一帧图像很多地方都是相似的,甚至没有变化。这个冗余的量是非常非常可观的。如果我们仅仅把视频当作一帧帧独立互不相关的图像来进行压缩,那是远远不够的!

小白:嗯,有道理!

我:其实视频编码技术,真正的核心技术点已经讲完了!就是如何解决视频帧与帧之间的冗余问题。其实除了空间冗余、时间冗余,还有视觉冗余、图像构造冗余、知识冗余等等。

视觉冗余其实我们已经提到过了,比如人眼对亮度色差的敏感度差异,人眼对低频高频分量之间的敏感度差异,都算是视觉冗余。

图像构造冗余的话,比方说一个具有很强的规则纹理性的图像,我们完全利用纹理中的相关性进行编码。知识冗余更有意思,假设我们的编解码系统具有了人的智慧,当发现图像有一个人脸,那么其实根据常识,我们知道人的有两只眼、一个鼻子、一张嘴,还能知道它们的大致相对位置,知道的信息越多,冗余就降低的越多,编码效率就越高!

小白:哇!视频编码听起来好好玩啊!接着说!!!

我:现在在视频编码领域,有两大组织,一个是ITU-T(国际电信联盟远程通信标准化组),另一个是ISO/IEC(国际标准化组织/国际电工委员会),好吧,翻译过来的名字有点长。这两个标准化组织在视频编码的历史中,互相促进,互相学习。前者制定的标准是H.26x系列,后者制定的标准是MPEG系列。

 


上面就是两个标准化组织制定的主要标准,中间的是两个组织合作的成果。

小白:原来还有这么两个组织在干这些事啊!看图最先出来的是H.261标准。

我:嗯,我们接下来就介绍H.261标准。其实当我们介绍完H.261标准之后,视频编码体系基本就已经介绍完了。因为之后的编码体系基本都是建立在H.261体系基础上,只是做一些算法等方面的改进。整个编码的宏观结构并没有改变。现在广泛用的是H.265编码,H.266还在制定之中。接下来我们讲什么是H.261编码。

 

 

第四部分:聊一聊H.261编码

小白:我已经知道了第一个视频编码标准是H.261。

我:嗯,接下来我来介绍H.261的编码规范。

H.261编码主要是为了解决帧与帧之间的时间冗余。由此它引入了一个前向预测的概念,即可以通过上一帧来预测当前帧的画面内容,并将当前帧的实际图像和预测图像的残差作为编码传输对象。

我们先定义一个I帧和一个P帧。I帧代表此帧不参考任何帧,当系统要传输I帧的时候,直接对图像进行压缩编码,不参考其它帧图像。P帧代表此帧要参考前面的一帧,所以当系统传输的是P帧的时候,仅仅只需要传输一个残差,以及预测的相关参数即可。解码端通过上一帧图像和残差以及相关参数,就可以恢复这一帧的原始图像了。

小白:老师,这里的相关参数是什么,不是只要一个残差和上一帧图像不就可以恢复出来了吗?两个相加不就可以了。

我:首先要明确一点,图像的编码都是基于宏块的,就像之前的静态的JPEG编码,也是将图像分成一个一个小块(宏块),然后以宏块为基本单位进行编码的。

如果我们在预测的过程中,仅仅是将上一帧和这一帧的每一个宏块的差值编码传输,确实不需要额外的参数,就可以完全恢复了。但是当在视频中,物体、人等对象往往都是在运动的,那么我们就可以去寻找当前帧的这一个欲编码的宏块与上一帧最相近的宏块的相对位置找到,然后再将这两个宏块的残差编码传输。寻找最近似匹配块的过程叫运动估计,将前后两个最近似的块作差的过程叫运动补偿。运动估计的过程如下图:

 

 

对当前帧的所有宏块进行运动估计则形成的一组运动矢量(场),如下:

 

 

所以在传输的过程中,不仅要传输残差信息,也要传输运动矢量,这样才能恢复原始图像。

小白:嗯,有点明白了,I帧直接传输原始图像信息,P帧要参考上一帧,进行运动估计和运动补偿,然后将预测的图像和当前的原始图像作残差,并和运动估计的矢量一起进行编码传输。

我:对,大致结构就是这一过程,但是这里面仍然有一些细节问题。

这样吧,我给你看一张H.261的整体框架图。

 

 

上图就是H.261的结构图,我们来一步一步梳理这里面的知识。流程如下:

  1. 图像输入。
  2. 帧内和帧间的选择器。这里的帧内就是要传输I帧的意思,帧间就是P帧的意思。而视频编码中,这一开关的控制权在编码者手中,标准中并没有做出严格规定。编码者可以通过“编码控制”模块,进行I、P帧的交换,可以控制I、P帧之间的比例大小。
  3. 当传输的I帧的时候,图像先经过DCT编码,转换到频域,再经过量化,编码,即可传输。由此可见,当视频编码中,如果传输的是I帧,其实仅仅相当于做了一个图像编码(JPEG)。
  4. 由于I帧之后是P帧,P帧的传输需要前面一帧(I帧或P帧)的参考,所以在第3步量化之后,又经过了反量化,反DCT变换,存储起来。当下一帧到来的时候,将这两帧图像进行进行运动估计和运动补偿。将运动估计的结构一起送入右边的编码传输模块。
  5. 在运动补偿之后,已经输出了当前帧的预测图像了。按照我们之前的分析,由于两帧间隔很短,这个预测图像和真实图像其实相差不多,通过一次环路滤波之后,和真实图像作差,然后编码传输。

大致就是这么一个框架,而这个框架将被一直延续了下来,之后的编码标准都是在这个的基础上进行小幅度修改和改进。

小白:这里有两个地方没搞明白。一个是环路滤波是做什么的,还有一个是在反DCT变换为什么会有一个相加器。

我:你观察的还是很仔细的,先解释环路滤波的问题。

我们知道,在视频编码中,我们是以一个一个宏块为基本单位编码的,那我们这种预测方式(估计、补偿)的预测结果往往容易出现一块一块的斑块,就好像图像都是一块一块的,块块之间有明显的间隙(分块效应)。这个和原始图像肯定还是有一些差距的。而环路滤波可以对这个预测图像的边缘进行低通滤波,使得块与块之间的边界不那么明显。所以更接近原始图像,残差也就越小,编码的效率也会越高。

至于第二问题,并不难理解。这是因为,我们并不只是I、P、I、P、I这样交换编码,我们可以在两个I帧之间,插入多个P帧,那在这种情况下,当上一帧是P帧,这一帧依旧是P帧时,从反DCT变换那里的输出结果就不是上一帧的完整图像了,而是残差!所以为了恢复完整图像,必须先和上一帧的预测图像进行一次加和。

 

H.261标准是一个很宽泛的标准,给予了编码者很多自我调整的空间。它的思想也一直影响了后面的编码标准的制定。

小白:嗯,明白了!

 

 

第五部分:从H.261到H.264的进化之旅

我:H.261已经讲完了,你还记得之前那个视频编码的年代图吗?

小白:记得记得,老师你看我这就给您复制过来!

 

 

我:谢谢谢谢!H.261之后,便是另一家标准组织的MPEG-1标准。由于都是基于H.261编码标准,所以,我们这里只介绍它的不同之处。

相比于H.261,MPEG-1真的没有做多少改进,但是它在预测方法上,引出了前后预测的方法,这是一个最大的改进。下面我们主要介绍这格前后预测是怎么回事。

我们知道H.261中有I帧、P帧,I帧是传输整个图像,P帧是参考的前一帧,只传输残差和相关参数。在MPEG-1中引入了B帧,这一帧不仅会参考前面的帧,也会参考后面帧,以此来共同预测当前帧。显然这样的预测方法可以使得预测结果更加接近原始图像。比如在前一帧中一个特征宏块在A处,在后一帧中那个特征宏块在B处,那么我们有理由去预测,在当前帧中,宏块很可能是在A、B的中点处。

 

 

这是编码过程中的的帧流,GOP是一组周期循环的帧组。如果我们将B帧全部去掉,那么其实和H.261是完全一样的。而我们在I、P帧间和P、P帧间插入的B帧,则是参考了前面I(P)帧以及后面的P(I)帧,注意B帧彼此不互相参考。那么这种算法结构就引发一个问题,视频采集的顺序肯定是IBBPBBPBBPBBI,而编码的时候,为了得出B帧要传输的残差,必须知道后面的P帧或I帧,以此来做参考。所以在这种要求下,视频采集端必须有一个缓冲,并且要将顺序重排,以适应编码顺序。

 

 

 

如上图,这便是加入了B帧之后的编码框图(其实这个图里面加入了一些MPEG-2的算法,我们现在不提,之后再提),和之前的H.261框图相比,整体结构没有多大改变,只是在视频输入端加入了帧重排模块。在反DCT变换之后,加入两个存储器,以实现双向预测。

小白:哦,原来MPEG-1相对于H.261最大的改进就是引入了双向预测帧。

我:是的,不过当然它还做了一些其它的改进,比如它还将每一帧的中的各个编码宏块的直流分量单独编码传输了,这个可以用于在快进的时候,快速播放。类似的小改进还有一些,不过整体结构一直没变。

小白:看来H.261才是视频编码的基石啊!

我:之后又出现了H.262/MPEG-2标准,这个标准其实只是MPEG-1的扩展版本,在全面继承MPEG-1的压缩算法基础上,增添了一些新的语法结构和算法。那么值得介绍说明的有:第一,MPEG-2不仅支持逐行扫描、也支持隔行扫描,以前的CRT显示器,为了防止扫描过程中,产生的闪烁现象,采用的是隔行扫描技术,同理在MPEG-2也添加了这一功能。第二,MPEG-2在运动估计的时候支持半像素的估计,也就是在估计的时候,可以先对估计的区域进行1:1插值(因为是半像素),然后估计的运动矢量就相比于整像素估计更精细了。第三,MPEG-2可以支持各种清晰度可变的编码方式,比如可以控制信噪比的变化、空间分辨率的变化、时间分辨率的变化。

 

 

 

这个还是刚才的图,我们说过,这里有MPEG-2才出现的算法结构。就是右上角的自适应量化器。我们可以通过这里去调节量化矩阵的参数,可以选择更小的量化阶梯来达到更高的信噪比。同时为了改变空间分辨率,我们可以在原有的最高分辨率情况下,可以空间降采样得到较低分辨率的视频,为了改变时间分辨率,则可以抽帧。这样做都是为了在传输带宽受限的情况下,能够以较低分辨率来正常的播放视频。

小白:嗯,看来H.262/MPEG-2也只是MPEG-1基础上做了一些小改进,尤其是分辨率可调的技术,很符合我们现在看视频的习惯了!

我:嗯是,之后MPEG-4又出来了,你去查MPEG-4的标准时,发现它是有很多部分组成,MPEG-4的第二部分是MPEG-4 Visual,我认为这是很大胆很前卫很有价值的改进,但是标准推出之后,由于实现难度过高,并没有落地。之后两家组织共同制定了H.264编码标准,这个标准也收录在MPEG-4的第十部分。

小白:MPEG-4 Visual这么厉害的吗?它是个啥东西?竟然都无法落地。

我:哈哈,其实这个标准很好理解,还记得我们之前说编码的时候都是以一个个宏块为基本单位编码的吗?这种只是做了机械的固定的图像分割。而在MPEG-4 Visual中,它是以视频中的对象进项编码的。比如视频中有一个人在操场上打篮球,则会视频就有三个主要的对象,分别是“人”、“篮球”、“背景操场”。那么我们在做运动估计和补偿的时候就可以以对象为单位。小白!还记得我之前跟你说过视频中有哪些冗余吗?这种可以减小哪种冗余呢?

小白:哦!!!我明白了,知识冗余、图像构造冗余好像都可以减小了。

我:是啊!当我们一直能检测出人和篮球的位置,那我们基本就可以以非常小的残差编码传输了。然而,我说到了检测,真正的难度就在检测,人工智能还远远没有发展到可以在视频编码中实时进行检测识别物体对象,这也是为什么mpeg-4 visual不好落地原因。

小白:这个标准竟然是2000年之前提出的,那些做编码的科学家真的好厉害啊!

我:嗯,科学研究永远要走在时代前面,才能为工业界指引前进的方向。

之后两家标准组织开始制定H.264/mpeg-4(part10)。这是一个得到了非常广泛应用的编码标准。然而正如我之前所说的,我们的编码整体的框架一直没有变化。H.264编码继承了先前开发的视频编码标准的许多优点,并在各个主要功能模块都做了一些“精雕细琢”的改进,采用了H.264标准,视频的压缩比是MPEG-2压缩比的2到3倍,有效降低了在有线网络、卫星网络和电信网络上传送高画质视频的成本。

虽然整体结构没有做大的改动,但是其中有几处也是很有必要值得说道说道的!

首先,我们之前说MPEG-2的时候,它先引入了半像素估计,使得运动矢量的更加精细了,到了H.264已经可以支持1/4像素了,也就是原始像素与像素之间,插值更多,运动矢量也更精细了,估计的位置也更精确了。

其次,预测编码的时候,块的大小不再固定为16*16了,现在可以可以支持8*8和4*4这种更精细的预测了。


当然还有一个最重要的改进,我们之前的预测仅仅局限在帧与帧之间的预测,这是时间冗余。但是在同一帧里,往往有很多空间冗余,即相邻宏块描述的图像也很接近。之前我们解决这种冗余是在JPEG编码的时候,将不同块的DC分量以增量编码形式编码传输。然而这还不够,我们为什么不引入帧内的预测模式呢?

 

如上图,中间的灰色就是一个4*4的预测块,而这种预测是根据其左边和上边像素进行预测的,而预测模式之多可以达到9种(8*8和16*16有4种预测方式),不同的预测方式对应不同的预测函数,H.264在帧内预测时候,并不是固定预测模式的,而是在搜索一个最佳(最近似)的预测模式,使得编码效率可以达到最高。

不仅有如上的改进,值得一提的是H.264为了提高DCT运算速度,提出了整数DCT变换,相对于小数变化,速度真是提升了很多。而且在传输之前的熵编码阶段,H.264使用了上下文自适应的可变长度编码和算术编码,在熵编码这一块更接近香农极限,并且很好提高了熵编码的实时性(传统的哈夫曼编码不是实时的哦!)。正是有了这些改进,H.264在推出后得到了很长时间的非常广泛的应用。

第六部分:H.265——现在的潮流

我:终于讲到了H.265编码标准了,H.265又称为HEVC,是H.264标准的继任者。2004年由两家标准组织开始制定。第一版的H.265视频压缩标准在2013年被正式推出。

小白:H.265应该也是建立之前的编码标准基础上的吧。

我:是的,科学的前进并不是为了打破标准而打破标准,更靠谱的方式应该是在过往的优秀经验上,一点一点改进发展。

我们知道,近些年的数字视频中,正朝着更高清(4k,8k)、更逼真(立体成像、VR)发展。在这种数据量越来越大的趋势推动下,H.264标准已经很难再支撑视频行业的高速发展了,如果继续采用以往的视频编码标准技术,就会出现以下一些局限性:

  1. 更高清的视频导致像素点的增加,每帧图像的宏块个数急剧增加导致编码宏块的预测模式、运动矢量等参数占用的码字过多。
  2. 同样由于视频的高清化,单个宏块描述的图像内容信息则很少,则在帧内预测的时候,相邻宏块之间的相似度增加,冗余度增加。
  3. 以往的编码结构比较适合串行运算,制约了用并行计算的方式来提高编码速度的实现。

正是有了这些局限性,H.265被推出了。

小白:也就是说H.265的出现是为了解决视频越来越高清所带来的冗余度增加的问题。

我:是的。H.265在很多细节上都做了改进,相比于H.264的编码标准,H.265的提高效果如下表:

 

480P

720P

1080P

4K

平均码率降低

52%

56%

62%

64%

小白:H.265标准也叫HEVC,全称为高效视频编码(High Efficiency Video Coding),就是为了高清视频降低码率而制定的。

我:是的。相比于H.264,H.265在高清视频压缩上做了一些比较好的改进。

首先H.265的编码结构发生了很大的变化,它采用的是四叉树的划分。什么是四叉树划分呢?首先H.265的图像最大的划分块是64*64像素的,然后继续分层,如下图:

 

 

 

 

 

对应于四叉树的话就是这样:

 

 

其中节点为0,代表这一子块没有继续分割,是叶子节点,节点是1,代表这一子块被继续分割了。我想说的是在H.264中,就有宏块继续分割子块的概念,目的都是为了在表达或者描述图像中更精细的部分时,能够采用更小的编码预测结构块,但是H.265这种以四叉树为基础的划分,更具有数据结构的整齐划一,在算法上便于回溯和查询,为更复杂的算法实现打下基础。

小白:嗯,这种树形结构的划分,很适合块的回溯和定位。

我:是的,也正因为基于这种划分结构,H.265在H.264的整体框架下,几乎将每一部分的算法都做了改进,使得编码的效率更高。

除此之外,在帧内预测时,H.265相比于H.264有着更多的预测模式,小白还记得H.264的帧内预测模式吗?

小白:记得啊,4*4的预测块有9种预测模式,在预测的时候,遍历所有的模式,选取最终和原始图像最接近的模式。

我:H.265为了提高预测精度,把预测模式的数量直接提高到了35种。

 

 

 

 

 

    左图:H.264的预测模式                  右图:H.265的预测模式

    

这种精细的预测模式,虽然带来更精确的效果,但是由于要遍历所有模式,并对每种模式进行评估比较,所以必然会带来繁重的计算负担。然而近几年的硬件发展速度很快,并且H.265也做了非常多的适应并行计算的优化,使这一切都变成了可能。

当然在帧内预测中,H.265还有一些改进,比如在预测之前,会对图像进行平滑滤波,减少噪声对预测的影响。

小白:说完帧内预测,接下来就是帧间预测的改进吧。

我:对,之前说过,虽然H.265整体结构没有大幅度改进,但是在每个部分的细节上的处理可谓很精妙!

在帧间预测的时候,我们的目的是要找到更合适MV(运动矢量),然后我们也会把MV作为参数进行编码传输到解码端,但是由于在高清视频中,传输MV的码字也很多,必须要对MV进行的传输进行优化。小白,我们都已学了这么编码优化的知识,你能想象如何对要传输的MV的信息进行压缩编码吗?

小白:哈哈,我明白你的意思了,对MV也进行预测,然后传输残差!

我:可以的!你已经掌握了编码的精髓了!哈哈哈哈!然而我想说的是,这种方法在H.264标准中已经采用了,利用的就是空间(或时间)相邻块之间的运动矢量的相关性,来进行残差编码。在高清视频中,这种编码技术显得尤为重要。

小白:那H.265也是采用H.264这种结构吗?

我:是的,但是H.265不仅保留这种编码技术,还采用一种基于索引编码传输的方式——merge模式。

merge模式会为当前子块建立一个MV候选列表,遍历这些候选MV,选取最近似的作为最优MV。若编解码器依照相同的方式建立候选列表,则编码器只需要传输最优MV在候选列表中的索引即可。这种候选列表的MV可以在空域与当前子块上相邻,也可以在时域与当前子块上相邻。

小白:merge模式直接传输了最优的MV的对应块的索引,这种索引也是基于四叉树结构,索引的传输相比于残差的传输又提高了编码效率。

我:这是帧间预测,H.265的改进还有在熵编码上做了优化,以及采用了很多的并行技术,使得它的复杂算法得以落地实现!

 

 

第七部分:憧憬和探索H.266

我:小白,讲到这里,你应该对整个视频编码的发展和实现思路有了一些自己的认识了吧。

小白:嗯,还行吧,我觉得视频编码的发展基本是基于第一代的编码标准(H.261),然后不断去改进,不断地适应时代的需求。

我:在这种改进的过程中,融入了很多科学家和工程师的精妙的想法,这个过程是艰辛的,因为改进一处,其实就会牵动很多方面,但是这个过程相信也是有趣的,与时代共进步,服务于整个多媒体行业是一件很有成就感的事。

小白:那说完前面的编码标准,是不是该憧憬一下未来的标准呢?我们之后的发展方向是什么样的呢?

我:下一代的编码标准H.266也是由两家标准组织共同制定的,H.266的探索是从2016年初开始提上日程,其目标是实现比现有标准提高50%以上的压缩率(目前已经达到40%以上),在开发日程上,第一个H.266标准版本将在2019年10月推出,最终标准将定于2020年底推出。新的标准将非常适合4K、8K、16K以及更高清的视频传输,以及在编解码中将会结合机器学习等AI算法,可以说是一种Future Video Codec。

小白:那H.266将会在哪些方面做出改进呢?

我:由于H.266标准还处在探索阶段,标准的制定方案并不是确定的,也不一定能保留到最后阶段,只能通过几次会议来大致做一个了解。

首先H.266的制定是针对4K及以上的高清视频,这导致目前编码器的最大块尺寸变为128*128(H.265是64*64)。其次在编码结构上,H.266中是四叉树、三叉树、二叉树混合划分的,比如一个大块可以先分成四块,然后子块可以再分成三块或两块,这就使得在编码过程中,更加可以精细地考虑图像的纹理特征,预测效果更好。几种划分方式如下:

 

 

 

除此之外,H.266在环路滤波技术上,可能会采用自适应环路滤波。在帧内预测中,H.266的预测模式数量可能会达到70种以上。

 

 

 

这么多种的帧内预测模式,遍历一遍会很耗计算力,H.266并不会全部遍历,而是会根据预测块的宽高比来选择使用哪些种角度预测模式作为候选预测模式(因为存在三叉树结构,宽高比肯定不会只有1:1)。

在帧间预测的时候,H.266可能会考虑仿射运动的预测,我觉得这一点是非常好玩的。在H.265中,只有平动模型被用于运动补偿预测,然而在真实世界中,有各种各样的运动,比如放大、缩小,旋转等非规则运动。基于这种的预测方式,将会给运动估计的效果带来更精确的效果,编码效率也将会有所提高。

总的来说,H.266将会在很多部分引入更优秀的算法,2018年4月10日美国圣地亚哥会议上,为新一代视频编码标准定名为Versatile Video Coding,主要目标是改进现有HEVC(H.265),提供更高的压缩性能,同时会针对新兴应用(360°全景视频和HDR)进行优化。2020年之后,5G通信开始商用化,人工智能不断发展,硬件的算力将会更高,新的视频编码标准将服务于人类更加Versatile(多功能的),多元化的视频需求!

小白:哇!生活在这个日新月异的时代真好!谢谢老师!

我:不用谢。

posted @ 2018-11-30 23:12  立冬以东  阅读(1582)  评论(1编辑  收藏  举报