为什么要有帧内预测?因为一般来说,对于一幅图像,相邻的两个像素的亮度和色度值之间经常是比较接近的,也就是颜色是逐渐变化的,不会一下子突变成完全不一样的颜色。而进行视频编码,目的就是利用这个相关性,来进行压缩。

很好理解,存储一个像素的亮度值可能需要8个bit,但是如果相邻的两个像素变化不大,我存储一个像素的原始值,以及第二个像素相对第一个像素的变化值,那么第二个值我可能用2个bit就够了,这就节约了很多的空间。而节约存储消耗的bit数,也就是节约码率,贯穿了H.264编码器的所有过程,不管是帧内预测、帧间预测、变换、量化、熵编码,一切的一切都是为这个目的服务的,明白了这一点,我们就能轻易的理解H.264编码器,所有看上去复杂难懂的地方,都是为了一个目的——节约码率。

说回到帧内预测,帧内预测的流程见下图

首先,是上图中蓝色的部分,假设现在我需要对一个像素X进行编码,在编码这个像素之前,先假设我已经有一个参考像素X'了,这个参考像素与同一帧的临近像素有关,根据参考像素X'的值,我得到了一个预测值Xp。

然后,是上图中红色的部分,我用编码的像素X减去预测值Xp,得到了残差d,这个残差d代替原始值X被编码进最终的图像,起到了节省码率的作用

最后,是上图中黑色的部分,残差d和预测值Xp相加,得到了X',用于下一个像素的预测。

总结起来就是三步:

1、以同一帧图像内的临近像素作为参考,计算预测值Xp

2、原始值X和预测值Xp的差值d,被传递到解码端

3、解码端接收到差值d,将其与预测值Xp相加,就得到了“原始值”X',X'=Xp+d

步骤很简单,但是里面有几个问题要明确,首先要知道的是,我们固然可以按像素来进行预测,但是这样太费事了,要计算很多次,而且由于帧内预测的特性,你要预测当前的像素,能参考的像素只能是它的临近像素,也就是前面已经编码完成的,它后面的像素还没有编到,所以自然是不能用来编码当前像素的,因此我们只能一个像素一个像素进行编码,编完了一个才能编下一个,这样显然会很慢。于是H.264标准中提出按块进行计算,一个宏块是16x16像素,然后它可以分成子块,最小是4x4的(这个大小是对于亮度编码而言,至于色度编码,4:2:0格式的色度宏块的长和宽都是亮度宏块的一半),这样也能大大提高计算速度。因此下面提到的“值”可以代表“像素”也可以代表“块”,从原理上来说是一样的,而实际采用的是“块”,因此我也就统一用块这个词了。

我们从上面三个步骤从头开始一点点找问题

1、这个参考值X'是怎么来的?答案是在第三步里,使用Xp和传递过来的残差d相加得到的,这个X'用于后面的块编码时的参考。

2、预测值Xp是怎么从X'获得的?答案是根据X',通过某个公式计算得到的。而这个X'并不是只有一个块,而是有左侧、左上、正上、右上一共四个块作为参考。

3、上面提到的这个某个公式是什么?根据白皮书,Intra(帧内预测)有两种,一种是4x4大小的亮度块,一种是16x16大小的亮度块。

对于4x4大小的亮度块,我们有9种预测模式,如下图所示

对于预测模式0(vertical),当前块的十六个像素值,完全由其上方块最后一行的那四个像素值决定,第一列所有的Xp值都等于A,第二排都等于B,以此类推。预测模式1(horizontal)也是一样,完全由图中IJKL四个像素值决定。

对于预测模式2(DC),则十六个像素值完全相等,等于ABCDIJKL这八个像素的平均值。

对于预测模式3-8,倾斜方向的,各个像素是由A到L像素通过权重不等的公式加权计算的

比如对于模式3(diagnal down-left)来说,a=(A+2B+C+2)/4,这里+2代表四舍五入,b和e=(B+2C+D)/4,cfi=(C+2D+E+2)/4,dgjm=(D+2E+F+2)/4,hkn=(E+2F+G+2)/4,lo=(F+2G+H+2)/4,p=(G+2H+H+2)/4=(G+3H+2)/4

对于模式4(diag down-right),加权系数也是(1,2,1)/4,afkp用IMA三个像素计算,以此类推

对于模式5(vertical right),aj=(M+A+1)/2,同理bk是AB均值,cl是BC均值,d是CD均值(因为这几个像素延长线都不在预测用的13个像素里面)。en在M的延长线上,所以等于(I+2M+A+2)/4,同理fo\gp\h\i\m都可以计算出来

