霍夫曼信源编码实验报告
1 实验 1:霍夫曼信源编码综合设计 【实验目的】 通过本专题设计,掌握霍夫曼编码的原理和实现方法,并熟悉利用 C 语言进行 程序设计,对典型的文本数据和图像数据进行霍夫曼编解码。 【预备知识】 1、熵的概念,霍夫曼编码原则 2、数据结构和算法设计 3、C(或 C++)编程语言 【实验环境】 1、设备:计算机一台 2、软件:C 程序编译器 【设计要求】 根据霍夫曼编码原则,利用 C 语言设计并实现霍夫曼编码和解码程序,要求能 够对给出的典型文本数据和图像数据进行霍夫曼编解码,并计算相应的熵和压缩比。 【实验原理】 Huffman 编码属于熵编码的方法之一,是根据信源符号出现概率的分布特性而 进行的压缩编码。 Huffman 编码的主要思想是:出现概率大的符号用长的码字表示;反之,出现 概率小的符号用短的码字表示。 Huffman 编码过程描述: 1. 初始化:将信源符号按出现频率进行递增顺序排列,输入集合 L; 2. 重复如下操作直至 L 中只有 1个节点: (a) 从 L 中取得两个具有最低频率的节点,为它们创建一个父节点; (b) 将它们的频率和赋给父结点,并将其插入 L; 3. 进行编码 :从根节点开始,左子节点赋予 1,右节点赋予 0,直到叶子节点。2 【基本定义】 1. 熵和平均编码符号长度 熵是信息量的度量方法,它表示某一事件出现的概率越小,则该事件包含的信息 就越多。根据 Shannon 理论,信源 S 的熵定义为 ,其中 是符 2 ( ) log (1/ ) i i i H s p p i p 号 在 S 中出现的概率; 表示包含在 中的信息量,也就是编码 所需要 i S 2 log (1/ ) i p i S i S 的位数 假设符号 编码后长度为 l i(i=1,…,n),则平均编码符号长度 L 为: i S i i i L pl 2. 压缩比 设原始字符串的总长度为 L orig 位,编码后的总长度为 L coded 位,则压缩比 R 为R = (L orig- L coded )/ L orig 【例子】 有一幅40个象素组成的灰度图像,灰度共有5级,分别用符号A、B、C、D和E 表示,40个象素中出现灰度A的象素数有15个,出现灰度B的象素数有7个,出现 灰度C的象素数有7个等等,如表1所示。如果用3个位表示5个等级的灰度值, 也就是每个象素用3位表示,编码这幅图像总共需要120位。 表1 符号在图像中出现的数目 符 号 A B C D E 出现的次数 15 7 7 6 5 根据Shannon理论,这幅图像的熵为 H(S) = (15/40) (40/15)+(7/40) (40/7)++(5/40) (40/5)=2.196 2 log 2 log 2 log 平均编码符号长度L为(15/40)*1+(7/40)*3+(7/40)*3+(6/40)*3+(5/40)*3 = 2.25 根据霍夫曼编码原则可以得到如下的霍夫曼编码表。 表2 霍夫曼编码举例 符号 出现的次数 log 2 (1/p i ) 分配的 代码 所需 位数 A 15(0.375) 1.4150 1 15 B 7(0.175) 2.5145 011 21 C 7(0.175) 2.5145 010 21 D 6(0.150) 2.7369 001 18 E 5(0.125) 3.0000 000 15 因而,这副图采用霍夫曼编码的压缩比R为1.3333:1(120:90)。 霍夫曼码的码长虽然是可变的,但却不需要另外附加同步代码。例如,码串中 的第1位为0,那末肯定是符号 A,因为表示其他符号的代码没有一个是以0开始的, 因此下一位就表示下一个符号代码的第1位。同样,如果出现“110”,那么它就代3 表符号D。如果事先编写出一本解释各种代码意义的“词典”,即码簿,那么就可以 根据码簿一个码一个码地依次进行译码。 【实验步骤】 (16学时) 根据提供的示例 Huffman 编译码器源程序,利用 VC++6.0 进行编译生成可执行 文件,阅读并运行程序。 1、用 Microsoft Office Vision 分别画出 Huffman 编码和译码程序流程图,写出用 到的主要数据结构并加以说明。 2、在 Huffman 编码器合适位置加入 4个函数: calcProbability,calcEntropy,calcAvgSymbolLength,calcCompressionRatio, 分别计算信源各符号出现的概率、信源的熵、平均编码符号长度以及压缩比。 (自定义函数的参数) 3、分析霍夫曼编译码码的计算复杂度,定量说明 Huffman 编码和译码哪种操作 更耗时? 4、设计中遇到的问题,怎样解决问题的。在设计过程中的心得体会。 思考题: 1、霍夫曼编码是否具有唯一性? 2、个人对霍夫曼编码方式的不足之处的思考以及怎么样在进行压缩时避免这些 问题。 3、分析霍夫曼编码对文本数据以及图象数据的编码效率,观察与对应信源概率 分布的关系。 4、参考静止图像压缩编码国际标准 JPEG,为了提高对图像编码的效率,通常要 在霍夫曼编码之前进行什么操作? 5、。 【实验结果】 一.译码与编码流程图如下所示: 1.译码流程图4 否 是 是 否 是 否 否 是 2.编码流程图 程序初始化 主程序 调用图像库数据 接收到有效指 令? 图像显示指令? 字符显示指令? 图像像素数据? 返回主程序 显示图像 显示字符 JPEG 格式图像解码 调用字符库数据5 否 是 是 否 是 否 否 是 二.四个部分的程序 1.计算每个个符号出现的概率 void calcProbability(int total, SymbolFrequencies *pSF) { 程序初始化 主程序 调用图像库数据 接收到有效指 令? 图像显示指令? 字符显示指令? 图像像素数据? 返回主程序 显示图像编码 显示字符编码 JPEG 格式图像编码 调用字符库数据6 int i; float prob[MAX_SYMBOLS]; memset(prob, 0, sizeof(prob)); for(i = 0; i count / total; printf(“%c, %f\n“, (*pSF)[i]->symbol, prob[i]); } } } 2.计算熵 void calcEntrop(SymbolFrequencies *pSF) { int i; float prob[MAX_SYMBOLS]; double entropy; double difference; double difference1; double difference2; entropy = 0; for(i = 0; i < MAX_SYMBOLS; ++i) { difference1 = log(prob[i]); difference2 = log(2); difference = difference1/difference2; entropy = entropy - prob[i]*difference; } printf(