霍夫曼编码实验

霍夫曼编码实验

霍夫曼(Huffman)编码是经典的无损编码方式,在实际应用中, Huffman编码通常与其他编码技术一起使用。本周根据《数据压缩导论(第四版)》的课后代码进行霍夫曼编码实验。请添加图片描述
实验所用到的Sena 、Sensin、Omaha原图像均为256x256像素大小的8位灰度图:
请添加图片描述请添图片描述请添加图片描述
根据 Read.me 文件的引导,代码的运行用到项目的命令参数,其中argc,argv参数的使用方法如下:

void main(int argc, char **argv)
/*argc是命令行总的参数个数;
argv[]是指针数组,共argc个参数,其中第0个参数是程序的全名,以后的参数。命令行后面跟的用户输入的参数。

argv[0]指向程序运行的全路径名
argv[1]指向在DOS命令行中执行程序名后的第一个字符串
argv[2]指向在DOS命令行中执行程序名后的第二个字符串,以此类推
*/

输出一下huff_enc.c 中 usage() 函数的内容,也可以看到具体的命令行输入格式:

Usage:
huff_enc [-i infile][-o outfile][-c codefile][-s storecode][-h]
         imagein : file containing the input to be encoded.  If no
                 name is provided input is read from standard in.  This
                 feature can be used to directly encode the output of programs
                 such as jpegll_enc, and aqfimg_enc.
         outfile : File to contain the encoded representation.  If no
                 name is provided the output is written to standard out.
         codefile: If this option is used the program will read the
                 Huffman code from codefile.  If the option is not used the
                 program computes the Huffman code for the file being encoded
         storecod: If this option is specified the Huffman code used to
                 encode the file is stored in codefile.  If this option is
                 not specified the code is stored in outfile

1、对原图像进行Huffman编码

在visual studio 中将编码器项目设为启动项目,以及本地windows调试器的调试属性中,输入项目的命令参数,得到Huffman编码后的文件:

-i ..\images\sena.img -o ..\huffmanout\sena.huff

比较编码前与编码后的文件大小:

图像名称Huffman编码前Huffman编码后压缩率(%)
Sena64kB57kB112.28
Sensin64kB60kB106.67
Omaha64kB58kB110.34

可以看到,在使用Huffman编码对图像进行压缩时,压缩率在110%左右,并不是很高,这也是无损压缩的特性带来的结果

2、对残差图像进行Huffman编码

自行编写代码 imgdiff.cpp 生成每个图像所对应的残差图像。残差图像的生成采用后向的DPCM,并采用8bit量化的形式,以sensin为例,残差图像如下:

在这里插入图片描述

所用到的DPCM代码:

imgdiff.cpp

/* Your codes here */

#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
#pragma warning(disable:4996)

void dpcm_diff(unsigned char* imagebuf, unsigned char* diffbuf,int width, int height, int bitdepth)
{
	for (int i = 0; i < width; i++)
	{
		for (int j = 1; j < height; j++)
		{
			diffbuf[i * width + j] = (imagebuf[i * width + j] - imagebuf[i * width + j - 1]+255) / pow(2, (9 - bitdepth));
		}
	}

	for (int i = 0; i < width * height; i++)
	{
		if (diffbuf[i] > 255)
			diffbuf[i] = 255;
		if (diffbuf[i] < 0)
			diffbuf[i] = 0;
	}
}

void main()
{
	FILE* image = NULL; FILE* qyuv = NULL; FILE* diff_image = NULL;
	const int width = 256; const int height = 256;
	int bitdepth = 8;
	if (!(image = fopen("../images/sensin.img", "rb")))
	{
		printf("open file error!");
		exit(-1);
	}
	else
	{
		printf("open file success");
	}
	
	if (!(diff_image = fopen("../out/sensin_diff.img", "wb")))
	{
		printf("open file error!");
		exit(-1);
	}
	else
	{
		printf("open file success");
	}
	unsigned char* imagebuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
	unsigned char* diffbuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height);

	fread(imagebuf, sizeof(unsigned char), width * height, image);
	dpcm_diff(imagebuf, diffbuf,width, height, bitdepth);


	fwrite(diffbuf, sizeof(unsigned char), width * height, diff_image);
	free(diffbuf); free(imagebuf);
	fclose(image);
	fclose(diff_image);

}

接着用同样的方式对残差图像进行Huffman压缩编码,比较编码前与编码后的文件大小:

图像名称Huffman编码前Huffman编码后压缩率(%)
Sena.diff64kB26kB246.15
Sensin.diff64kB30kB213.33
Omaha.diff64kB45kB142.22

可见结合了DPCM的Huffman编码与单独使用Huffman编码相比,压缩率大幅度提升了,DPCM将原图像的分布转化为拉普拉斯分布,对Huffman编码有着良好的适应性。

3、用Sensin图像的码本对其他图像编码

根据命令参数指引,生成Sensin图像的码本:

-i ..\images\sensin.img -o ..\huffmanout\sensin.huff -s .\huffmanout\sensin.code

接着对bookshelf1.img进行编码,使用刚刚生成的码本:

-i ..\images\bookshelf1.img -o ..\huffmanoutout\bookshelf1.huff -c ..\out\sensin.code

比对分析两幅图像的压缩效果:

图像名称编码前编码后(Sensin码本)压缩率(%)
Sensin64kB57kB112.28
bookshelf164kB71kB90.14

可见对于自身的码本,图像进行Huffman编码能够对图像进行压缩,而对于其他图像的码本,在进行Huffman编码时可能不能达到良好的压缩效果,甚至会出现负压缩,这是因为两幅图像的灰度概率分布不一致所造成的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值