HEVC碼率控制介紹(R-Lamda)

轉載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也要用個東西替掉,不替代是不是不合理,替掉的話複雜度是不是又上了?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章