分享

HEVC码率控制介绍(R-Lamda)

 托尼虎 2018-12-05
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/listener51/article/details/50810050

本来是不想贴出相应的代码的,但是还是贴出来大概的模块吧,这样才能不纸上谈兵!

 R-lamda模型提出到优化已有2年,从近几年的文章来看,大体归为以下几类:一类是帧内的码率控制算法,一类是模型参数更新,一类是考虑感知。 

第一类:K0103码率控制算法主要是在P/B帧上提出的,I帧没有做,体现在I帧中LCU编码时用的还是帧层的QP,而帧层的QP是由配置文件(即*.cfgQP: 32 # Quantization parameter(0-51)  这里的32我们可以更改,一般设置为22273237),如果码率控制开启,实际上配置文件中#======== Quantization =============这一栏的QP设置已经没有多大意义,因为码率控制一旦开启,就会根据相应的分配模型将码率分配到编码单元(这里不区分码率跟比特,习惯了,实际上配置文件中的我们叫码率,而在HM平台里会有一个将码率除以帧率的计算,码率除以帧率后才是比特),码率分配好,就可以根据R-lamda模型计算相应的QP,用于编码编码单元(码率控制中的编码单元最小是一个LCU,最大是一个silce,配置文件中可设置) 

针对K0103的不足,后续出来几个提案(M0257M0036),说白了M0036就是考虑了K0103I帧码率控制的缺陷,编码编码单元时,此时用的QP不在是帧层的QP,每个编码单元的QP很有可能不一样,而K0103中每个编码单元的QP和帧层的QP一致(这个在TencSlice.cpp中,

K0103中相应的代码是:

  1. if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE || !m_pcCfg->getLCULevelRC() )  

M0036中相应的代码是:

  1. if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )  
  1. m_pcCfg->getForceIntraQP()如果你不动配置文件中的使能端,这个就一直为否。这样就解决了每个编码单元的QP和帧层的QP一致的bug。  

M0036还做了一个工作,就是方法相应的alpha,beta的取值范围,为什么放大,这个提案给出了具体的说明,这里不重复。

M0257相对M0036改动相对更大一点,怎么说呢,一句话概括,考虑了空域的复杂度,即对原始帧做了一个HAD变换,然后在对HAD变换的值相加,这个提案中说是SATDSATD即经过哈达曼变换后的绝对误差和,一般是对预测块与原始块的差值(即残差)做哈达曼变换,主要作为ME/Merge模式选择中率失真代价函数中的失真,至于这里为什么对原始帧做HAD变换合理,原因是在编码后才能知道预测块,编码前得不到只能对原始帧做一个咯,HAD主要是用于消除空域冗余,将图像的能量集中在低频系数,一般在变换块的左上角值比较大,这里的值指绝对值。

M0257只做了帧内的码率分配模型,这个模型的实现跟提案介绍肯定有非常大的区别。看平台吧,不多说,而且很多具体的参数怎么来的,不得而知,这里我不介绍了,但是根据我个人的理解,有的参数作者虽没有给出具体的求法,但是可以猜的到,一般就是用QP=1~51去编码所有的序列,差不多就可以确定那些参数的上限下限。参数的初始值估计就是对这些序列取平均。真正做参数更新范围限定,或初始值确定,这个实验量是相当的大,但想做快一点无非就是参数更新,以及确定粗糙一点!!

最后M0257不易深究,因为提案跟代码实现区别是相当的大。。 

至于以后提案更新到啥样了,我也没关注了,但是跟踪近几年的文章,应该变化不大

 

现在讲讲我这两年码率控制的感悟吧,以及比较好做的点,不喜勿喷 

1、  率失真优化

2、  比特分配

3、  感知编码

4、 建立码率控制模型 

1、率失真优化是相对这三点是相对简单的,为什么呢,下面我说下原因:

首先看这上面的公式,注意下标也要看。率失真优化改的地方有两个,一是改失真,二是改lamda!!,如果做跟视觉感知的失真,同时你认为你改的失真不会影响Lamda的变化,好吧。那你改失真可能有点困难,改的地方实在是太多了,那你就求个导。

这两个公式看的懂吧,这个能这个干,前提是K只能信源或视觉特征有关,这样做是简单的也是较合理的,为什么呢,因为你想如果你改了失真,是不是率失真曲线(R-D)是不是要变,如果失真改的好还OK,如果改的不好,打个比方,如果你改的失真,导致编码出来的失真最大只有10,而产生的比特不考虑skip/merge模式,至少也是几百到几万吧,10跟几百几万是一个数量级么,那就不叫率失真曲线了,叫码率线(哈哈有点极端)。如果单改lamda,是不是在率失真曲线上仅相当于斜率变了,最佳工作点变了,曲线还是没变。当然改失真没错,但工作量相当的大,一:改了失真,至少要计算这个失真标准下lamda的计算方法,是吧!所以这又是一个耗时的统计过程,统计过程我就不说了,算是一个方法。

所以你看到很多文章中的大牛替换SSE,lamda绝对会变,这个是绝对正确。人家换一种失真模型,肯定对这个失真模型做了一个处理,使得失真跟码率之间的数量级至少不会相差太大。使得失真与码率有一个平衡,这个也不具体介绍了,大体就是这样。。 

