h.264 去塊濾波

塊效應及其產生原因

我們在觀看視頻的時候,在運動劇烈的場景常能觀察到圖像出現小方塊,小方塊在邊界處呈現不連續的效果(如下圖),這種現象被稱為塊效應(blocking artifact)。

首先我們需要搞清楚塊效應產生的原因。h.264在編碼過程中對像素殘差進行了DCT變換,變換后得到的DCT系數是與每個像素都相關的,這些系數代表了被變換數據的基礎色調與細節。h.264在DCT變換后對DCT系數進行了量化,量化能有效去除相鄰像素間的空間冗余,也就是說會抹去元素數據的部分細節。比較理想的情況是量化抹去人眼無法識別的細節部分,但是在低碼率的情況下就會導致原始數據的細節丟失過多。而且,DCT變換時基于塊的,即將8x8或者4x4的像素殘差進行變換后得到8x8或者4x4DCT系數,此時如果進行了低碼率的量化,就會使得相鄰兩個塊的相關性變差,從而出現塊效應。

h.264的運動補償加劇了由變換量化導致的塊效應。由于運動補償塊的匹配不可能絕對準確,各個塊的殘差大小程度存在差異,尤其是當相鄰兩個塊所用參考幀不同、運動矢量或參考塊的差距過大時,塊邊界上產生的數據不連續就更加明顯。

塊效應主要有兩種形式:一種是由于DCT高頻系數被量化為0,使得強邊緣在跨邊界處出現鋸齒狀,稱為梯形噪聲;另一種經常出現在平坦區域,由于量化導致本來平緩變換的亮度塊DC系數發生跳躍,造成變換塊的基礎色調改變,這種稱為格形噪聲。

?

?

去塊濾波在編解碼器中的位置

為了減輕和消除視頻圖像中的塊效應,通常會使用濾波器對塊邊界處的像素進行濾波以平滑像素值的突變,這種濾波被稱為去塊濾波器(Deblocking Filter)。

標準8.7小節中規定了去塊濾波的內容,這部分被稱為環路濾波器(loop filter)。環路濾波器是被放置在編解碼的圖像重建環路當中。在啟用了環路濾波的編解碼環境中,無論是編碼器還是解碼器,都是在圖像被重建后才進行濾波。在編碼器中,濾波后的圖像會作為后續編碼運動補償的參考圖像;在解碼器中,濾波后的圖像會被輸出顯示并且作為后續圖像解碼重建的參考圖像。

?

?

濾波前的準備

1. 濾波參數

在標準中,去塊濾波會被應用于亮度以及色度宏塊的濾波,語法元素disable_deblocking_filter_idc用于控制去塊濾波是否打開,它的取值有三個:0~2。

  • 0:開啟去塊濾波功能,去塊濾波能穿越slice邊界。
  • 1:關閉去塊濾波功能。
  • 2:開啟去塊濾波功能,但是濾波只能對同一個slice范圍內的宏塊執行。

?

2. 濾波邊界

去塊濾波基于宏塊進行,包括亮度宏塊以及色度宏塊。亮度宏塊的寬高為16x16宏塊,而色度宏塊有幾種不同的格式,去塊濾波邊界如下圖:

?

image

圖中粗線條為濾波邊界,其中紅色粗線為水平邊界(Horizontal edge),藍色粗線為垂直邊界(Vertical edge),濾波邊界把宏塊分割成多個4x4的塊。需要注意的一點是,如果transform_8x8_mode_flag為1,則代表亮度宏塊以及4:4:4的色度宏塊會采用8x8的DCT,此時亮度宏塊以及4:4:4的色度宏塊的濾波邊界會把宏塊分割成8x8的塊。

濾波邊界還能根據濾波過程是否會用到當前宏塊以外宏塊來進行細分。宏塊的頂部邊界、左邊界由于處于宏塊邊緣,濾波的時候肯定需要用到相鄰宏塊,而其余的濾波邊界在濾波時只會用到當前宏塊內部的像素。

image

