多媒體技術相關壓縮算法

1、香農編碼


這個例子展示了一組字母的香濃編碼結構(如圖a所示)這五個可被編碼的字母有如下出現次數:

Symbol

A

B

C

D

E

Count

15

7

6

6

5

Probabilities

0.38461538

0.17948718

0.15384615

0.15384615

0.12820513

從左到右,所有的符號以它們出現的次數劃分。在字母B與C之間劃定分割線,得到了左右兩組,總次數分別爲22,17。 這樣就把兩組的差別降到最小。通過這樣的分割, A與B同時擁有了一個以0爲開頭的碼字, C,D,E的碼子則爲1,如圖b所示。 隨後, 在樹的左半邊,於A,B間建立新的分割線,這樣A就成爲了碼字爲00的葉子節點,B的碼子01。經過四次分割, 得到了一個樹形編碼。 如下表所示,在最終得到的樹中, 擁有最大頻率的符號被兩位編碼, 其他兩個頻率較低的符號被三位編碼。

符號

A

B

C

D

E

編碼

00

01

10

110

111


 

2、哈夫曼編碼

 

 

 

 

3、算術編碼(理解即可)

算術編碼的基本原理是將編碼的消息表示成實數0和1之間的一個間隔(Interval),消息越長,編碼表示它的間隔就越小,表示這一間隔所需的二進制位就越多。

算術編碼用到兩個基本的參數:符號的概率和它的編碼間隔。信源符號的概率決定壓縮編碼的效率,也決定編碼過程中信源符號的間隔,而這些間隔包含在0到1之間。編碼過程中的間隔決定了符號壓縮後的輸出。

給定事件序列的算術編碼步驟如下:

(1)編碼器在開始時將“當前間隔” [ L, H) 設置爲[0,1)。

(2)對每一事件,編碼器按步驟(a)和(b)進行處理

  (a)編碼器將“當前間隔”分爲子間隔,每一個事件一個。

  (b)一個子間隔的大小與下一個將出現的事件的概率成比例,編碼器選擇子間隔對應於下一個確切發生的事件相對應,並使它成爲新的“當前間隔”。

(3)最後輸出的“當前間隔”的下邊界就是該給定事件序列的算術編碼。

例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

概率

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-1所示。

 

圖03-04-1 算術編碼過程舉例

 

這個例子的編碼和譯碼的全過程分別表示在表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

 

4、遊程編碼

行程編碼的基本原理是:用一個符號值或串長代替具有相同值的連續符號(連續符號構成了一段連續的“行程”。行程編碼因此而得名),使符號長度少於原始數據的長度。只在各行或者各列數據的代碼發生變化時,一次記錄該代碼及相同代碼重複的個數,從而實現數據的壓縮。

常見的遊程編碼格式包括TGA,Packbits,PCX以及ILBM。

例如:5555557777733322221111111

行程編碼爲:(5,6)(7,5)(3,3)(2,4)(1,7)。可見,行程編碼的位數遠遠少於原始字符串的位數。

並不是所有的行程編碼都遠遠少於原始字符串的位數,但行程編碼也成爲了一種壓縮工具。

5、LZ77

算法核心是查找從前向緩衝存儲器開始的最長匹配串

編碼算法的具體執行步驟如下:

把編碼位置設置到輸入數據流的開始位置

查找窗口中最長匹配串

以(Pointer, Length,Characters)的格式輸出,其中Pointer是指向窗口中匹配串的指針,Length表示匹配字符的長度,Characters是前向緩衝存儲器中的不匹配的第1個字符,如果沒有匹配,輸出形式爲( 0, 0, new symbol )

如果前向緩衝存儲器不是空的,則把編碼位置和窗口向前移(Length+1)個字符,然後返回到步驟2

 

 

6、LZ78

LZ78算法的基本思路與LZ77算法類似,也是利用已經處理過的編碼信息,但它發生匹配時,不是保存一個三元組,而是一個二元組:匹配位置和不匹配的第一個字符。同時,還要將這個字符串保存到內存中,爲此,它需要一個不斷增長的編碼字串表(字典)。

與LZ77相比,LZ78的最大優點是在每個編碼步驟中減少了字符串比較的數目,而壓縮率與LZ77類似。

如對符號串“ababcbabaaaaaaa”編碼,需要的字典:

 

編碼步驟

1 在開始時,詞典和當前前綴P都是空的

2 當前字符C:=字符流中的下一個字符

3 判斷P+C是否在詞典中:

  a.是:用C擴展P,P:= P+C

  b.否:① 輸出與P相對應的碼字和當前字符C

        ② 把P+C 添加到詞典中

        ③ 令P:=空值

4.判斷字符流中是否還有字符需要編碼

  a.是:返回到步驟2

  b.否:若P非空,輸出相應碼字,結束

LZ78編碼示例

ABBCBCABABCAABCAAB

 

(0,A)(0,B)(2,C)(3,A)(2,A)(4,A)(6,B)

7、LZW

LZW算法-編碼原理

Welch modification (Welch 1984)

爲了解決在發送新字符時的低效問題

與LZ78的區別

LZW只輸出代表詞典中的綴-符串(String)的碼字(code word),因此開始時詞典被初始化爲包含可能在字符流出現中的所有單字符

由於所有可能出現的單個字符都事先包含在詞典中,每個編碼步驟開始時都使用單字符前綴(one-character prefix),因此在詞典中搜索的第1個綴-符串有兩個字符

LZW算法-編碼步驟

1:開始時的詞典包含所有單字符,當前前綴P爲空

2:當前字符C:=字符流中的下一個字符;

3:判斷綴-符串P+C是否在詞典中

   (1) 是:P:= P+C;  //用C擴展P

   (2) 否:

       ① 把代表當前前綴P的碼字輸出到碼字流;

       ② 把綴-符串P+C添加到詞典;

       ③ 令P:= C;   //現在的P僅包含一個字符C

4: 判斷碼字流中是否還有碼字要譯

    (1) 是,就返回到步驟2;

    (2) 否

        ① 把代表當前前綴P的碼字輸出到碼字流;

        ② 結束。

LZW算法-編碼示例

 

LZW算法-解碼步驟

 


1:在開始譯碼時詞典包含所有單字符

2:cW:=碼字流中的第一個碼字,輸出String.cW到碼字流。

3:先前碼字pW:=當前碼字cW,

4:當前碼字cW:=碼字流中的下一個碼字。

5:判斷String.cW是否在詞典中

   (1) 是,則:

       ① String.cW輸出到字符流

       ② P:=String.pW,C:=Sting.cW的第一個字符。

       ③ 把P+C添加到詞典。

   (2) 否,則:

       ① P:=String.pW,C:=String.pW的第一個字符。

       ② 輸出P+C到字符流,然後把它添加到詞典中。

6: 判斷碼字流中是否還有碼字要譯

    (1) 是,就返回到步驟3。

    (2) 否, 結束。


 

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