关于率失真还有一种做法,就是直接对lamda做修正,这样的话涉及到一个速降率的问题,是码率降的快,还是质量降的块,这个质量有多种评价方法,看你做的什么,质量可以用PSNR衡量,也可以打分,不知道你们试过没有,不开码率控制用QP=22编码跟用QP=25编码有什么多大的区别,肯定会有人说你这不是说的废话么,肯定会有变化,不好意思我说的是你看编码出来的重建图像,你不去拿放大镜看,你又看的出多大的区别。但是你在看看码率是不是区别很大。这你估计就会懂了,感知可做的就来了。这就不细说了!!!  

2、比特分配,为什么说比特分配相对率失真优化难做一点呢,因为比特分配不一定有效果,因为你单从比特分配上来考虑,提升的效果也不会太大,因为码率控制的模型最关键的地方在于根据比特计算相应的QP以及模型中的参数更新,你分配的在准,QP计算不准,参数更新不准,编码出来的码率绝对达不到你分配的码率。这里哪种方案最好,我也不过多介绍。只是有感而发!!!  

3、感知码率控制说难不难,说易也不易,为何这么说,做感知前,请停下笔想想,你用什么去评价最终的效果。这里我说一个常用的评价吧(PSNR?   PSPNSR?  SSIM?   MSSIM?  MOS?   DMOS?等等)。究竟哪种合理呢,你知我知大家知!!谁知道哪种方式最符合感知,只能根据相应的失真类型去评价!!!!PSNR是啥,是不是SSE的函数。。,另外图像的评价方法不一定适合序列,人总不能一个小时盯着一幅图像看吧。前几次,做过类似的工作,码率节省19.5%PSNR平均下降1.5dB(单视点)。自己觉得PSNR下降太大,就差不多直接扔了,方法也是大家常用的方法。想过主观打分,但是懒得做打分序列。就这么不了了。近来看文献,人家trans.码率也就是节省18%左右,PSNR降了接近1.6dB,可能更多,为何人家能发,关键是写!!!!因为感知感知,最终还是给人看的,对序列中的一些细节可能不是人眼关注的,而这些细节恰恰又是导致PSNR猛降的地方,你说怎么办,感知这东西真不好说,跟人的兴趣爱好也不一样,可能关注体育的知道科比,不关注的谁又知道科比是谁。 

4、  建立码率控制模型,来点难度大的吧。这弄出来绝对轰动。但绝非易事!!!! 

首先看这两个公式,这两个公式用在哪里呢?第一个公式用在CU分割那里,第二个公式用在模式选择那里,具体的说第二个公式中的SATD用在变换域,一个用在非变换域。为什么不全用SSE度量失真,据说是为了简化计算量,这个我也不太清楚,希望知道的说下。 

先来说R-LAMDA模型是怎么出来的吧,第一:失真确定,选择的是SSE度量失真,选这个失真是最合理的,为什么,下面会说。第二个公式中的lamda跟第一个公式中的lamda不一样,第二个lamda是第一个lamda的开方,为什么是开方,是通过实验统计得出来的关系,在一篇rate distortion 的文章,九几年的文章。具体名字我也忘记了,率失真模型就出自那篇文章。记住统计也是建立在SSE作为失真度量的基础上。这就方便了R-lamda模型的产生,如果R-lamda模型诞生在别的失真上,估计工作量又会加一点。 

如果建码率控制模型,想用一种失真替换SSE,首先这个工作量绝对会大,假设用SSIM来代替,SSIM最大为1,而编码出的码率最小为多少,可能为0Merge模式),最大为多少,上万,1在上万面前是不是可以忽略不计,那么问题就来了,编码不就是在码率和失真之间选择一种平衡么。现在哪能平衡,当然做法也很多,有人说,对失真放大,但是放大多少倍是合理的?才能找到这种平衡? 

失真替换掉了,这个lamda势必要重新建立,经典的做法,就是不开码率控制,把失真替换掉,固定几个QP,用Nlamda去编码,得出QP-lamda的关系,得出关系之后在slice层(相应的地方是函数:

Void TEncSlice::initEncSlice( TComPic* pcPic, Int pocLast, Int pocCurr, Int iNumPicRcvd, Int iGOPid, TComSlice*& rpcSlice, TComSPS* pSPS, TComPPS *pPPS )
)改进,这里改进不是用在码率控制,是用在QP确定,相应的lamda就会确定,然后选用低延时或随机访问结构,求出QP-LAMDA的关系,这个关系是用在码率控制模型中,用于根据码率计算相应的QP(QP = 4.2005Ln(lamda)+13.7122),为什么选择递延时结果,答案,分级。递延时分3级,每以及的QP增量不一样,利用上一步QP-lamda的关系是不是能得出lamda,然后在通过在LCU编码时多遍历几个QP,选出对应Lmada下的最优QP,是不是会得出一个关系。 

说这么多,问题在哪,复杂度,SSESSIM替换,是不是SAD/SATD也要用个东西替掉,不替代是不是不合理,替掉的话复杂度是不是又上了?发现越写越写不清了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多