多媒体技术与应用实验之Huffman编解码matlab实现

202 阅读5分钟

多媒体技术与应用实验之Huffman编解码matlab实现
主函数:

clc;
clear;
close all ;
X=imread( 'lena.bmp' ); %图像灰度化
data=uint8(X); 
[zipped,info]=huffencode(data); %调用 Huffman 编码程序进行压缩 
unzipped=huffdecode(zipped,info); %调用 Huffman 编码程序进行解码

subplot(121);imshow(data);title( ' 原始图像 ' ); 
subplot(122);imshow(unzipped);title( 'Huffman 编码并解码后图像 ' ); 
disp( ' 平均码长 ' );L=info.avalen 
disp( ' 压缩比 ' );CR=info.ratio 
disp( ' 信息熵 ' );H=info.h 
disp( ' 编码效率 ' );CE=info.ce
disp( ' 编码 ' );huffcode = info.huffcodes

编码函数:

function [zipped,info]=huffencode(vector) 

[m,n]=size(vector); %求输入矩阵的行列数 
vector=vector(:)'; %将矩阵按列转换成一列后转至,成为一个行向量 ( 其中存放灰度值 ) 
f=frequency(vector); %0-255灰度概率,值为概率
symbols=find(f~=0); %概率不为零的灰度值,1-215 值为灰度值
f=f(symbols); %筛选后概率向量,0-2550概率
[f,sortindex]=sort(f); %排序升序,sortindex筛选后的序号
fs=f; 
symbols=symbols(sortindex); %灰度值按概率排序
len=length(symbols); %读取位置向量的长度 

symbols_index=num2cell(1:len); %生成异质矩阵
codeword_tmp=cell(len,1); %异质变量 存放码字
while length(f)>1     % Huffman 树,得二进制码表
    index1=symbols_index{1}; 
    index2=symbols_index{2};    
    codeword_tmp(index1)=addnode(codeword_tmp(index1),uint8(0)); %添加节点且该分支按 0 标记 
    codeword_tmp(index2)=addnode(codeword_tmp(index2),uint8(1)); %添加节点且该分支按 1 标记 
    f=[sum(f(1:2)) f(3:end)]; %求出两个最小概率之和,列出其他概率,组成一个新的行向量 
    symbols_index=[{[index1,index2]} symbols_index(3:end)]; %合并已编码的符号索引 
    [f,sortindex]=sort(f); %将新的概率向量按照概率从小到大排序   
    symbols_index=symbols_index(sortindex); %得到新的索引表
end 

codeword=cell(256,1); 
codeword(symbols)=codeword_tmp; %各符号二进制码字按原符号位存入细胞型矩阵
len=0; 
for i=1:length(symbols) %得到各符号码长矩阵
    wordlen(i)=length(codeword_tmp{i}); 
end
avawordlen=fs*wordlen'; %计算平均码长
Hlog=log2(fs)'; 
H=-(fs*Hlog); %计算信息熵 

for index=1:length(vector) %得到整个图像各点灰度值转化为二进制码字后的总比特数
    len=len+length(codeword{double(vector(index))+1}); 
end

string=repmat(uint8(0),1,len); %创建元素数与总比特数一致的行向量 
pointer=1; %定义指针变量 
for index=1:length(vector)  % 对输入图像进行编码 
    code=codeword{double(vector(index))+1}; %对应符号的二进制码字给 
    len=length(code); %读取码字长度 
    string(pointer+(0:len-1))=code; %将二进制码字存入行向量中 
    pointer=pointer+len; %指针移移位
end
% 将二进制编码按照每 8 位生成一个新字符。
len=length(string); 
zp=8-mod(len,8); 
if zp>0     
    string=[string uint8(zeros(1,zp))]; %不足 8 位的在后补零
end

codeword=codeword(symbols); %码字按符号概率放入列向量中 
codelen=zeros(size(codeword)); %创建与列向量元素数相同的列向量

%将二进制转化为十进制
weights=2.^(0:23); 
for index=1:length(codeword)    
    len=length(codeword{index}); %读二进制码字长度
    if len>0         
        code=sum(weights(codeword{index}==1)); %计算二进制码字对应的十进制数 
        code=bitset(code,len+1); %将码字最高位的上一位置 1 
        codeword{index}=code;         
        codelen(index)=len; %码字长度存入列向量中
   end 
end

codeword=[codeword{:}]; %转化为行向量



%计算压缩后的向量
cols=length(string)/8; 
string=reshape(string,8,cols); 
weights=2.^(0:7); 
zipped=uint8(weights*double(string)); %码表存储到一个稀疏矩阵



huffcodes=sparse(1,1);

for index=1:nnz(codeword) 
    huffcodes(codeword(index),1)=symbols(index); 
end
%返回编码参数
% info.zeropad=zp; %添加的比特数 
info.huffcodes=huffcodes; %码字表 
info.length=length(vector); %灰度化图像矩阵长度
info.rows=m; %灰度图像行数
info.cols=n; %灰度图像列数
info.avalen=avawordlen; %平均码长 
info.ratio=8/avawordlen; %压缩比 
info.h=H; %信息熵 
info.ce=H/avawordlen; %编码效率 
end

解码函数:

%huffdecode 函数对输入矩阵 vector 进行 Huffman 编码,返回解压后的图像数据
function vector=huffdecode(zipped,info) 
len=length(zipped); %读取压缩矩阵长度 
string=repmat(uint8(0),1,len*8); %创建全为 0的行向量
bitindex=(1:8); 
for index=1:len %还原成01串
    string(bitindex+8.*(index-1))=uint8(bitget(zipped(index),bitindex)); % 读取压缩矩阵中的值并转化为 8位二进制按顺序放入 string 矩阵中
end 
len=length(string); 
%开始解码
vector=repmat(uint8(0),1,info.length); %创建与灰度化图像行向量等长的行向量
vectorindex=1; 
codeindex=1; 
code=0; 
for index=1:len-1     
    code=bitset(code,codeindex,string(index)); %按位读编码码字 
    codeindex=codeindex+1; %移位 
    byte=decode(bitset(code,codeindex),info); %进行码字匹配,读取相对应符号   
    if byte>0 %若读取到对应符号则进行下面操作,无符号继续按位读取码字 
        vector(vectorindex)=byte-1; %将符号表示的灰度值放入容器矩阵中 
        codeindex=1; %重置 
        code=0; %重置 
        vectorindex=vectorindex+1; %容器指针移位
    end 
end
vector=reshape(vector,info.rows,info.cols); %将构成的灰度矩阵按原图矩阵行列 数重构,解码完成
end

检测频率概率:

%函数 frequency 计算各符号出现的概率
function f=frequency(vector) 
f=zeros(1,256); %设置一个 256 个元素都为 0 的行向量 
len=length(vector); %读取输入矩阵元素个数
for index=0:1:255    
    f(index+1)=sum(vector==index); %统计输入图像矩阵中 0 至 255 各值出现的个数, 存入一个行向量中
end
f=f./len; %求各符号值出现的概率
end

decode:

%函数 decode 返回码字对应的符号 
function byte=decode(code,info)
byte=info.huffcodes(code); 
end

addnode:

%函数 addnode 添加节点确定符号码字
function codeword_new=addnode(codeword_old,item) 
codeword_new=cell(size(codeword_old)); %前一步码字维数作为新细胞型变量的维数, 用于存放码字 
for index=1:length(codeword_old) %确定符号对应码字
    codeword_new{index}=[item codeword_old{index}]; 
end
end