1、算術編碼簡介
算術編碼是一種無損數據壓縮方法,也是一種熵編碼的方法。和其它熵編碼方法不同的地方在於,其他的熵編碼方法通常是把輸入的消息分割爲符號,然後對每個符號進行編碼。而算術編碼是直接把整個輸入的消息編碼爲一個數,一個滿足(0.0 ≤ n < 1.0)的小數n。
算術編碼用到兩個基本的參數:符號的概率和它的編碼間隔。信源符號的概率決定壓縮編碼的效率,也決定編碼過程中信源符號的間隔,而這些間隔包含在0到1之間。
2、算術編碼的算法思想如下:
(1)對一組信源符號按照符號的概率從大到小排序,將[0,1)設爲當前分析區間。按信源符號的概率序列在當前分析區間劃分比例間隔。(2)檢索“輸入消息序列”,鎖定當前消息符號(初次檢索的話就是第一個消息符號)。找到當前符號在當前分析區間的比例間隔,將此間隔作爲新的當前分析區間。並把當前分析區間的起點(即左端點)指示的數“補加”到編碼輸出數裏。當前消息符號指針後移。
(3)仍然按照信源符號的概率序列在當前分析區間劃分比例間隔。然後重複第二步。直到“輸入消息序列”檢索完畢爲止。
(4)最後的編碼輸出數就是編碼好的數據。
3、在算術編碼中需要注意幾個問題:
(1)由於實際計算機的精度不可能無限長,運算中出現溢出是一個明顯的問題,但多數及其都有16位,32位或者64位的精度,因此這個問題可以使用比例縮放方法解決。
(2)算術編碼器對整個消息只產生一個碼字,這個碼字是在間隔[0,1)中的一個實數,因此譯碼器在接受到表示這個實數的所有位之前不能進行譯碼。
(3)算術編碼是一種對錯誤很敏感的編碼方法,如果有一位發生錯誤就會導致整個消息譯錯。
算術編碼可以是靜態的或者是自適應的。在靜態算術編碼中,信源符號的概率是固定的。在自適應算術編碼中,信源符號的概率根據編碼時符號出現的頻率動態地進行修改,在編碼期間估算信源符號概率的過程叫做建模。需要開發動態算術編碼的原因是因爲事前知道精確的信源概率是很難的,而且不切實際。當壓縮消息時,不能期待一個算術編碼器獲得最大的效率,所能做的最有效的方法是在編碼過程中估算概率。因此動態建模就成爲確定編碼器壓縮效率的關鍵。
4、示例
算術編碼器的編碼解碼過程可用例子演示和解釋。
例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-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 |
在上面的例子中,我們假定編碼器和譯碼器都知道消息的長度,因此譯碼器的譯碼過程不會無限制地運行下去。實際上在譯碼器中需要添加一個專門的終止符,當譯碼器看到終止符時就停止譯碼。
5、MATLAB代碼
clear all;
clc;
in='00000011111010101';
pr=[0.5 0.5]; %各字符出現的概率
temp=[0.0 0.5 1.0];
orignal=temp;
n=length(in);
%編碼
for i=1:n
width=temp(3)-temp(1);
w=temp(1);
switch in(i)
case '0'
m=1;
case '1'
m=2;
end
temp(1)=w+orignal(m)*width;
temp(3)=w+orignal(m+1)*width;
left=temp(1);
right=temp(3);
fprintf('left=%.6f',left);
fprintf(' ');
fprintf('right=%.6f\n',right);
end
encode=(temp(1)+temp(3))/2
%解碼
decode=['0'];
for i=1:n
fprintf('tmp=%.6f\n',encode);
if(encode>=orignal(1)& encode<orignal(2))
decode(i)='0';
t=1;
elseif(encode>=orignal(2)& encode<orignal(3))
decode(i)='1';
t=2;
end
encode=(encode-orignal(t));
encode=encode/pr(t);
end
decode
參考:
算術編碼的原理和MATLAB實現:http://blog.sina.com.cn/s/blog_4a8f0cbc01000b6e.html
行程編碼和算術編碼:https://www.cnblogs.com/pulas/archive/2012/02/22/2363314.html
圖像壓縮——算術編碼:http://blog.csdn.net/u010798503/article/details/53291743