huffman编码及截断huffman编码解码实习报告word版.docx
- 文档编号:24476065
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:20
- 大小:533.85KB
huffman编码及截断huffman编码解码实习报告word版.docx
《huffman编码及截断huffman编码解码实习报告word版.docx》由会员分享,可在线阅读,更多相关《huffman编码及截断huffman编码解码实习报告word版.docx(20页珍藏版)》请在冰豆网上搜索。
huffman编码及截断huffman编码解码实习报告word版
题目:
编码与解码
1、要求
对下图实施截断哈夫曼编码和解码,计算图象熵,平均码长和冗余度;
3
3
4
4
4
4
5
2
4
1
1
2
2
1
5
4
4
3
4
4
4
4
5
2
4
5
2
5
0
3
1
2
1
5
0
3
3
5
6
4
2
3
1
1
2
2
1
2
0
3
6
5
5
7
2
0
3
1
2
2
1
5
0
3
2、理论
Ⅰ信息量和熵
信息量的定义:
对应每个符号的
其中,
指
出现的概率。
信源的定义:
信源指能够产生信息的事情。
在数学上信源是一概率场,若信源X可能产生的信源是
,这些信息出现的概率分别是
,则该信源可能表示为
由于
是一个随机变量,因此也可以定义信源的信息量的统计平均为熵[entropy]
在编码应用中,熵表示信源中消息的平均信息量,在不考虑消息间的相关性时,是无失真代码平均长度比特数的下限。
Ⅱ编码过程
编码器是用符号集A中的符号构成输出代码,并建立输出信号单元与输出代码的对应关系,如下图所示
根据Shannon无干扰信息保持编码定理,若对原始图数据的信息进行信源的无失真图像编码,则压缩后的平均码率
存在一个下限,这个下限是信源信息熵H。
理论上最佳信息保持编码的平均码长可以无限接近信源信息熵H。
若原始图像平均码长为
,则
为灰度级
对应的码长,
为灰度级
出现的概率。
那么
总是大于或等于图像的熵H。
因此可定义冗余度
编码效率
定义为
当经过编码压缩后图像信息的冗余度r已接近于零,或编码效率已接近于1时,那么平均码长已接近其下限,这类编码方法称为高效编码
ⅢHuffman编码
Huffman编码是由D.A.Huffman在1952年提出的一种编码方法。
这种编码方法根据源数据各信号发生的概率进行编码。
在源数据中出现概率越大的信号,分配的码字越短;出现概率越小的信号,其码字越长,从而达到用尽可能少的码表示源数据的目的。
它在变长编码方法中是最佳的。
Huffman编码的步骤如下:
设信源X有m个符号(消息)
(1)把信源X中的消息按概率从大到小的顺序排列;
(2)把最后两个出现概率最小的消息合并成一个消息,从而使信源的消息数减少,并同时再按信源符号(消息)出现的概率从大到小排列;
(3)重复上述2个步骤,直到信源最后为
(4)将被整合的消息分别赋予1和0,并对最后的两个消息也相应地赋予1和0.
通过以上步骤就可构成最优变长码(Huffman编码)
Ⅳ截断Huffman编码
(1)对最可能出现的M个符号进行Huffman编码
(2)对其他的码都用在一个合适的定长码前加一个前缀码来表示
3、算法设计
Ⅰ编码部分
由于我们最开始得到的image是一个
的矩阵,因此我们第一步需要做的是事情就是将矩阵中的字符进行概率分布计算,并得到概率分布矩阵,以进行下面的计算
特此编写pro=getpro(image)函数返回得到概率分布矩阵pro(其中pro为
阶矩阵,第一行为各字符概率值,第二行为相应各字符,
为所有字符种类的总个数)。
由Huffman编码要求
(1),得到的概率分布矩阵要按照从大到小得顺序来排列,所以需要编写pro=getsequence(pro)函数来得到顺序排列的概率分布矩阵。
由Huffman编码要求
(2),我们需要从pro(1,:
)中找到两个最小的概率值,所以需要编写找出两个最小值的函数[min1,min2]=getmin(tree),其中tree是在进行Huffman编码过程中产生的Huffman树(包含pro信息,具体下面介绍),并且在min1与min2中若两者值相等,则在pro中概率序号在前的概率值赋予min1,概率序号在后的概率值赋予min2,此函数主要部分如下:
fori=s;
if(tree(2,i) min2=min1; m2=m1; min1=i; m1=tree(2,i); elseif(tree(2,i) min2=i; m2=tree(2,i); end end 下面先介绍下tree,树在matlab中的构造,在matlab中用tree(MN,s1,s2,s3……)这个系统函数来构造二叉树。 声明一个tree(6,x)结构的树型结点,一个结点包括有6个变量存储单元。 其中tree(1,x)记录该结点的编号;tree(2,x)记录该结点的概率值;tree(3,x)记录该结点的父结点编号;tree(4,x)记录该结点是左结点还是右结点(其中左结点为“0”,右结点为“1”);tree(5,x)记录该结点是否为根结点标志(该结点为根结点记为“1”,否则决为“0”)。 tree(6,x)记录该结点的字符,x的个数为pro中字符的个数,其余值人为赋零。 由截断Huffman编码要求 (2),我们需要对字符进行一个定长码的顺序编码,所以需要编写函数SequenceTree=Sequence(pro)来得到一棵顺序编码的二叉树,其中pro为截断Huffman编码要求中剩余的字符组成的新pro概率分布矩阵(按概率值先大后小的顺序排序) n0=size(pro,2); n1=ceil(log2(n0)); n=2^n1; tree=ones(6,2*n-1); tree(1,: )=1: (2*n-1); tree(5,(n+1): end)=0; tree(2,1: n)=pro(1,: ); tree(6,1: n)=pro(2,: ); tree(6,n+1: end)=0; 如上为在进行顺序编码前构造的基本树 fori=1: 2: (2*n-3); location=(i+1)/2+n; tree(2,location)=tree(2,i)+tree(2,i+1); tree(5,location)=1; tree(3,i)=location;tree(3,i+1)=location; tree(4,i)=0;tree(4,i+1)=1; tree(5,i)=0; tree(5,i+1)=0; end SequenceTree=tree; 通过以上步骤可以返回得到一棵顺序编码完成的二叉树SequenceTree。 由截断Huffman编码要求 (1),需要对M个符号进行Huffman编码,因此编写其编码部分,主要代码如下 fori=(n+1): (2*n-1); [mi1,mi2]=getmin(tree); tree(2,i)=tree(2,mi1)+tree(2,mi2); tree(5,i)=1; tree(3,mi1)=i;tree(3,mi2)=i; tree(4,mi1)=1;tree(4,mi2)=0; tree(5,mi1)=0; tree(5,mi2)=0; end T_HuffmanTree=tree; 通过以上两步,得到了两棵二叉树T_HuffmanTree和T_SequenceTree 接下来进行对image的编码部分 依次获取image中的每个字符,然后历遍T_HuffmanTree和T_SequenceTree(如果满足进入条件)可以得到最后的T_HuffmanCode 主要代码如下: m=find(T_SequenceTree(6,1: n2)==k); while(T_SequenceTree(5,m (1))~=1)%判断是否已历遍到根节点 Code(CodeNumber)=T_SequenceTree(4,m (1)); CodeNumber=CodeNumber+1; m=T_SequenceTree(3,m);%指向父节点 end k=-1;%指向标示位 如上为逆历遍T_SequenceTree的过程。 m=find(T_HuffmanTree(6,1: n)==k); while(T_HuffmanTree(5,m)~=1)%判断是否已历遍到根节点Code(CodeNumber)=T_HuffmanTree(4,m); CodeNumber=CodeNumber+1; m=T_HuffmanTree(3,m);%指向父节点 end 如上为逆历遍T_HuffmanTree的过程。 forz=LastPoint: SumCode;%将n个符号的编码组合到一起 T_HuffmanCode(z)=Code(CodeNumber); CodeNumber=CodeNumber-1; end 如上为历遍之后再将暂时储存在Code(CodeNumber)中的数据传至T_HuffmanCode中输出。 循环完毕后即得到编码完成的T_HuffmanCode。 根据题目要求我们还需计算图象熵,平均码长和冗余度 求熵部分如下 Entropy=0; forj=1: n1; Entropy=Entropy-pro(1,j)*log2(pro(1,j)); End 计算平均码长前需要先得到每个字符的码长,因此需要先编写得到每个字符码长的数组(代码略,详见第四部分: 编程代码),接着由下得到平均码长 AverageCodeLength=sum(CodeLength.*pro(1,: )) 再根据冗余度的计算公式可得 Redundancy=AverageCodeLength/Entropy-1; Ⅱ解码部分 解码部分需要的元素有T_HuffmanTree、T_SequenceTree、T_HuffmanCode以及原始图像的宽高Information.high,Information.wide。 解码时是依次取遍T_HuffmanCode中的每个值,从T_HuffmanCode中最高的父节点开始,历遍T_HuffmanTree和T_SequenceTree(当历遍T_HuffmanTree得到根节点为标示符-1时进入) 如下先为T_SequenceTree的扫描部分 temp2=find(T_SequenceTree(3,: )==temp1); if(T_SequenceTree(4,temp2 (1))==i) temp1=temp2 (1); else temp1=temp2 (2); end start1=start1+1; if(step==N) flag=1; else step=step+1; end if(temp1<=nn1)%跳出扫面 break; end 接下为T_HuffmanTree的扫描部分 temp2=find(T_HuffmanTree(3,: )==temp1); if(T_HuffmanTree(4,temp2 (1))==i) temp1=temp2 (1); else temp1=temp2 (2); end start1=start1+1; if(step==N) flag=1; else step=step+1; end if(temp1==n2)%扫描标记T_SequenceTree flag_s=1; temp1=nn; elseif(temp1<=n1)%跳出扫描 break; end 由以上两部分扫描就能得到一个返回值,再将返回值赋予数组image中 if(flag_s==0)%选择输出值位置 iimage(j)=T_HuffmanTree(6,temp1); else iimage(j)=T_SequenceTree(6,temp1); end 当然最后需要根据原图像宽高将一维的iimage数组转换成二维的数组 image=reshape(iimage,Information.high,Information.wide); 由此截断Huffman解码部分完成,得到返回值image。 4、编程代码 Ⅰ截断Huffman编码 function[T_HuffmanTree,T_SequenceTree,T_HuffmanCode,T_Information,T_Result]=TruncationHuffman(image) [m,n]=size(image); T_Information.high=m; T_Information.wide=n; length=m*n; image=reshape(image,1,length); pro=getpro(image); pro=getsequence(pro); n1=size(pro,2); temp=sum(pro(1,ceil(n1/2)+1: end)); pro1(: 1: ceil(n1/2)+1)=pro(: 1: ceil(n1/2)+1); pro1(1,ceil(n1/2)+1)=temp; pro1(2,ceil(n1/2)+1)=-1; pro1=getsequence(pro1); n=size(pro1,2); %///////////////Huffman编码//////////// tree=ones(6,2*n-1); tree(1,: )=1: (2*n-1); tree(5,(n+1): end)=0; tree(2,1: n)=pro1(1,: ); tree(6,1: n)=pro1(2,: ); tree(6,n+1: end)=0; fori=(n+1): (2*n-1); [mi1,mi2]=getmin(tree); tree(2,i)=tree(2,mi1)+tree(2,mi2); tree(5,i)=1; tree(3,mi1)=i;tree(3,mi2)=i; tree(4,mi1)=1;tree(4,mi2)=0; tree(5,mi1)=0; tree(5,mi2)=0; end T_HuffmanTree=tree; %///////////////顺序编码///////////// pro2=pro(: ceil(n1/2)+1: end); [T_SequenceTree]=Sequence(pro2); %///////////////编码部分///////////// T_HuffmanCode=1; Code=[]; SumCode=0; LastPoint=1; n2=size(T_SequenceTree,2); intz; fork=image;%循环完成n个符号的编码 flag_loc=0; loc=find(pro(2,: )==k); if(loc>ceil(n1/2)) flag_loc=1; end CodeNumber=1; if(flag_loc==1) m=find(T_SequenceTree(6,1: n2)==k); while(T_SequenceTree(5,m (1))~=1)%判断是否已历遍到根节点 Code(CodeNumber)=T_SequenceTree(4,m (1)); CodeNumber=CodeNumber+1; m=T_SequenceTree(3,m);%指向父节点 end k=-1; end m=find(T_HuffmanTree(6,1: n)==k); while(T_HuffmanTree(5,m)~=1)%判断是否已历遍到根节点 Code(CodeNumber)=T_HuffmanTree(4,m); CodeNumber=CodeNumber+1; m=T_HuffmanTree(3,m);%指向父节点 end CodeNumber=CodeNumber-1; SumCode=SumCode+CodeNumber;%累加计算编码长度 forz=LastPoint: SumCode;%将n个符号的编码组合到一起 T_HuffmanCode(z)=Code(CodeNumber); CodeNumber=CodeNumber-1; end LastPoint=SumCode+1; end %///////////////求熵///////////// Entropy=0; forj=1: n1; Entropy=Entropy-pro(1,j)*log2(pro(1,j)); end %///////////////计算单位码长///////////// CodeLength=zeros(1,n1+1); nn1=size(pro2,2); nn=ceil(log2(nn1)); loc=find(pro1(2,: )==-1); fork=1: n;%循环完成n个符号的编码 m=k; if(m==loc) CodeLength(1,k)=CodeLength(1,k)+nn; end while(T_HuffmanTree(5,m)~=1)%判断是否已历遍到根节点 m=T_HuffmanTree(3,m);%指向父节点 CodeLength(1,k)=CodeLength(1,k)+1; end end temp=CodeLength(loc); CodeLength(loc)=[]; CodeLength(ceil(n1/2)+1: end)=temp; T_Result.CodeLength=CodeLength; T_Result.SumCode=SumCode; T_Result.Entropy=Entropy; T_Result.AverageCodeLength=sum(CodeLength.*pro(1,: )); T_Result.Redundancy=T_Result.AverageCodeLength/T_Result.Entropy-1 Ⅱ截断Huffman解码 functionimage=unTruncationHuffman(T_HuffmanTree,T_SequenceTree,T_HuffmanCode,Information) n=size(T_HuffmanTree,2);%T_HuffmanTree的长度 n1=(n+1)/2;%pro1的长度 nn=size(T_SequenceTree,2);%T_SequenceTree的长度 nn1=(nn+1)/2;%pro2的长度 n2=find(T_HuffmanTree(6,: )==-1);%T_HuffmanTree中T_SequenceTree起始位标示位置 flag=0;%变长码扫描结束起始位 flag_s=0;%T_SequenceTree扫描起始位 start=1;%T_HuffmanCode扫描起始位 start1=0;%每个变长码长度 step=1;%扫描过的T_HuffmanCode长度 j=0;%输出字符的位置 N=size(T_HuffmanCode,2);%总码长 while(flag==0) start=start+start1; temp1=n; start1=0; flag_s=0; fori=T_HuffmanCode(1,start: N) if(flag_s==1)%扫描进入T_SequenceTree temp2=find(T_SequenceTree(3,: )==temp1); if(T_SequenceTree(4,temp2 (1))==i) temp1=temp2 (1); else temp1=temp2 (2); end start1=start1+1; if(step==N) flag=1; else step=step+1; end if(temp1<=nn1)%扫描跳出 break; end else%扫描进入T_HuffmanTree temp2=find(T_HuffmanTree(3,: )==temp1); if(T_HuffmanTree(4,temp2 (1))==i) temp1=temp2 (1); else temp1=temp2 (2); end start1=start1+1; if(step==N) flag=1; else step=step+1; end if(temp1==n2)%标记扫描T_SequenceTree flag_s=1; temp1=nn; elseif(temp1<=n1)%跳出扫描 break; end end end j=j+1; if(flag_s==0)%选择输出值位置 iimage(j)=T_HuffmanTree(6,temp1); else iimage(j)=T_SequenceTree(6,temp1); end end image=reshape(iimage,Information.high,Information.wide); Ⅲ其他子程序代码 pro=getpro(image)%得到概率分布矩阵 [min1,min2]=getmin(tree)%得到最小两个概率值 pro=getsequence(proo)%按大小顺序重新排列概率分布矩阵 [SequenceTree]=Sequence(pro)%顺序编码函数 这四个子程序由于篇幅原因不在此处完整贴出,详见附文 5、程序运行结果及对比分析 在CommandWindow中输入 >>[T_HuffmanTree,T_SequenceTree,T_HuffmanCode,T_Information,T_Result]=TruncationHuffman(image) (其中image为题目要求先前输入的矩阵) 在T_Information中包含image的宽与高 在T_Result中包含的数据有字符码长、总码长、图像的熵、平均码长、冗余度 得到如下图(一次截图不完全,分开截图): 图1.1Truncation
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- huffman 编码 截断 解码 实习 报告 word