算術編碼轉載1

算術編碼是一種無損數據壓縮方法,也是一種熵編碼的方法。和其它熵編碼方法不同的地方在於,其他的熵編碼方法通常是把輸入的消息分區爲符號,然後對每個符號進行編碼,而算術編碼是直接把整個輸入的消息編碼爲一個數,一個滿足(0.0 ≤ n < 1.0)的小數n。
1,編碼
算術編碼將整個要編碼的數據映射到一個位於[0,1)的實數區間中。並且輸出一個小於1同時大於0的小數來表示全部數據。利用這種方法算術編碼可以讓壓縮率無限的接近數據的熵值,從而獲得理論上的最高壓縮率。
算術編碼進行編碼時,從實數區間[0,1)開始。按照符號的頻度將當前的區間分割成多個子區間。根據當前輸入的符號選擇對應的子區間,然後從選擇的子區間 中繼續進行下一輪的分割。不斷的進行這個過程,直到所有符號編碼完畢。對於最後選擇的一個子區間,輸出屬於該區間的一個小數。這個小數就是所有數據的編 碼。現在來舉個例子。假設一份數據由“A”、“B”、“C”三個符號組成。現在要編碼數據“BCCB”,編碼過程如圖所示。
算術編碼
首先說明一點,這裏使用的是自適應模型。也就是說一開始時,三個符號的頻度都是1。隨着編碼的進行再更新頻度。另外,在計算時理論上要使用無限小數。這裏爲了說明方便,四捨五入到小數點後4位。

觀察圖可以發現算術編碼的過程。首先,算術編碼是從區間[0,1)開始的。這時三個符號的概率都是1 / 3,按照這個概率分割區間。第一個輸入的符號是“B”,所以我們選擇子區間[0.3333,0.6667)作爲下一個區間。輸入“B”後更新頻度,根據新 的概率對區間[0.3333,0.6667)進行分割。這時輸入的符號是“C”,我們可以選擇子區間[0.5834,0.6667)。繼續更新頻度、分割 區間、選擇子區間,直到符號全部編碼完成。我們最後得到的區間是[0.6390,0.6501)。輸出屬於這個區間的一個小數,例如0.64。那麼經過算 術編碼的壓縮,數據“BCCB”最後輸出的編碼就是0.64。

2,解碼

算術 編碼進行解碼時僅輸入一個小數。解碼前首先需要對區間[0,1)按照初始時的符號頻度進行分割。然後觀察輸入的小數位於那個子區間。輸出對應的符號,選擇 對應的子區間,然後從選擇的子區間中繼續進行下一輪的分割。不斷的進行這個過程,直到所有的符號都解碼出來。整個過程相當於編碼時的逆運算。

在我們的例子中,輸入的小數是0.64。首先,初始時三個符號的概率都是1 / 3,按照這個概率分割區間。觀察圖2.1可以發現0.64落在子區間[0.3333,0.6667)中,於是可以解碼出“B”。並且選擇子區間 [0.3333,0.6667)作爲下一個區間。輸出“B”後更新頻度,根據新的概率對區間[0.3333,0.6667)進行分割。這時0.64落在子 區間[0.5834,0.6667)中,於是可以解碼出“C”。按照上述過程進行,直到所有的符號都解碼出來。可見,只需要一個小數就可以完整還原出原來 的所有數據。

3,編碼過程

用[1,0)區間編碼,顯然是不科學的,況且,幾乎是不可能的!
因此採用整數編碼方式,以下將以8位編碼爲例,闡述算術編碼和解碼過程.

1,以下將以字符串"ababcab"爲例進行講述.
2,首先我們已經知道要編碼的字符串中只有a,b,c三種字符;
3,由以上信息,對下一圖表進行初始化
(其中,high表示:8位的最大數字255,即,編碼上界,low即0位表示的最小數字,亦即編碼下界,a1表示:兩條虛線之間爲a,1表示在"自適應"中所用可能出現的字符,都初始其權值(個數)爲1)
high--------------255--------
    c1
------------------
    b1
------------------
    a1
low---------------0----------

4,現在開始編碼:首先"ababcab"第1個字符爲a
當前所有字符的個數總和total=3
low不變;
high = low + 1*(high-low)/total;(其中1是當前a的個數)
於是:
low=0;
high = 0 + 1*(255-0)/3 = 85;且a的權值加1
high--------------85--------
    c1
------------------
    b1
