導航:首頁 > 文件處理 > 哈夫曼編碼壓縮比

哈夫曼編碼壓縮比

發布時間:2025-03-20 13:42:22

『壹』 哈夫曼編碼進行圖像壓縮

% 演示圖象的哈夫曼編解碼過程
% chenyong 2009.04.20

clear all;
close all;
clc;
Dimens = 256; % 矩陣維數,假設矩陣為方陣即256*256
src_size = Dimens^2; % 矩陣元素的個數
gray_level = 9; % 灰度級

src = randn(Dimens); %產生模擬圖像矩陣,滿足正態分布,零均值,方差為1
%src = randint(Dimens,Dimens,gray_level); % 產生隨機圖像矩陣,灰度值為0~63,滿足均勻分布
src_one = reshape(src,1,src_size);
src_max = max(src_one);
src_min = min(src_one);
quan = linspace(src_min,src_max,gray_level); % 產生均勻量化區間
src_d = []; % 數字矩陣
for row = 1:Dimens % 逐點量化
for vol = 1:Dimens
diff = abs(src(row,vol)-quan);
[min_diff,min_index] = min(diff);
quan_gray = min_index -1;
src_d(row,vol) = quan_gray;
end
end

%將數字圖像矩陣還原成模擬矩陣
src_a = [];
quan_space = quan(2)-quan(1);
for row = 1:Dimens
for vol = 1:Dimens
src_a(row,vol) = src_d(row,vol) * quan_space + src_min;
end
end

% prob數組保存圖像中各灰度出現的概率
prob = [];
for src_value=0:(gray_level-1)
index = find(src_d==src_value);
i = src_value + 1;
prob(i) = length(index)/src_size;
end

% 畫出直方圖
% stem(0:gray_level-1,prob);
% xlabel('灰度值');
% ylabel('概率');
% title('灰度直方圖');

% huffman編碼
p = prob;
n=length(p);
q=p;
m=zeros(n-1,n);
for i=1:n-1
[q,l]=sort(q);
m(i,:)=[l(1:n-i+1),zeros(1,i-1)];
q=[q(1)+q(2),q(3:n),1];
end
bre=zeros(n-1,n);
bre(n-1,1)=0+j; %虛部表示當前的二進制數的位數,以下類似
bre(n-1,2)=1+j;
for time=1:n-2
loc_1 = find(real(m(n-time,:))==1);
prebit = bre(n-time,loc_1);
bre(n-time-1,1) = (real(prebit)*2 + 0) + j*(imag(prebit)+1);
bre(n-time-1,2) = (real(prebit)*2 + 1) + j*(imag(prebit)+1);

loc_not1 = find(real(m(n-time,:))>1);
bre(n-time-1,3:3+time-1) = bre(n-time,loc_not1);
end
[m1,index] = sort(m(1,:));
code = bre(1,index);
code_data = real(code);
code_bits = imag(code);
disp(['gray level',' ', 'huffman code']);
for i = 1:length(code)
disp([num2str(i-1),' ' ,num2str(dec2bin(code_data(i)))]);
disp([num2str(i-1),' ' ,num2str(dec2bin(code_data(i),code_bits(i)))]);
end
code_binary = dec2bin(code_data);

%逐點編碼
out = [];
for row = 1:Dimens
for vol = 1:Dimens
now_gray = src_d(row,vol);
now_code = code_binary(now_gray+1,:);
now_bits = code_bits(now_gray+1);
now_code = now_code(end-now_bits+1:end);
out = [out, now_code];
end
end

%計算壓縮比
real_bitnum = length(out);
bitnum_no_huffman = src_size*nextpow2(gray_level);
comp_ratio =bitnum_no_huffman/real_bitnum;
Lavg = real_bitnum/src_size;
Hshannon = (-1)*prob*(log2(prob))';
disp(['Lavg = ',num2str(Lavg)]);
disp(['normal bit num = ',num2str(nextpow2(gray_level))]);
disp(['comp_ratio = ',num2str(comp_ratio)]);
disp(['Hshannon = ',num2str(Hshannon)]);

