You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
14 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 06帧内预测如何减少空间冗余
你好,我是李江。
前面几节课我们一起讨论了视频编码的原理以及编码码流结构,从今天开始我们一起来聊一聊具体的编码模式。
我们知道在视频编码时主要需要减少4个冗余包括空间冗余、时间冗余、视觉冗余和信息熵冗余。其中空间冗余就是通过帧内预测的方式来实现的。那帧内预测到底是怎么做到减少空间冗余的呢
其实一般来说,**一幅图像中相邻像素的亮度和色度信息是比较接近的,****并且****亮度和色度信息也是逐渐变化的,不太会出现突变**。也就是说,**图像具有空间相关性**。帧内预测就是利用这个特点来进行的。即**帧内预测通过利用已经编码的相邻像素的值来预测待编码的像素值,最后达到减少空间冗余的目的**。
这里需要注意的一个点就是,我们是通过已经编码了的像素值去预测待编码的像素值。你可能会问,已经编码了的像素值变成码流了,不再是一个个像素了,怎么去预测待编码的像素呢?其实已经编码了的像素是会重建成重建像素,用来做之后待编码块的参考像素的。你可以认为是**已经编码的块会解码成像素用来做参考像素**。
好了我们已经知道了帧内预测是怎么减少空间冗余的那我们还有一个最重要的问题要解答。既然帧内预测是通过相邻像素来预测待编码像素的那它到底是怎么预测的呢下面我们就以H264标准来讲解每种帧内预测模式是怎么做预测的。
## 不同块大小的帧内预测模式
我们在视频编码原理的那节课里面讲过,视频编码是以块为单位进行的。**在H264标准里面块分为宏块和子块。宏块的大小是16 x 16YUV 4:2:0图像亮度块为16 x 16色度****块****为8 x 8**。在帧内预测中亮度宏块可以继续划分成16个4 x 4的子块。因为图像中有的地方细节很多我们需要划分成更小的块来做预测会更精细所以会将宏块再划分成4 x 4的子块。如下图所示
![](https://static001.geekbang.org/resource/image/5c/5b/5c0a24c3d52e8yy2de20fb07b58c625b.jpg?wh=1280x446)
帧内预测是根据块的大小分为不同的预测模式的。还有一个点就是亮度块和色度块的预测是分开进行的。这里我给你总结一下主要有以下3点规则
1. **宏块大小是16 x 16其中亮度块为16 x 16色度块为8 x 8**
2. **帧内预测中亮度块和色度块是分开独立进行预测的**,即亮度块参考已编码亮度块的像素,而色度块参考已编码色度块的像素;
3. **16 x 16的亮度块可以继续划分成16个4 x 4的子块**
所以我们在实际帧内预测的时候就会分为4 x 4亮度块的预测、16 x 16亮度块的预测、8 x 8色度块的预测注意亮度8 x 8模式和I\_PCM模式很少使用我们这里不做讨论。下面我们就开始一个个展开来讨论吧。
### 4 x 4亮度块的帧内预测模式
因为4 x 4的块帧内预测模式最多并且基本包含亮度16 x 16和色度8 x 8的模式所以我们接下来先从4 x 4亮度块的帧内预测模式讲起。
4 x 4亮度块的帧内预测模式总共有9个。其中有**8种方向模式和一种DC模式**且方向模式指的是预测是有方向角度的。好了那我们接下来就聊聊这9种模式吧。
1. Vertical模式
**Vertical模式就是指当前编码亮度块的每一列的像素值都是复制上边已经编码块的最下面那一行的对应位置的像素值。**这句有点拗口,别急,等会儿我会给出计算方法和示意图,让你能很容易地理解它。
**Vertical模式得到的预测块同一列中的像素值都是一样的**。该模式得到的块就叫做Vertical预测块。注意**该模式只有在上边块存在的时候才可用,如果不存在则该模式不可用**。比如图像最上边的块就没有可参考的块存在。
该模式下预测块像素计算方法如下:
![](https://static001.geekbang.org/resource/image/03/e7/03b05d50574c17ed523f9164929019e7.jpg?wh=1280x362)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/c4/d8/c4yy0c94ba713d778fd81917238863d8.png?wh=1160x762)
2. Horizontal模式
**Horizontal模式就是指当前编码亮度块的每一行的像素值都是复制左边已经编码块的最右边那一列的对应位置的像素值**(同样地,下面有计算方法和示意图)。**Horizontal模式得到的预测块同一行的像素值都是一样的**该模式得到的块就叫做Horizontal预测块。注意**该模式只有在左边块存在的时候才可用,如果不存在则该模式不可用**。比如图像最左边的块就没有可参考的块存在。
该模式下预测块像素计算方法如下:
![](https://static001.geekbang.org/resource/image/81/91/8185bc4a93669c2a800f5cf0743f7091.jpg?wh=1280x342)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/a1/f5/a15b484807812294b00f1aebcbc942f5.png?wh=1154x750)
3. DC模式
**DC模式就是指当前编码亮度块的每一个像素值是上边已经编码块的最下面那一行和左边已编码块右边最后一列的所有像素值的平均值**。注意,**DC模式预测得到的块中每一个像素值都是一样的**。DC模式得到的块就叫做DC预测块。
根据上边块和左边块是不是存在,该模式下预测块像素的计算方法分为以下四种情况:
![](https://static001.geekbang.org/resource/image/85/ff/85de3eafb25bff062e821f83f11236ff.jpg?wh=1280x720)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/0y/6b/0yyb8202b3dd85233975ea3cffc13b6b.png?wh=1160x760)
4. Diagonal Down-Left模式
**Diagonal Down-Left模式是上边块和右上块**上边块和右上块有可能是一个块因为可能是一个16 x 16的亮度块意思理解就可以**的像素通过插值得到**。**如果上边块和右上块不存在则该模式无效。**
该模式下预测块计算的方法分为下面两种情况:
![](https://static001.geekbang.org/resource/image/a6/06/a6b8b26163ca9d9274377b5735785f06.jpg?wh=1280x412)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/11/a1/110b13f5d5af1d119b6f2a559e39f7a1.png?wh=1178x754)
5. Diagonal Down-Right模式
**Diagonal Down-Right模式需要通过上边块、左边块和左上角对角的像素通过插值得到。如果这三个有一个不存在则该模式无效**
该模式下预测块计算的方法有以下三种情况:
![](https://static001.geekbang.org/resource/image/4f/b7/4f10404d6fc9e3625092d92090aed6b7.jpg?wh=1280x474)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/fc/93/fcbdf7eaec95fea21158b4ce1047ed93.png?wh=1154x760)
6. Vertical-Right模式
**Vertical-Right模式是需要通过上边块、左边块以及左上角对角的像素插值得到的**。必须要这三个都有效才能使用,否则该模式无效。
该模式下预测块计算的方法有以下四种情况:
![](https://static001.geekbang.org/resource/image/63/ce/63b391728df65ce7551012753ae331ce.jpg?wh=1280x720)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/c5/bf/c5d488c6a80b9c27ba50048fb4ef4cbf.png?wh=1150x732)
7. Horizontal-Down模式
**Horizontal-Down模式需要通过上边块、左边块以及左上角对角的像素插值得到。必须要这三个都有效才能使用否则该模式无效。**
该模式下预测块计算的方法有以下四种情况:
![](https://static001.geekbang.org/resource/image/12/40/120761b8313c18c7433f7708d8b4a140.jpg?wh=1280x720)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/6a/bc/6a3ab22c2570589ac2680c561be0c5bc.png?wh=1172x756)
8. Vertical-Left模式
**Vertical-Left模式是需要通过上边块和右上块**上边块和右上块有可能是一个块因为可能是一个16 x 16的亮度块意思理解就可以**最下面一行的像素通过插值得到**。如果这两种块不存在则该模式不可用。该模式下预测块的计算方法有下面两种情况:
![](https://static001.geekbang.org/resource/image/83/66/835d3ec11768f9928098ab2e54556466.jpg?wh=1280x442)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/5e/5d/5e13e4207abd6788b189d9e86669665d.png?wh=1170x774)
9. Horizontal-Up模式
**Horizontal-Up模式是需要通过左边块的像素通过插值得到的**。如果左边块不存在,则该模式不可用。
该模式下预测块的计算方法有下面四种情况:
![](https://static001.geekbang.org/resource/image/7b/59/7bbb469c4f050a098b0744ea3cc94e59.jpg?wh=1280x720)
示意图如下:
![图片](https://static001.geekbang.org/resource/image/53/f8/53ddf8a40698cb99e48f103206b149f8.png?wh=1156x764)
### 16 x 16亮度块的帧内预测模式
上面我们讲了4 x 4亮度块的9种预测模式接下来我们来聊一下16 x 16亮度块的预测模式。
**16 x 16亮度块总共有****4****种预测模式。****它们****分别是****Vertical****模式,****Horizontal****模式、DC模式****和****Plane模式**前面三种模式跟4 x 4的原理是一样的这里就不重复讲解了。16 x 16亮度块的帧内预测的4种模式的示意图如下
![图片](https://static001.geekbang.org/resource/image/e3/e6/e303d85a11dced7978cedea604f001e6.png?wh=1920x872)
![图片](https://static001.geekbang.org/resource/image/b0/24/b09910c6bc61b97924a52dcd89c04824.png?wh=1920x885)
接下来我们介绍一下Plane模式。这种模式相比前面三种模式稍微复杂一些但是基本原理都差不多。**Plane预测块的每一个像素值都是将上边已编码块的最下面那一行和左边已编码块右边最后一列的像素值经过下面公式计算得到的**。
![](https://static001.geekbang.org/resource/image/4y/f2/4yyf0416de0dda660b69cb3b59b36ff2.jpeg?wh=2428x1076)
### 8 x 8色度块的帧内预测模式
上面我们讲述了亮度块的帧内预测模式,接下来我们简单介绍一下色度块的帧内预测模式。
8 x 8色度块的帧内预测模式跟16 x 16亮度块的是一样的也是总共有4种分别为DC模式、Vertical模式Horizontal模式、Plane模式。与16 x 16亮度块不同的是块大小不同所以参考像素值数量会不同。但是基本是一致的这里就不重复了。
## 帧内预测模式的选择
现在我们学习了这么多的模式而每一个块却只能有一种帧内预测模式。那我们怎么确定一个块到底使用哪种模式呢我们这边先把思路讲一讲具体细节不展开。等到你把编码基础弄明白了之后可以阅读一下x264的代码里面有关于具体如何去选择模式的方法。
以亮度块为例。一个16 x 16的亮度块我们可以不划分直接使用4种16 x 16的帧内预测模式最多得到4种预测块也可以划分成16个4 x 4的子块每一个子块最多有9种帧内预测模式。
对于每一个块或者子块我们可以得到预测块再用实际待编码的块减去预测块就可以得到残差块。主要有下面3种方案来得到最优预测模式
* 第一种方案先对每一种预测模式的残差块的像素值求绝对值再求和称之为cost然后取其中残差块绝对值之和也就是cost最小的预测模式为最优预测模式。
* 第二种方案对残差块先进行Hadamard变换在DCT变换和量化那节课中会介绍变换到频域之后再求绝对值求和同样称为cost然后取cost最小的预测模式为最优预测模式。
* 第三种方案也可以对残差块直接进行DCT变换量化熵编码计算得到失真大小和编码后的码流大小然后通过[率失真优化](https://www.jianshu.com/p/6f8be3709003?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation)(作为课外内容自行学习,这里不展开讨论)的方法来选择最优预测模式。
为了让你更容易理解第三种方案,这里我稍微简单介绍一下率失真优化的思想**。**
我们知道预测之后经过DCT变换再量化会丢失高频信息。一般来说QP越大丢失的信息越多失真就越大但是码流大小也越小反之QP越小丢失的信息越少但是码流大小就越大。这是一个跷跷板。**我们一般会在失真和码流大小之间平衡,尽量找到在一定码率下,失真最小的模式作为最优的预测模式,这就是率失真优化的思想**。
其实还有很多不同的方案比如有的为了加速模式选择的过程率失真计算的时候只会进行DCT变换和量化不会进行熵编码。码流大小直接通过QP值估算或者使用预测模式的大小来代替。这些方案都可以具体看编码器的实现。一般来说选择过程越精细效果越好但是速度会越慢。
通过上面讲的这些方法我们找到了每一个4 x 4块的最优模式之后将这16个4 x 4块的cost加起来与16 x 16块的最小cost对比选择cost最小的块划分方式和预测模式作为帧内预测模式。
## 小结
好了,今天的课到这里就要结束了。我们来回顾一下这节课的主要内容。
我们主要是一起聊了聊帧内预测。我们先详细讲述了有哪几种预测模式,以及各种预测模式的预测块的计算方法。同时强调一点,就是有的模式在参考像素不存在的时候是无效的,也就是不能使用的。这一点需要注意,并不是列举出来的每一个模式都是可以使用的。
为了方便你记忆,下面我把每一种块和子块支持的预测模式用一个表格来总结一下。
![](https://static001.geekbang.org/resource/image/ee/2d/eea93f2ace612181dfe81e34dd5e532d.jpg?wh=1280x720)
最后我们还简单介绍了一下预测模式的选择方法主要有计算残差块绝对值之和、将残差块做Hadamard变换之后再求和、率失真优化等几种方案来得到cost然后我们取cost最小的模式作为帧内预测模式。
## 思考题
在H264标准里面视频的第一帧的第一个块应该怎么选择预测模式呢
你可以把你的答案留在评论区,和我一起探讨、交流,看看自己的理解是不是正确。下节课再见。