实验一 无失真信源压缩编码
此文系后续整理,懒得copy,对应的方法可以根据需要可以直接下载代码,附件:
https://download.csdn.net/download/weixin_40744915/10296130
https://download.csdn.net/download/weixin_40744915/10296133
https://download.csdn.net/download/weixin_40744915/10296135
https://download.csdn.net/download/weixin_40744915/10296154
目录
一、实验目的及要求... 1
二、任务分析及方案选择... 1
(一)Huffman编码... 1
(二)游程编码... 1
(三)算术编码... 2
(四)字典码... 3
三、实验原理及过程... 5
(一)Huffman编码实现信源无失真压缩... 5
(二)游程编码与Huffman编码结合实现信源无失真压缩... 13
(三)字典码实现信源无失真压缩... 18
四、实验结果分析与思考... 20
(一)Huffman编码实现信源无失真压缩... 20
(二)游程编码与Huffman编码结合实现信源无失真压缩... 23
(三)字典码实现信源无失真压缩... 24
五、实验小结... 27
一、实验目的及要求
1、对文本信源,寻求最佳压缩方案,现完整的无失真压缩的编译码算法,完成对文本文件的压缩及解压。
2、构建性能分析模块,实现对信源熵的统计、压缩后的传输率(bits/symbol),以及恢复文本的完整情况进行分析。
二、任务分析及方案选择
香农第一定理从理论上给出了进行无失真信源压缩的理论极值,并论证了理想最佳信源编码的存在性,也就是说,总能找到某种合适的编码方法使编码后信源的信息传输率任意逼近信源的信息熵而不存在任何失真,这样的无失真信源编码在数据压缩技术中又称为熵编码。典型的代表有霍夫曼编码、游程编码、算术编码和字典码,霍夫曼编码主要适用于多元独立的信源,游程编码和算术编码主要使用与二元信源及具有一定相关性的有记忆信源,字典码针对信源的统计特性未知时有较好的性能。本次实验给定的是一个大小较小、无记忆文本文件,所以Huffman编码是应该一个比较合适的方案,下面具体进行原理分析与比较:
(一)Huffman编码
Huffman编码是一种即时码,二元Huffman编码步骤如下:
(1)将q个信源符号按递减概率排列起来,设
(2)用0和1码符号分别分配给概率最小的两个信源符号,并将这两个概率最小的信源符号合并成一个新符号,并用这两个最小概率之和作为新符号的概率,从而得打只包含个符号的新信源,作为原信源的缩减信源;
(3)把缩减信源的符号仍按照概率大小递减排列,再将其最后两个概率最小的符号合并成一个新符号,依次递推,直至缩减信源最后只剩下两个符号为止。将这最后两个符号分别用0和1码表示,最后他们俩的概率之和为1。然后从最后一级缩减信源开始,依照编码路径从后向前返回,就得出各个信源符号所对应的码符号序列,即对应的码字。
但Huffman编码得到的码并非唯一的,因为每次对缩减信源最后两个概率最小的符号,用0还是1表示可以是任意的,所以可能得到码长相同但码字不同的码;另外当缩减信源中缩减合并后的符号的概率与其他信源符号相同时,概率次序也不一定,所以其Huffman编码并不唯一。但由于平均码长没变,所以有相同的编码效率。
后续将给出实验(一)中给出具体过程及步骤。
(二)游程编码
游程编码又称“运行长度编码”或“行程编码”,是一种统计编码,该编码属于无损压缩编码,是栅格数据压缩的重要编码方法。对于二元信源,其输出只有两个符号,‘0’或‘1’。连续出现‘1’符号或者连续出现‘0’符号的个数称为这一段的游程长度,这个游程长度是一个随机变量,可取值从1……无穷,且‘0’和‘1’游程一定是交替出现的。用自然数标记游程长度的这种映射是可逆的,无失真的,而且游程长度越长以及长游程频繁出现时压缩效率就会越高。
同样,由于通过游程的映射变换已经减弱了原来二元序列符号间的相关性,并把它变成了多元序列,这样可以在游程编码的基础上进行其他的变长编码方式,就能进一步压缩信源,提高通信效率。当然要首先测定‘0’游程长度和‘1’游程长度的概率分布,即以游程长度为元素,构造一个新的多元信源进行霍夫曼编码,得到不同游程长度映射的码字,就可以将游程序列变换成码字序列,使信源得到进一步压缩。若二元序列的概率特性已知,由于二元序列和映射所得的游程序列是一一对应的,就可以计算出游程序列的概率特性,根据信息熵的定义分别计算‘0’游程长度信源和‘1’游程长度信源的熵,以及平均游程长度,原信源的二元序列是由‘0’游程和‘1’游程交替出现而组成的,所以原二元序列的熵等于两个游程长度信源熵之和除以它们的平均游程长度之和,即游程变换后的信源信息熵没有变,当‘0’游程和‘1’游程的编码效率都很高时,采用游程编码的编码效率也很高。因此要想编码效率尽可能高,应该尽量提高熵值较大的游程的编码效率。
因此,在后续将给出游程编码和Huffman编码结合的无失真压缩编码,具体在实验(二)中给出具体过程及步骤。
(三)算术编码
虽然Huffman编码是最佳码,但是对于二元信源,必须对二元信源的N次扩展信源进行Huffman编码时,才能使得平均码长接近信源的熵,编码效率才高。必须要计算出所有N长信源序列的概率分布,并构造相应的完整的码树,所以较为复杂。算术编码可以无需计算出所有N长信源序列的概率分布及编出码表,可以直接对输入的信源符号序列进行编码输出,对于很长的信源符号序列来说是一个简单有效的编码方法。算术编码的基本原理是将编码的消息表示成实数0和1之间的一个间隔(Interval),消息越长,编码表示它的间隔就越小,表示这一间隔所需的二进制位就越多。
算术编码用到两个基本的参数:符号的概率和它的编码间隔。信源符号的概率决定压缩编码的效率,也决定编码过程中信源符号的间隔,而这些间隔包含在0到1之间。编码过程中的间隔决定了符号压缩后的输出。
给定事件序列的算术编码步骤如下:
(1)编码器在开始时将“当前间隔” [ L, H) 设置为[0,1)。
(2)对每一事件,编码器按步骤a和b进行处理
a.编码器将“当前间隔”分为子间隔,每一个事件一个。
b.个子间隔的大小与下一个将出现的事件的概率成比例,编码器选择子间隔对应于下一个确切发生的事件相对应,并使它成为新的“当前间隔”。
(3)最后输出的“当前间隔”的下边界就是该给定事件序列的算术编码。
设Low和High分别表示“当前间隔”的下边界和上边界,CodeRange为编码间隔的长度,LowRange(symbol)和HighRange(symbol)分别代表为了事件symbol分配的初始间隔下边界和上边界。上述过程的实现可用伪代码描述如下:
set Low to 0
set High to 1
while there are inputsymbols do
take a symbol
CodeRange = High – Low
High = Low + CodeRange *HighRange(symbol)
Low = Low + CodeRange * LowRange(symbol)
end of while
output Low
算术码解码过程用伪代码描述如下:
get encoded number
do
find symbol whose range straddles theencoded number
output the symbol
range = symbo.LowValue – symbol.HighValue
substracti symbol.LowValue from encodednumber
divide encoded number by range
until no more symbols
由于算术编码可以对于输入的信源符号序列不需计算概率,只需要计算累积分布函数即可进行编码输出,因此编码效率很高。当信源符号序列很长时,平均码长接近信源的信源熵。由于算数编码的效率高、编译码速度快,因此在图像压缩等方面有广泛应用,在方案设计部分给出了其实现的伪代码,由于算术编码有关信源符号序列的累积分布函数的计算是将累积分布函数写成二进位的小数,取小数后的l位(若后面有尾数,就进位到第l位)得到的,所以这样根据二进位小数截去位数可能对于精度有一定影响;算术编码也是一种对错误很敏感的编码方法,如果有一位发生错误就会导致整个消息译错,这是算术编码在实际应用中需要考虑的问题。
(四)字典码
Huffman编码、游程编码、算术编码都是基于统计思想的编码方法,但当统计参数发生了变化的时候,这种静态的统计编码就会产生性能下降。因此在1980年代提出了自适应或者半自适应的动态方法,对于工程实践中无法测定信源的统计概率或者产生统计失配时,具有较好的性能。1977-1978年由以色列的研究人员Ziv和Lempel提出的,习惯称为LZ码,由于把已经编码的字符串存储作为字典使用,又称为字典码。典型的字典码是上述二人于1977、1978年提出的LZ-77码、LZ-78码,以及1984年由韦尔奇改进的LZW码,随后又出现了对LZ码和LZW码的改进或变形的多种字典码,如LZSS码,LZRW1-4码,LZP1-4码等。这类字典码,编译简捷,易于软件实现,使其得到广泛的应用。LZ码是一种通用编码方法,就是指在信源概率统计特性不知或不存在时,对信源进行编码,而且使编码效率仍为很高的一种码。
我们先举例说明字典码的思想。设A,B两人约定在用完全相同的字典下互相通信,A将信文中的每个单词用二元标识符(a,b)代替,a,b是表示单词所在字典中的页数和在此页的位置次序,当逐个单词被替代后,就将标识符序列发给B。B收到标识符序列后可按标识符恢复单词和信文。标志符号的个数显然少于单词符号个数,就实现了文本压缩的目的。另外若对字符序列进行压缩编码,其效率要高于对单个字符的压缩。而且字符串越长,平均码长越短。在压缩编码中又常把字符串或字符序列称为数据流。
LZ-77编码算法的主要思想是把已输入的数据流存储起来,作为字典使用。编码器为输入流开设一个滑动窗口,其长可达几千字节,将输入的数据存在窗内,做字典使用,窗口右侧是待编码数据流的缓存器,长只有几十字节。用三元标识(K,Ɩ,d)给数据编码,K是窗内从尾自又向左搜索的字符位数,称为移位数,Ɩ是窗内可以与窗外有相同符号的字符串的长,称为匹配串长度,d是窗外已找到匹配的串的后面串的首字符。以自