同理模式6、7、8也基本跟5一样,注意对于模式8来说,klmnop四个像素都等于L,因为其延长线在L的下面和前面,没有可以平均的像素,于是只好用L一个值代替了。

还有一点要注意的是,这里面A到L的像素有的没有怎么办?对于模式2(DC),有什么用什么,反正是求均值就对了。其余的模式就必须用到的那几个像素都存在才行(EFGH四个像素可以不存在,此时认为都等于D)

最终,我们要选择哪种模式进行预测?为了在后面节约码率考虑,当然是预测的越准越好,也就是选择Xp和X'差距最小为好。而评判这个差距其实也有好几种算法,比如SAD、SATD等,等到了变换那里再详细说。总之我们用一个公式把上面9种模式的预测都评价了一番,选出里面最好的一种,作为4x4帧内预测的选择。

我们注意到这里有9种模式,之后要进行编码的话,我们除了把残差编进去,总得知道我预测的时候用了哪种模式吧,9这个数就尴尬了,因为刚好三个比特可以表示8种,四个比特可以表示16种,所以3bit不够4bit又浪费了。怎么办呢?有个方法就比较巧妙,我有1bit用来表示我当前用的模式和前面的是不是一样的,因为经常有这样的情况,我前面块用的预测方向和现在这个块用的预测方向一样(比如物体边缘是一条直线,那么对应的那几个块用的预测方向很可能都是一样的),如果一样,我只用1bit就足够存储了,如果不一样,我再用用4个bit存储,也就达到了节约bit的目的。

说完了4x4的亮度块,我们看看16x16大小的亮度块。16x16亮度块有四种模式,如下图

前面三种很好理解了,重点是第四种plane的计算方式,从图上看大概能理解,不过具体算法我还不是很理解。

我们假设左上角起,上方那一行是17个像素是a1 b2 c3 d4 e5 f6 g7 h8 i9 j8 k7 l6 m5 n4 o3 p2 q1,用这17个像素计算一个H值。

我在上面标了1~9~1的数字,有数字相同的8对像素,后面计算的时候,都是一对对的计算的。

i9;j8 - h8;k7 - g7;l6 - f6;m5 - e5;n4 - d4;o3 - c3;p2 - b2;q1 - a1,这九对分别乘以权重0到8(也就是i9这个像素没有用到),而最左边和最右边两个像素权重最大。

同理V值,也是一样的算法,从上到下像素记作带'的(当然a1' = a1)。