?

  • Left MB Edge: 垂直方向上宏塊最左邊的宏塊濾波邊界
    • 如果當前宏塊為圖像的最左邊宏塊的話,不需要進行左邊界濾波
    • 如果規定了只能用當前slice的宏塊進行濾波(disable_deblocking_filter_idc=2),并且當前宏塊與其左邊宏塊不為同一slice,那也不需要進行左邊界濾波
  • Vertical Internal Mb Edge: 垂直方向上的宏塊內部濾波邊界。不同宏塊類型其中包含的垂直內部濾波邊界的數量不同
    宏塊格式Y4:2:0 Cb/Cr4:2:2 Cb/Cr4:4:4 Cb/Cr
    垂直內部濾波邊界數目3113
  • Top MB Edge: 水平方向上宏塊最頂部的宏塊濾波邊界
    • 如果當前宏塊為圖像的最頂部宏塊的話,不需要進行頂部邊界濾波
    • 如果規定了只能用當前slice的宏塊進行濾波(disable_deblocking_filter_idc=2),并且當前宏塊與其上方宏塊不為同一slice,那也不需要進行頂部邊界濾波
  • Vertical Internal Mb Edge: 垂直方向上的宏塊內部濾波邊界。不同宏塊類型其中包含的垂直內部濾波邊界的數量不同
    宏塊格式Y4:2:0 Cb/Cr4:2:2 Cb/Cr4:4:4 Cb/Cr
    水平內部濾波邊界數目3133

?

濾波先進行亮度宏塊濾波后進行色度宏塊濾波,對一個宏塊濾波邊界的濾波也需要遵循一定順序

  • 先進行垂直邊界濾波,從左到右
  • 后進行水平邊界濾波,從上到下

?

3. 濾波源像素選擇

去塊濾波所用的源像素分布在邊界的兩邊,分別有4個像素點,如下圖所示

image

p與q像素所在的4x4或者8x8塊我們分別成之為P塊與Q塊。

如果當前編碼的圖像以幀或者場的方式進行編碼,則可以直接按照上述邊界兩邊的位置得到濾波的源像素點。不過如果圖像采用幀場自適應方式進行編碼(MBAFF),則需要對邊界兩邊的像素進行定位以得到正確的源像素。

我們在前面已經討論過,塊效應是由于對塊(block)進行DCT變換量化產生的,去塊濾波的目的是消除塊效應,因此去塊濾波需要正確地定位出進行DCT變換量化的塊。在幀場自適應的編碼環境下,宏塊可以以幀或者場的方式進行編碼,但是在宏塊進行重建后得到的都是幀宏塊,因此我們需要根據實際情況定位出當時進行DCT變換量化的塊所在的像素。

以下是在幀場自適應編碼環境下,一個垂直邊界濾波像素定位的事例

image

以下是在幀場自適應編碼環境下,一個水平邊界濾波像素定位的事例

image

另外,在幀場自適應的編碼環境下,如果當前宏塊為幀宏塊,它的上方宏塊為場宏塊,那么在進行頂部邊界濾波時需要進行兩條邊界的濾波

image

?

?

濾波過程

1. 估算邊界強度

對于濾波邊界,我們首先需要根據邊界所在的位置已以及宏塊的信息來粗略地估計邊界兩邊的像素差距,我們稱這個像素差距為邊界強度(BS,Boundary Strength)。

判斷條件邊界強度 BS
P塊或者Q塊為幀內編碼模式,并且塊邊緣為宏塊邊緣
4
P塊或者Q塊為幀內編碼模式
3
P塊或者Q塊的殘差變換系數包含非零系數
2
P塊或者Q塊的殘差變換系數都不包含非零系數,并且P塊和Q塊的參考幀或運動向量數目(前后向)不同
1
P塊或者Q塊的殘差變換系數都不包含非零系數,并且P塊和Q塊的參考幀以及運動向量數目(前后向)相同
0

上述表格用于亮度BS的計算,色度宏塊的BS沿用其相應亮度宏塊的BS。由于表格的描述不盡詳細,詳情請參考標準8.7.2.1

?

2. 區分真假邊界

在粗略地估算濾波邊界強度后,我們需要區分這個邊界強度是由于對塊進行DCT變換量化引起的塊效應(虛假邊界)還是視頻圖像原有的邊界(真實邊界)。如果是真實邊界則不需要進行濾波,如果是虛假邊界則需要進行去塊濾波。區分真假邊界基于下面兩個假設:

  • 真實邊界兩邊像素點的差值通常比虛假邊界兩邊像素值要大
  • 對于兩邊像素值差別很小的真實邊界,即使使用了去塊濾波,對它的主觀效果不會有太大影響

因此,去塊濾波應該遵循以下原則:

  • 在平坦區域,即使很小的像素不連續也很容易被人察覺,所以要使用比較強的去塊濾波,可以改變較多的像素點
  • 對于復雜的區域,為了保持圖像細節,要使用較弱的去塊濾波,改變較少的像素點

?