------------------
    a2
low---------------0----------

5,"ababcab"第2個字符爲b
當前所有字符的個數總和total=4
low = low + <2*(high-low)/total>;(其中2是當前a的個數,"z = "運算表示:z = x/y + ((x%y) ? 1 : 0);)
high = low + 3*(high-low)/total;(其中3是當前a的個數加b的個數之和)
於是:
low= 0 + <2*(85-0)/4> = 43;
high = 0 + 3*(85-0)/4 = 63;
high--------------63--------
    c1
------------------
    b2
------------------
    a2
low---------------43----------

6,"ababcab"第3個字符爲a.同理可得:
high--------------51--------
    c1
------------------
    b2
------------------
    a3
low---------------43----------

7,"ababcab"第4個字符爲b.同理可得:
high--------------49--------
    c1
------------------
    b3
------------------
    a3
low---------------47----------
此時再進行下一輪,high=49,low=49於是問題出現了,因爲是有限整數,每次又是取的上一區間的子區間,high和low趨於相等是必然的.
我們在此使用high和low向左移的方式進行擴大區間(極限情況:有資料提出,位移後low的二進制首位爲0,其他位爲全1,high的二進制首位爲1,其他位爲全0,如8位時:low=01111111B,high=10000000B的情況,暫時保留)
位移時保證兩個原則:(1),保證high-low>=total否則繼續位移,(2),保證[low, high]在上一個[low, high]的子區間.(其實,只需要位移即可,此條,已經在"z="運算是得到了保證)
兩者左移1位後溢出位用新變量存儲,假設爲out,同理out到底存了幾個位,我們用bits保存.
所以:
a),進行第1次位移
total=7
out=0B;(0B表示二進制0,例如:0x86=10000110B)
bits=1;
high=49<<1=98;
low=47<<1=94;
不滿足"位移原則1"

b),進行第2次位移
total=7
out=00B;
bits=2;
high=98<<1=196;
low=94<<1=188;
high--------------196--------
    c1
------------------
    b3
------------------
    a3
low---------------188---------
滿足"位移原則1",進行下一輪

8,"ababcab"第5個字符爲c.同理可得:
high--------------196--------
    c2
------------------
    b3
------------------
    a3
low---------------195----------
由(7)可知,又要"位移"了
a),進行第3次位移
total=8
out=001B;
bits=3;
high=196<<1=136;
low=195<<1=134;
不滿足"位移原則1"

b),進行第4次位移
total=8
out=0011B;
bits=4;
high=136<<1=16;
low=134<<1=12;
不滿足"位移原則1"

c),進行第5次位移
total=8
out=00110B;
bits=5;
high=16<<1=32;
low=12<<1=24;
high--------------32--------
    c2
------------------
    b3
------------------
    a3
low---------------24---------
滿足"位移原則1",進行下一輪

9,"ababcab"第6個字符爲a.同理可得:
high--------------27--------
    c2
------------------
    b3
------------------
    a4
low---------------24----------
於是:
a),進行第6次位移
total=9
out=001100B;
bits=6;
high=27<<1=54;
low=24<<1=48;
不滿足"位移原則1"

b),進行第7次位移
total=9
out=0011000B;
bits=7;
high=54<<1=108;
low=48<<1=96;
high--------------108--------
    c2
------------------
    b3
------------------
    a4
low---------------96---------
滿足"位移原則1",進行下一輪

10,"ababcab"第7個字符爲b.也是最後一個
high--------------105--------
    c2
------------------
    b4
------------------
    a4
low---------------102---------
high=105,low=102也是最後的區間,後面已經沒有字符,我們無須"位移",僅記下此區間的某一個數即可,如:magic=104.

11,整個編碼過程就結束了.現在我們得到了以下幾條信息:
(a),原字符串只有a,b,c,初始區間是0-255
(b),out=0011000B; bits=7; magic=104.

下面,我們將用以上(a),(b)兩條信息,還原字符串"ababcab"

12,同樣由信息(a)初始化圖表,如下:
high--------------255--------
    c1
------------------170--------
    b1
------------------85---------
    a1
low---------------0----------

由信息(b),out=0011000B; bits=7; magic=104.
於是可以得到一個bits+sizeof(magic)*8 = 15位的數X = 001100001101000B = out<<8 | magic;
我們取X的高8位,得到d = 00110000B = 48;