然后计算一个A值,它等于右上角(q1)和左下角(V值计算时候对应的那个q1')的和乘以16

计算一个B值,它等于(5*H+32)/64,计算一个C值,C=(5*V+32)/64,这种后面加了32又除以64的,其实都是用来四舍五入的。

然后就能计算我们的预测值了。

i00 = A - 7*B -7*C + 16

pix[0][0] = i00 / 32(超出0到255范围的要截断成0或者255)

然后计算第一行十六个像素分别是i00 + B到i00 + 15*B,然后除以32(然后截断到0~255)

第二行是在第一行基础上加了一个C,一直到第16行,加了15个C,于是这256个像素都算出来了。

这就是plane方式的算法。算出来结果就跟下图一样。

  

对于色度块是亮度块的四分之一,也就是8x8的,那就只有一种了,预测模式也跟亮度16x16块的类似,有四种,只不过具体的序号不一样而已。是0代表DC,1代表horizontal,2代表vertical,3代表plane。

plane的算法和上面16x16的类似,只不过系数变了,而且两个色度块用的方式一定都是一样的。

好了,我们回到前面的帧内预测的步骤,还有几个问题没有解决

4、重建值X'和原始值是不是一样的?答案是不一样,因为d在传到解码端的过程中经过了量化、变换、反变换和反量化,有了精度的损失,因此Xp+d得到的X'跟原始的X是不一样的。这也是为什么要用重建值X'来得到Xp而不是用原始值X。因为解码器那边在解码图像的时候,用到的是有损的X'获得Xp,如果编码器用无损的X来得到Xp的话,那么得到的残差d在编码侧和解码侧就不一致了,这个误差扩散到了下一个块里。

好了,这样上面的步骤就组成了一个循环,可以一直编码下去了,当然最开始没有参考的那个块,其预测值Xp又是怎么来的呢?可以有一种方式叫做DC128,也就是认为这个块的每个像素都是0x80,然后依据此来计算。

实际上对于一个16x16的宏块,上面这个16x16的四种模式和它16个子块(大小4x4)的9种模式都会算一遍,然后用16个子块的SATD最小值和16x16的四种模式的SATD最小值比较,选择更小的那个,所以这里面计算量还是很大的。x264源代码里有很多节约计算量的设计,不过这些就得看代码了,白皮书里面是没有的,以后再做研究。

另外x264里面还有Intra8x8亮度块的模式,这种我认为应该也是为了找到一个预测最准的模式而加进去的,而且也不常用,所以也就不多介绍了。

回过头来看最开始的那个步骤图,跟白皮书里给的编码器流程图,是不是正是编码器的一部分呢?

H.264 White Paper学习笔记(二)帧内预测的更多相关文章

  1. H.264 White Paper学习笔记(一)总览

    H.264 White Paper对于264编码器的原理讲的比较透彻,在阅读学习的时候收获很大,这份文献网上有很多了,也有不少人翻译,不过想要理解更清楚我觉得还是得看英文原版的. 首先看一下白皮书里给 ...

  2. H.264学习笔记2——帧内预测

    帧内预测:根据经过反量化和反变换(没有进行去块效应)之后的同一条带内的块进行预测. A.4x4亮度块预测: 用到的像素和预测方向如图: a~f是4x4块中要预测的像素值,A~Q是临块中解码后的参考值. ...

  3. H.264学习笔记3——帧间预测

    帧间预测主要包括运动估计(运动搜索方法.运动估计准则.亚像素插值和运动矢量估计)和运动补偿. 对于H.264,是对16x16的亮度块和8x8的色度块进行帧间预测编码. A.树状结构分块 H.264的宏 ...

  4. H264提供了哪些帧内预测?

    H.264/AVC 提供了四种帧内预测方式:4x4 亮度块的帧内预测(Intra_4x4).16x16 亮度块的帧内预测(Intra_16x16).8x8 色度块的帧内预测(Intra_chroma) ...

  5. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  6. Django学习笔记二

    Django学习笔记二 模型类,字段,选项,查询,关联,聚合函数,管理器, 一 字段属性和选项 1.1 模型类属性命名限制 1)不能是python的保留关键字. 2)不允许使用连续的下划线,这是由dj ...

  7. 学习笔记(二)--->《Java 8编程官方参考教程(第9版).pdf》:第七章到九章学习笔记

    注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法者自负一切 ...

  8. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  9. muduo学习笔记(二)Reactor关键结构

    目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...

随机推荐

  1. $(this).bind("change",itemno_change);

    如果是onchange 会出错,超过3个可能就无效.

  2. 录制iPhone屏幕并转成gif方案

    app的开发经常会碰到需要演示一个交互,或者一个bug的情况,通常涉及一连串的操作以及操作的反馈,这是文字,或截图都无法表达的,视频的话还得播放器参与,最好的一个想法应该是录制屏幕然后再转成gif图片 ...

  3. Android 布局学习之——Layout(布局)详解一

    layout(布局)定义了用户界面的可视化结构(visual structure),如Activity的UI,应用窗口的UI. 有两种方式声明layout: 1.在xml文件中声明UI组件. 2.在运 ...

  4. input元素默认选中设置

    单选按钮: 加checked=checked属性 复选框 加checked=checked属性 select下拉框 加selected=selected属性 date日期: value='2018-0 ...

  5. 关于HTML标签嵌套的问题详解

    先说基础,HTML标签有两类: 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.men ...

  6. phoenix连接hbase数据库,创建二级索引报错:Error: org.apache.phoenix.exception.PhoenixIOException: Failed after attempts=36, exceptions: Tue Mar 06 10:32:02 CST 2018, null, java.net.SocketTimeoutException: callTimeou

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  7. MongoVUE破解

    使用MongoVUE来查看,管理GridFS MongoVUE地址:http://www.mongovue.com/ MongoVUE是个免费软件,但超过15天后功能受限.可以通过删除以下注册表项来解 ...

  8. MTK 隐藏通知栏

     步骤: 源码/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarVie ...

  9. 给一个由n-1个整数组成的未排序的序列,其元素都是1~n中的不同的整数。如何在线性时间复杂度内寻找序列中缺失的整数

    思路分析:尼玛这不就是等差数列么.首先将该n-1个整数相加,得到sum,然后用(1+n)n/2减去sum,得到的差即为缺失的整数.因为1~n一共n个数,n个数的和为(1+n)n/2,而未排序数列的和为 ...

  10. ab压测札记(Apache Bench)

    1 ab安装 ab实际上是apache httpd里面的一个工具或者说子模块,安装apache httpd可以参考另一篇文章JBOSS集群的2.3节 安装目录:/apache目录/bin/,如下 2 ...