假設下圖為像素點的亮度值分布圖,這種情況下兩邊像素點的差值非常大,根據上面的假設,在p0和q0之間出現的是物體的真實邊界,因而不需要進行濾波。

image

標準h.264中設定了兩個閾值α和β來判斷真假邊界,α表示塊與塊之間的邊界閾值,β表示塊內部邊界的閾值。對于邊界兩邊的像素點的差值,如果下面三個條件都滿足就會被判定為需要濾波的虛假邊界,否則就判定為不需要濾波真實邊界。

|p0 - q0| < α[IndexA]

|p1 - p0| < β[IndexB]

|q1 - q0| < β[IndexB]

其中α與β可以通過IndexA以及IndexB從表格中得到。IndexA以及IndxeB為表格的索引,他們的計算方法如下

IndexA = Clip3( 0, 51, QPaverage + FilterOffsetA )

IndexB = Clip3( 0, 51, QPaverage + FilterQffsetB )

其中QPaverage = ( QPp+QPq+1) / 2,FilterOffsetA以及FilterOffsetB則為偏移量,偏移量用于調整濾波強度。當需要增加濾波強度時,用正偏移量,可以去除由次優運動估計、編碼模式選擇不當引起的塊效應,改善圖像主觀質量;當需要減少濾波強度時,用負的偏移量,可以保護圖像細節不被濾波器的平滑作用模糊掉。偏移量將在slice頭信息中傳輸,請參考h.264語法結構分析中的deblocking相關語法元素。

Index012345678910111213141516171819202122232425
α00000000000000004456789101213
β00000000000000002223333444
Index2627282930313233343536373839404142434445464748495051
α15172022252832364045505663718090101113127144162182203226255255
β66778899101011111212131314141515161617171818

由上述式子知道,α與β的取決于QP的大小,IndexA、IndexB與α、β對應值見下表

?

可見QP越大(Index越大),α與β就越大。QP越大意味著量化誤差越大,塊效應會越明顯,因此閾值也應該取較大值來增大濾波效果,反之閾值應該取較小值。

?

3. 濾波運算

在前面我們討論了5種邊界強度BS,當邊界強度不為0時,就需要進行邊界濾波。h.264的邊界濾波有兩種濾波器

  • BS = 1,2,3,采用強度較弱的濾波器,首先改變p0、q0兩個像素點,接著用閾值β判斷是否需要調整p1和q1
  • BS = 4,此時有兩種強度的濾波器,強濾波器可以改變6個像素點(p0、p1、p2、q0、q1、q2),弱濾波器只改變邊界上的兩個點(p0、q0)

?

(1) BS = 1,2,3時的濾波運算

①首先對邊界上的兩個像素點p0與q0進行濾波,它需要輸入p1、p0、q0、q1,濾波過程如下

image

  1. 先要得到差值Δ,差值的計算方式:Δ = ( (q0-p0)<<2 + (p1-q1) + 4 ) >> 3
  2. 然后需要對差值Δ進行限幅,保證這個差值在一定的范圍內,這個范圍主要通過查表得到,詳情請查看標準8.7.2.3
  3. 用差值Δ來計算新的p0、q0,也就是濾波后的值

?

②接下來對塊內的像素點p1與q1分別進行濾波。4:2:0以及4:2:2色度宏塊邊界的話是不需要執行這部分的濾波的。如果是要計算p1,則需要輸入p2、p1、p0、q0;如果是q1,則需要輸入p0、q0、q1、q2。

另外,只有滿足|p2-p0|<β才能對p1進行濾波,因為滿足這個條件則認為P塊內部p1處有虛假邊界,p1的濾波過程如下

image

  1. 先要得到差值Δ,差值的計算方式為:Δ = ( p2 + ((p0+q0+1)>>1) ? (p1<<1)) >> 1
  2. 然后需要對差值Δ進行限幅,保證這個差值在一定范圍內,這個范圍主要通過查表得到,詳情請查看標準8.7.2.3
  3. 用差值來計算新的p1

q1的濾波過程也是類似的步驟。

?

(2) BS = 4時的濾波運算

在h.264的幀內預測編碼中,傾向于對紋理簡單的區域用16x16亮度預測模式編碼(如藍天、白色墻面等),以達到快速編碼的目的。雖然這種方法只會在宏塊邊界引起輕微的塊效應,但是在這種情況下,即使很小的強度值查表也會在視覺上產生陡峭的階梯狀的感覺(色塊分層),因而對于這種內容平滑的宏塊邊界就需要采用較強的濾波器;如果此時宏塊邊界有大量的細節存在,反而不應做強濾波。對此h.264仍采用閾值法來判斷是否存在真實邊界,如果不存在大量細節信息,可以做強濾波,反之做弱濾波。

