基于matlab的图像huffman编码研究文档格式.docx
《基于matlab的图像huffman编码研究文档格式.docx》由会员分享,可在线阅读,更多相关《基于matlab的图像huffman编码研究文档格式.docx(9页珍藏版)》请在冰豆网上搜索。
所以,对图像数据压缩显得非常重要。
1.2图像数据压缩的原理
对数字图像压缩主要运用两个基本原理:
一是图像的相关性。
在图像同一相邻像素之间,活动图像的相邻帧的对应像素之间往往存在很强的相关性,去除或减少这些相关性,也就除去或减少图像信息中的冗余度,继而实现对数字图像的压缩。
二是人的视觉心理特征,人的视觉对于边缘急剧变化不敏感,对颜色分辨力弱,利用这些特征在相应部分降低编码精度而使人从视觉上感觉不到图像质量的下降,从而达到对数字图像压缩的目的。
1.3Huffman编码
Huffman编码是一种编码方式,是一种用于无损数据压缩的熵编码算法。
它是Huffman在1952年根据Shannon在1948年和Fano在1949年阐述的这种编码思想下提出的一种不定长编码的方法,有时也称之为最佳编码。
依据信源数据中各信号出现的频率分配不同长度的编码。
其基本思想是在编码过程中,对出现频率越高的值,分配越短的编码长度,相应地对出现频率越低的值则分配较长的编码长度,完全依据字符出现概率来构造异字头的平均长度最短的码字。
哈夫曼编码方法的实质是针对统计结果对字符本身重新编码,而不是对重复字符或重复子串编码,得到的单位像素的比特数最接近图像的实际熵值。
2.设计任务
2.1设计任务
研究实现灰度图像的Huffman编码和解码恢复。
2.2设计目的
(1)了解Huffman编码的基本原理及其特点;
(2)理解并熟练对图像进行哈夫曼编码的算法;
(3)学习和熟悉MATLAB图像处理工具箱;
(4)熟悉和掌握MATLAB
程序设计方法;
2.3设计要求
现灰度图像的Huffman编码和解码恢复图像;
处理结果要求最终图像显示,且计算图像的信息熵,平均码字长度,编码效率,压缩比。
3.总体设计方案
3.1系统运行环境
Windows8.1/10系统
3.2编程软件平台
MATLABR2013a/R2014a
3.3Huffman编码算法原理
哈夫曼编码的基本方法是先对图像数据扫描一遍,计算出各种像素出现的概率,按概率的大小指定不同长度的唯一码字,由此得到一张该图像的哈夫曼码表。
编码后的图像数据记录的是每个像素的码字,而码字与实际像素值的对应关系记录在码表中。
(1)计算信源符号出现的概率;
(2)将信源符号按其出现的概率,由小到大顺序排列,并从左至右排列为叶节点[1];
(3)将两个概率最小的顶层节点进行组合相加,组成一个父节点,并在到左右子节点的两条连线上分别标记0和1;
(4)重复上一步骤,直到得到根节点,形成一颗二叉树;
(5)从根节点开始到相应于每个符号的叶节点的0/1串,就是该符号的二进制哈夫曼编码。
3.4Huffman编码算法的特点
(1)编出来的码都是异字头码,保证了码的唯一可译性。
(2)由于编码长度可变。
因此译码时间较长,使得哈夫曼编码的压缩与还原相当费时。
(3)编码长度不统一,硬件实现有难度。
(4)对不同信源的编码效率不同,当信源的符号概率为2的负幂次方时,达到100%的编码效率;
若信源符号的概率相等,则编码效率最低。
(5)由于符号按概率大小排列既可以从右到左也可以从左到右,即0与1的指定是任意的,故最后的编码结果可能不唯一,但仅仅是分配的代码不同,其平均码长是一样的,故不影响编码效率与数据压缩性能。
3.5算法流程图设计
3.5.1主流程图
开始
加载图像,并将其灰度化
将灰度图像转换成无符号的8位整数矩阵
调用Huffman编码程序进行压缩
调用Huffman解码程序进行解码
显示原始图像、灰度图像
和经编码解码后的图像
结束
显示平均码长、压缩比、信息熵及编码效率
3.5.2编码流程图
计算各符号(灰度值)出现概率
按照概率从小到大排序
生成Huffman树
得到二进制哈夫曼编码码字
对图像(图像矩阵)进行编码
计算编码参数
(平均码长、信息熵等)
计算二进制码字对应的十进制数,并存入矩阵中,得到码字与灰度值的对应关系表,即码表
3.5.3解码流程图
读取压缩矩阵,并存入行向量中
解码后的矩阵按图像矩阵尺寸重排,得到解码矩阵
解码,按位读取行向量中的编码
并进行相应灰度值匹配
3.6组员任务分工
王振宇:
编写主要程序,编码解码函数程序及相关子程序,修改报告及演示文稿。
龙航:
编写部分主程序及部分函数程序,撰写报告。
王一鸣:
编写部分程序,进行程序调试完善,制作演示文稿。
4.程序实现
4.1函数主程序
clc;
clear;
closeall;
X=imread('
peppers.JPG'
);
%图像灰度化
R=X(:
:
1);
G=X(:
2);
B=X(:
3);
Y=0.299*R+0.587*G+0.114*B;
subplot(1,3,1);
imshow(X);
title('
原始图像'
data=uint8(Y);
[zipped,info]=huffencode(data);
%调用Huffman编码程序进行压缩
unzipped=huffdecode(zipped,info);
%调用Huffman编码程序进行解码
%显示原始图像,灰度化图像和经编码解码后的图像
subplot(1,3,2);
imshow(data);
灰度化图像'
subplot(1,3,3);
imshow(unzipped);
Huffman编码并解码后图像'
disp('
平均码长'
L=info.avalen
压缩比'
CR=info.ratio
信息熵'
H=info.h
编码效率'
CE=info.ce
4.2编码程序
%huffencode函数对输入矩阵vector进行Huffman编码,返回编码后的数据及相关信息
function[zipped,info]=huffencode(vector)
if~isa(vector,'
uint8'
)%确定输入矩阵是uint8格式
error('
inputargumentmustbeauint8vector'
end
[m,n]=size(vector);
%求输入矩阵的行列数
vector=vector(:
)'
;
%将矩阵按列转换成一列后转至,成为一个行向量(其中存放灰度值)
f=frequency(vector);
%计算各符号出现的概率
symbols=find(f~=0);
%返回概率矩阵中非零元素的位置向量,作为符号向量
f=f(symbols);
%非零概率位置上的概率值组成非零概率行向量
[f,sortindex]=sort(f);
%将符号按照出现的概率从小到大排序,并保留非零概率向量位置索引
fs=f;
symbols=symbols(sortindex);
%读出原位置向量中的值(即概率向量中的位置),得到按概率排序后的符号向量
len=length(symbols);
%读取位置向量的长度
symbols_index=num2cell(1:
len);
%生成从1开始以1递增,1行len列的细胞型矩阵
codeword_tmp=cell(len,1);
%创建一个len行1列的细胞型变量用于存放码字
whilelength(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:
%合并已编码的符号索引
[f,sortindex]=sort(f);
%将新的概率向量按照概率从小到大排序
symbols_index=symbols_index(sortindex);
%得到新的索引表
codeword=cell(256,1);
codeword(symbols)=codeword_tmp;
%各符号二进制码字按原符号位存入细胞型矩阵
len=0;
fori=1:
length(symbols)%得到各符号码长矩阵
wordlen(i)=length(codeword_tmp{i});
avawordlen=fs*wordlen'
%计算平均码长
Hlog=log2(fs)'
H=-(fs*Hlog);
%计算信息熵
forindex=1:
length(vector)%得到整个图像各点灰度值转化为二进制码字后的总比特数
len=len+length(codeword{double(vector(index))+1});
string=repmat(uint8(0),1,len);
%创建元素数与总比特数一致的行向量
pointer=1;
%定义指针变量
length(vector)%对输入图像进行编码
code=codeword{double(vector(index))+1};
%对应符号的二进制码字给code
len=length(code);
%读取码字长度
string(pointer+(0:
len-1))=code;
%将二进制码字存入行向量中
pointer=pointer+len;
%指针移移位
%将二进制编码按照每8位生成一个新字符。
len=length(string);
zp=8-mod(len,8);
ifzp>
string=[stringuint8(zeros(1,zp))];
%不足8位的在后补零
codeword=codeword(symbols);
%码字按符号概率放入列向量中
codelen=zeros(size(codeword));
%创建与列向量元素数相同的列向量
weights=2.^(0:
23);