13,顯然我們可以從12中得知d = 00110000B = 48;是a所在區間,於是解壓的字符串xcode = "a"
並且此時區間變成:(其實,現在得出一個結論:區間嚴格說是"[low, high)")
high--------------85--------
    c1
------------------63--------
    b1
------------------43--------
    a2
low---------------0---------

14,與13同理d = 00110000B = 48;是b所在區間,於是解壓的字符串xcode = "ab"
區間變成:
high--------------63--------
    c1
------------------?---------
    b2
------------------51----------
    a2
low---------------43----------

15,與13同理d = 00110000B = 48;是a所在區間,於是解壓的字符串xcode = "aba"
區間變成:
high--------------51---------
    c1
------------------49---------
    b2
------------------47---------
    a3
low---------------43----------
此時"位移原則1"仍滿足,不位移

16,與13同理d = 00110000B = 48;是b所在區間,於是解壓的字符串xcode = "abab"
區間變成:
high--------------49---------
    c1
------------------
    b3
------------------
    a3
low---------------47----------
此時"位移原則1"不滿足,進行位移

17,d去掉首位,取得X接下來的8位,即
d = 01100001B = 97;
total=7;
high=98;
low=94
此時"位移原則1"不滿足,再位移

d = 11000011B = 195;
total=7;
high=196;
low=188;

high--------------196---------
    c1
------------------195---------
    b3
------------------?-----------
    a3
low---------------47----------
此時"位移原則1"滿足,下一輪位移

18,由17所得,d = 11000011B = 195;是c所在區間[low, high),於是解壓的字符串xcode = "ababc"
區間變成:
high--------------196---------
    c2
------------------
    b3
------------------
    a3
low---------------195----------
此時:
total=8;
high=196;
low=195;
"位移原則1"不滿足,位移

d = 10000110B = 131;
total=8;
high=high<<1=136;
low=low<<1=134;
"位移原則1"不滿足,位移

d = 00001101B = 25;
total=8;
high=high<<1=32;
low=low<<1=24;
"位移原則1"滿足,
區間變成:
high--------------32----------
    c2
------------------?-----------
    b3
------------------27----------
    a3
low---------------24----------

19,由18所得,d = 00001101B = 25;是a所在區間,於是解壓的字符串xcode = "ababca"
區間變成:
high--------------27---------
    c2
------------------
    b3
------------------
    a4
low---------------24----------
此時:
total=9;
high=27;
low=25;
"位移原則1"不滿足,位移
"0001101000B"
d = 00011010B = 26;
total=9;
high=high<<1=54;
low=low<<1=48;
"位移原則1"不滿足,位移
d = 00110100B = 52;
total=9;
high=high<<1=108;
low=low<<1=96;
"位移原則1"滿足,但是d = 00110100B = 52;不在[low, high)區間,於是d位移;
d = 01101000B = 104;(此時d已經用盡X)
high--------------108---------
    c2
------------------105---------
    b3
------------------102---------
    a4
low---------------96----------

20,由19所得,d = 01101000B = 104;是b所在區間,於是解壓的字符串xcode = "ababcab"
區間變成:
high--------------105---------
    c2
------------------
    b3
------------------
    a4
low---------------102----------

"位移原則1"不滿足,位移
d = 01101000B = 104;
total=9;
high=high<<1=164;
low=low<<1=152;
"位移原則1"滿足,但是d = 01101000B = 104;不在[low, high)區間,於是d位移;
並且d用盡X不能再一次取,故解壓完成!(若再知道total=9,也可以使解壓程序退出).

21,總結,我們再一次看看11.我們提供的信息
(a),原字符串只有a,b,c,初始區間是0-255
(b),out=0011000B; bits=7; magic=104.


--------------------------------------------------------------------------------------------------
在第6步,我們"使用high和low向左移的方式進行擴大區間"(極限情況:有資料提出,位移後low的二進制首位爲0,其他位爲全1,high的二進制首位爲1,其他位爲全0,如8位時:low=01111111B,high=10000000B的情況,暫時保留)
貌似在我們的編碼規範中,擴展後出現這個現象是不可能的.因爲,位移時high,low都是左移1位.而資料多數是,high左移1位,low左移1位再加1.
但是,每次給high和low重新賦值時,產生上述情況是有可能的.
出現該現象時,我們可以規定,保留相同位,並將該區間擴展至原始區間,如8位是[0, 255);32位是[0, 0xffffffff);
Good Luck !

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