這里的濾波是比較好理解的抽頭濾波器,P、Q塊上的濾波過程差不多,這里以P塊為例。

對于P塊的點,如果滿足下式,則認為細節信息不多:

$\left\{\begin{matrix}
|p0-q0|&<&(\alpha >> 2)+2\\
|p2-p0|&<&\beta
\end{matrix}\right.$

采用強濾波

$\left\{\begin{matrix}
p0 &= &(p2+2p1+2p0+2q0+q1+4)>>3\\
p1 &= &(p2+p1+p0+q0+2)>>2 \\
p2 &= &(2p3+3p2+p1+p0+q0+4)>>3
\end{matrix}\right.$

否則采用弱濾波,只改變p0點

$p0 = (2p1+p0+q1+2)>>2$

?

?

參考文獻

ITU-T Rec. H.264 (04-2013) Advanced video coding for generic audiovisual services

陳靖、劉京、曹喜信:深入理解視頻編解碼技術——基于H.264標準及參考模型

轉載于:https://www.cnblogs.com/TaigaCon/p/5500110.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374659.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374659.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android開發的知識點(一)

1.android中背景圖的設置&#xff1a; 將背景圖放入到項目中的res/drawable-hdpi或res/drawable-mdpi或res/drawable-xhdpi或res/drawable-xxhdpi等任一文件夾下。然后在layout的xml文件夾下使用android:background"drawable/背景圖名"&#xff0c;其中背景圖必須是p…

566. 重塑矩陣

在 MATLAB 中&#xff0c;有一個非常有用的函數 reshape &#xff0c;它可以將一個 m x n 矩陣重塑為另一個大小不同&#xff08;r x c&#xff09;的新矩陣&#xff0c;但保留其原始數據。 給你一個由二維數組 mat 表示的 m x n 矩陣&#xff0c;以及兩個正整數 r 和 c &…

RabbitMQ播放模塊! 構架

RabbitMQ提供了具有可預測且一致的吞吐量和延遲的高可用性&#xff0c;可伸縮和便攜式消息系統。 RabbitMQ是AMQP &#xff08;業務消息傳遞的開放標準&#xff09;的領先實現 &#xff0c;并且通過適配器支持XMPP&#xff0c;SMTP&#xff0c;STOMP和HTTP來進行輕量級Web消息傳…

Cyclic Nacklace - HDU 3746(next求循環節)

題目大意&#xff1a;給你一些串&#xff0c;問如果想讓這個串里面的循環節至少循環兩次&#xff0c;需要添加幾個字符&#xff08;只能在最前面或者最后面添加&#xff09;。比如ababc 需要添加5個就是添加ababc。 分析&#xff1a;其實字符串的長度len-next[len] 最小循環節…

Xuggler開發教程

大家好&#xff0c; 在這篇文章中&#xff0c;我想介紹JavaCodeGeeks上的一些很酷的新教程。 他們將討論與Xuggler &#xff0c; FFmpeg和Wowza進行媒體&#xff08;音頻/視頻&#xff09;操縱的方式。 我將在這篇文章中跟蹤所有相關的教程。 您可以通過查看Pat較早的關于使用…

739. 每日溫度

請根據每日 氣溫 列表 temperatures &#xff0c;請計算在每一天需要等幾天才會有更高的溫度。如果氣溫在這之后都不會升高&#xff0c;請在該位置用 0 來代替。 代碼一 單調棧 class Solution {public int[] dailyTemperatures(int[] temperatures) {int length temperatur…

一個非常好的性格切割問題

結伙stackoverflow看到一道非常不錯的問題。遂拿來分享之。 題目要求&#xff1a;我有一個非常長的字符串&#xff1a; String s1"This is my world. This has to be broken." 我要把上面的字符串打亂以固定的長度&#xff08;比如10&#xff09;使得輸出為&#xff…

Cajo,用Java完成分布式計算的最簡單方法

摘自Jonas Boner在2006年5月1日發布在TheServerSide.com上的文章“ Distributed Computing Easy”中的介紹部分&#xff1a; 分布式計算在企業應用程序開發世界中變得越來越重要。 如今&#xff0c;開發人員不斷需要解決以下問題&#xff1a;如何通過將應用程序擴展到單個節點之…

Java中Integer.parseInt()用法

1.先看看該方法的實現 public static int parseInt(String s) throws NumberFormatException {return parseInt(s,10);}2.事實上他可以有兩個參數&#xff0c; public static int parseInt(String s,int radix)意味著將字符串s按照radix進制轉換成整數。太抽象了&#xff0c;…

關于maven相互依賴的工程部署問題

環境&#xff1a;win7 64位&#xff0c;myeclipse10.6&#xff0c;eclipse4.5&#xff0c;都配置了svn插件 問題描述&#xff1a;1、工程模塊化之后都是通過pom配置model來關聯的&#xff0c;svn提交之后&#xff0c;通過myeclipse的svn‘檢出為項目’&#xff0c;依賴的子工程…

什么是JAR包?

jar包就是別人已經寫好的一些類&#xff0c;然后將這些類進行打包&#xff0c;你可以將這些jar包引入你的項目中&#xff0c;然后就可以直接使用這些jar包中的類和屬性了&#xff0c;這些jar包一般都會放在lib目錄下的 轉載于:https://www.cnblogs.com/wulianshang/p/5513474.h…

....

輸入流和輸出流相對于內存設備而言. 將外設中的數據讀取到內存中:輸入將內存的數寫入到外設中&#xff1a;輸出。 字符流的由來&#xff1a;其實就是&#xff1a;字節流讀取文字字節數據后&#xff0c;不直接操作而是先查指定的編碼表。獲取對應的文字。在對這個文字進行操作。…

DataNucleus 3.0與Hibernate 3.5

如官方產品站點所述&#xff0c; DataNucleus Access Platform是現有的最符合標準的開源Java持久性產品。 它完全符合JDO1 &#xff0c; JDO2 &#xff0c; JDO2.1 &#xff0c; JDO2.2 &#xff0c; JDO3 &#xff0c; JPA1和JPA2 Java標準。 它還符合OGC簡單功能規范&#xf…

手工內存管理規則的總結

1.如果需要保持一個對象不被銷毀,可以使用retain.在使用完對象后,需要使用release銷毀 2.給對象發送release消息并不會銷毀對象,只有當這個對象的引用計數減為0時,對象才會被銷毀.然后系統會發送dealloc消息給這個對象用于釋放它的內存. 對使用了retain或者copy,mutableCopy,al…

Java 字符,整型,字符串三者轉換

1.整型 —> 字符型 先把整型轉化為字符串&#xff0c;再把字符串轉化為字符 //整型 ---> 字符型 toString(int n).charAt(int index) System.out.println(Integer.toString(20).charAt(0));2.整型 —> 字符串 //整型 ---> 字符串 Inte…

AngularJS 的常用特性(二)

3、列表、表格以及其他迭代型元素 ng-repeat可能是最有用的 Angular 指令了&#xff0c;它可以根據集合中的項目一次創建一組元素的多份拷貝。 比如一個學生名冊系統需要從服務器上獲取學生信息&#xff0c;目前先把模型之間定義在 JavaScript 代碼里面&#xff1a; 1 var stud…

Ruby,Python和Java中的Web服務

今天&#xff0c;我不得不準備一些示例來說明Web服務是可互操作的。 因此&#xff0c;我已經使用Metro使用Java創建了一個簡單的Web服務&#xff0c;并在Tomcat上啟動了它。 然后嘗試使用Python和Ruby消耗它們。 這是全部完成的過程… Java中的Web服務 我從Java中的簡單Web服…

bzoj4199: [Noi2015]品酒大會

題面見http://uoj.ac/problem/131 一道后綴數組題 先求出height&#xff0c;然后從大到小枚舉每個height。 然后對于每個height值&#xff0c;兩端的集合中任意一對后綴的LCP都是這個height。 我們統計答案之后合并兩端的集合&#xff0c;用并查集維護即可。 1 #include<cst…

css中position初解

positon:static|absolute|relative|fiexd 1、static為默認值&#xff0c;沒有定位&#xff0c;元素出現在正常的文檔流中&#xff0c;忽略left,right,top,bottom,i-index值。 2、absolute為絕對定位&#xff0c;通過left,top等值對元素進行定位&#xff0c;定位時如果父元素的p…

零XML的Spring配置

Tomasz Nurkiewicz是我們的JCG合作伙伴之一&#xff0c;也是Spring框架的堅定支持者&#xff0c;在他的最新文章中描述了如何在不使用XML的情況下配置Spring應用程序。 注解方法在頂部。 查看他的教程&#xff1a; 沒有XML的Spring框架...根本&#xff01; 翻譯自: https://ww…