『貳』 已知6個符號的信源A={a1,a2,……a6},若其概率分布為P={0.30, 0.25, 0.25, 0.10}1、寫出Huffman編碼(要

1、寫出Huffman編碼

a6和a5組成n1節點,權重0.14

a4和n1組成n2節點,權重0.26

a3和a2組成n3節點,權重0.42

n2和a1組成n4節點,權重0.58

n3和n4組成n5節點,權重1,即為根節點

Huffman編碼:

a1: 11

a2: 01

a3: 00

a4: 100

a5: 1011

a6: 1010

2、Huffman編碼的平均編碼長度

2 * (0.32 + 0.25 + 0.17) + 3 * 0.12 + 4 * (0.09 + 0.05)

= 1.48 + 0.36 + 0.56

= 2.4

3、壓縮比

如果不用Huffman編碼,則6個符號需要3個二進制符號,編碼長度是3,所以壓縮比是3 / 2.4 =1.25

擴展內容

哈夫曼編碼(Huffman Coding)原理

設某信源產生有五種符號u1、u2、u3、u4和u5,對應概率P1=0.4,P2=0.1,P3=P4=0.2,P5=0.1。首先,將符號按照概率由大到小排隊,如圖所示。

編碼時,從最小概率的兩個符號開始,可選其中一個支路為0,另一支路為1。這里,我們選上支路為0,下支路為1。再將已編碼的兩支路的概率合並,並重新排隊。多次重復使用上述方法直至合並概率歸一時為止。

赫夫曼碼的碼字(各符號的代碼)是異前置碼字,即任一碼字不會是另一碼字的前面部分,這使各碼字可以連在一起傳送,中間不需另加隔離符號,只要傳送時不出錯,收端仍可分離各個碼字,不致混淆。

長遊程的主碼和基碼均用赫夫曼規則進行編碼,這稱為修正赫夫曼碼,其結果有表可查。該方法已廣泛應用於文件傳真機中。

『叄』 哈夫曼編碼的壓縮實現

壓縮代碼非常簡單,首先用ASCII值初始化511個哈夫曼節點:
CHuffmanNode nodes[511];
for(int nCount = 0; nCount < 256; nCount++)
nodes[nCount].byAscii = nCount;
其次,計算在輸入緩沖區數據中,每個ASCII碼出現的頻率:
for(nCount = 0; nCount < nSrcLen; nCount++)
nodes[pSrc[nCount]].nFrequency++;
然後,根據頻率進行排序:
qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare);
哈夫曼樹,獲取每個ASCII碼對應的位序列:
int nNodeCount = GetHuffmanTree(nodes); 構造哈夫曼樹非常簡單,將所有的節點放到一個隊列中,用一個節點替換兩個頻率最低的節點,新節點的頻率就是這兩個節點的頻率之和。這樣,新節點就是兩個被替換節點的父節點了。如此循環,直到隊列中只剩一個節點(樹根)。
// parent node
pNode = &nodes[nParentNode++];
// pop first child
pNode->pLeft = PopNode(pNodes, nBackNode--, false);
// pop second child
pNode->pRight = PopNode(pNodes, nBackNode--, true);
// adjust parent of the two poped nodes
pNode->pLeft->pParent = pNode->pRight->pParent = pNode;
// adjust parent frequency
pNode->nFrequency = pNode->pLeft->nFrequency + pNode->pRight->nFrequency; 有一個好的訣竅來避免使用任何隊列組件。ASCII碼只有256個,但實際分配了511個(CHuffmanNode nodes[511]),前255個記錄ASCII碼,而用後255個記錄哈夫曼樹中的父節點。並且在構造樹的時候只使用一個指針數組(ChuffmanNode *pNodes[256])來指向這些節點。同樣使用兩個變數來操作隊列索引(int nParentNode = nNodeCount;nBackNode = nNodeCount –1)。
接著,壓縮的最後一步是將每個ASCII編碼寫入輸出緩沖區中:
int nDesIndex = 0;
// loop to write codes
for(nCount = 0; nCount < nSrcLen; nCount++)
{
*(DWORD*)(pDesPtr+(nDesIndex>>3)) |=
nodes[pSrc[nCount]].dwCode << (nDesIndex&7);
nDesIndex += nodes[pSrc[nCount]].nCodeLength;
}
(nDesIndex>>3): >>3 以8位為界限右移後到達右邊位元組的前面
(nDesIndex&7): &7 得到最高位.
此外,在壓縮緩沖區中,必須保存哈夫曼樹的節點以及位序列,這樣才能在解壓縮時重新構造哈夫曼樹(只需保存ASCII值和對應的位序列)。 解壓縮比構造哈夫曼樹要簡單的多,將輸入緩沖區中的每個編碼用對應的ASCII碼逐個替換就可以了。只要記住,這里的輸入緩沖區是一個包含每個ASCII值的編碼的位流。因此,為了用ASCII值替換編碼,我們必須用位流搜索哈夫曼樹,直到發現一個葉節點,然後將它的ASCII值添加到輸出緩沖區中:
int nDesIndex = 0;
DWORD nCode;
while(nDesIndex < nDesLen)
{
nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3)))>>(nSrcIndex&7);
pNode = pRoot;
while(pNode->pLeft)
{
pNode = (nCode&1) ? pNode->pRight : pNode->pLeft;
nCode >>= 1;
nSrcIndex++;
}
pDes[nDesIndex++] = pNode->byAscii;
}

閱讀全文

與哈夫曼編碼壓縮比相關的資料

熱點內容
雲伺服器平台雲伺服器提供商排名 瀏覽:723
如何快速孵化程序員 瀏覽:722
背部脊骨中間壓縮性骨折 瀏覽:695
app怎麼運用 瀏覽:775
基於單片機的恆溫控制系統設計 瀏覽:291
民兵應急營幹部命令宣布大會 瀏覽:407
給我個伺服器地址 瀏覽:227
加法運算律和加法運演算法則 瀏覽:621
如何與國外伺服器連接 瀏覽:172
庫房管理系統源碼 瀏覽:59
安卓應用多為什麼會卡 瀏覽:10
php程序員工作職責 瀏覽:306
程序員可以轉行做運維嗎 瀏覽:323
如何檢測到伺服器埠是否通 瀏覽:851
linuxsed正則 瀏覽:109
linux安裝gz文件 瀏覽:357
linux如何卸載編譯的軟體 瀏覽:929
高三解壓活動視頻 瀏覽:780
如何把伺服器卡爆 瀏覽:949
餓了么java程序員 瀏覽:960