H.264---CABAC---自適應算術算術編碼部分
轉自:https://www.cnblogs.com/CATHY-MU/p/6189617.html
1、算術編碼
早在1948年,夏農就提出將信源符號依其出現的概率降序排序,用符號序列累計概率的二進值作為對芯源的編碼,並從理論上論證了它的優越性。1960年, Peter Elias發現無需排序,只要編、解碼端使用相同的符號順序即可,提出了算術編碼的概念。Elias沒有公佈他的發現,因為他知道算術編碼在數學上雖然成 立,但不可能在實際中實現。1976年,R. Pasco和J. Rissanen分別用定長的暫存器實現了有限精度的算術編碼。1979年Rissanen和G. G. Langdon一起將算術編碼系統化,並於1981年實現了二進位制編碼。1987年Witten等人發表了一個實用的算術編碼程式,即CACM87(後用 於ITU-T的H.263視訊壓縮標準)。同期,IBM公司發表了著名的Q-編碼器(後用於JPEG和JBIG影象壓縮標準)。從此,算術編碼迅速得到了 廣泛的注意。
算術編碼的基本原理是將編碼的訊息表示成實數0和1之間的一個間隔(Interval),訊息越長,編碼表示它的間隔就越小,表示這一間隔所需的二進位制位就越多。
算術編碼用到兩個基本的引數:符號的概率和它的編碼間隔。信源符號的概率決定壓縮編碼的效率,也決定編碼過程中信源符號的間隔,而這些間隔包含在0到1之間。編碼過程中的間隔決定了符號壓縮後的輸出。
給定事件序列的算術編碼步驟如下:
(1)編碼器在開始時將“當前間隔” [ L, H) 設定為[0,1)。
(2)對每一事件,編碼器按步驟(a)和(b)進行處理
(a)編碼器將“當前間隔”分為子間隔,每一個事件一個。
(b)一個子間隔的大小與下一個將出現的事件的概率成比例,編碼器選擇子間隔對應於下一個確切發生的事件相對應,並使它成為新的“當前間隔”。
(3)最後輸出的“當前間隔”的下邊界就是該給定事件序列的算術編碼。
設Low和High分別表示“當前間隔”的下邊界和上邊界,CodeRange為編碼間隔的長度,LowRange(symbol)和HighRange(symbol)分別代表為了事件symbol分配的初始間隔下邊界和上邊界。上述過程的實現可用虛擬碼描述如下:
set Low to 0
set High to 1
while there are input symbols do
take a symbol
CodeRange = High – Low
High = Low + CodeRange *HighRange(symbol)
Low = Low + CodeRange * LowRange(symbol)
end of while
output Low
算術碼解碼過程用虛擬碼描述如下:
get encoded number
do
find symbol whose range straddles the encoded number
output the symbol
range = symbo.LowValue – symbol.HighValue
substracti symbol.LowValue from encoded number
divide encoded number by range
until no more symbols
算術編碼器的編碼解碼過程可用例子演示和解釋。
例1:假設信源符號為{A, B, C, D},這些符號的概率分別為{ 0.1, 0.4, 0.2,0.3 },根據這些概率可把間隔[0, 1]分成4個子間隔:[0, 0.1], [0.1, 0.5], [0.5, 0.7], [0.7, 1],其中[x,y]表示半開放間隔,即包含x不包含y。上面的資訊可綜合在表03-04-1中。
表03-04-1 信源符號,概率和初始編碼間隔
符號 |
A |
B |
C |
D |
概率 |
0.1 |
0.4 |
0.2 |
0.3 |
初始編碼間隔 |
[0, 0.1) |
[0.1, 0.5) |
[0.5, 0.7) |
[0.7, 1] |
如果二進位制訊息序列的輸入為:C A D A C D B。編碼時首先輸入的符號是C,找到它的編碼範圍是[0.5,0.7]。由於訊息中第二個符號A的編碼範圍是[0, 0.1],因此它的間隔就取[0.5, 0.7]的第一個十分之一作為新間隔[0.5,0.52]。依此類推,編碼第3個符號D時取新間隔為[0.514, 0.52],編碼第4個符號A時,取新間隔為[0.514, 0.5146],…。訊息的編碼輸出可以是最後一個間隔中的任意數。
這個例子的編碼和譯碼的全過程分別表示在表03-04-2和表03-04-3中。
表03-04-2 編碼過程
步驟 |
輸入符號 |
編碼間隔 |
編碼判決 |
1 |
C |
[0.5, 0.7] |
符號的間隔範圍[0.5, 0.7] |
2 |
A |
[0.5, 0.52] |
[0.5, 0.7]間隔的第一個1/10 |
3 |
D |
[0.514, 0.52] |
[0.5, 0.52]間隔的最後一個1/10 |
4 |
A |
[0.514, 0.5146] |
[0.514, 0.52]間隔的第一個1/10 |
5 |
C |
[0.5143, 0.51442] |
[0.514, 0.5146]間隔的第五個1/10開始,二個1/10 |
6 |
D |
[0.514384, 0.51442] |
[0.5143, 0.51442]間隔的最後3個1/10 |
7 |
B |
[0.5143836, 0.514402] |
[0.514384,0.51442]間隔的4個1/10,從第1個1/10開始 |
8 |
從[0.5143876, 0.514402]中選擇一個數作為輸出:0.5143876 |
表03-04-3 譯碼過程
步驟 |
間隔 |
譯碼符號 |
譯碼判決 |
1 |
[0.5, 0.7] |
C |
0.51439在間隔 [0.5, 0.7) |
2 |
[0.5, 0.52] |
A |
0.51439在間隔 [0.5, 0.7)的第1個1/10 |
3 |
[0.514, 0.52] |
D |
0.51439在間隔[0.5, 0.52)的第7個1/10 |
4 |
[0.514, 0.5146] |
A |
0.51439在間隔[0.514, 0.52]的第1個1/10 |
5 |
[0.5143, 0.51442] |
C |
0.51439在間隔[0.514, 0.5146]的第5個1/10 |
6 |
[0.514384, 0.51442] |
D |
0.51439在間隔[0.5143, 0.51442]的第7個1/10 |
7 |
[0.51439, 0.5143948] |
B |
0.51439在間隔[0.51439,0.5143948]的第1個1/10 |
8 |
譯碼的訊息:C A D A C D B |
在上面的例子中,我們假定編碼器和譯碼器都知道訊息的長度,因此譯碼器的譯碼過程不會無限制地執行下去。實際上在譯碼器中需要新增一個專門的終止符,當譯碼器看到終止符時就停止譯碼。
在算術編碼中有幾個問題需要注意:
· 由於實際的計算機的精度不可能無限長,一個明顯的問題是運算中出現溢位,但多數機器都有16、32或者64位的精度,因此這個問題可使用比例縮放方法解決。
· 算術編碼器對整個訊息只產生一個碼字,這個碼字是在間隔[0,1]中的一個實數,因此譯碼器在接受到表示這個實數的所有位之前不能進行譯碼。
· 算術編碼也是一種對錯誤很敏感的編碼方法,如果有一位發生錯誤就會導致整個訊息譯錯。
算術編碼可以是靜態的或者自適應的。在靜態算術編碼中,信源符號的概率是固定的。在自適應算術編碼中,信源符號的概率根據編碼時符號出現的頻繁程度動態地 進行修改,在編碼期間估算信源符號概率的過程叫做建模。需要開發動態算術編碼的原因是因為事先知道精確的信源概率是很難的,而且是不切實際的。當壓縮訊息 時,我們不能期待一個算術編碼器獲得最大的效率,所能做的最有效的方法是在編碼過程中估算概率。因此動態建模就成為確定編碼器壓縮效率的關鍵。
此外,在算術編碼的使用中還存在版權問題。JPEG標準說明的算術編碼的一些變體方案屬於IBM, AT&T和Mitsubishi擁有的專利。要合法地使用JPEG算術編碼必須得到這些公司的許可。
2、算術編碼的自適應性