实验四:DPCM 压缩系统的实现和分析

本文探讨了DPCM编码技术与熵编码结合在图像压缩中的应用,通过实验验证了固定预测器与均匀量化器在不同量化比特下的编码效率。结果显示,DPCM+熵编码比单纯熵编码提高了压缩比,但图像质量无显著下降,揭示了编码效率与图像质量的权衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验原理


  DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。

  在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。

在这里插入图片描述

DPCM编解码原理图

实验内容


  在本次实验中,我们采用固定预测器和均匀量化器。预测器采用左侧、上方预测均可。量化器采用8比特均匀量化。本实验的目标是验证DPCM编码的编码效率。首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差,并对预测误差进行8比特均匀量化(基本要求) 。还可对预测误差进行1比特、2比特和4比特的量化设计。

  在DPCM编码器实现的过程中可同时输出预测误差图像和重建图像。将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。

实验结果


原始图像8bit量化4bit量化2bit量化1bit量化
量化误差图像/image-20200510235534712image-20200510235634416image-20200510235731126image-20200510235830722
重建图像(或者原始图像)image-20200510235359623image-20200510235607766image-20200510235701793image-20200510235943935
(量化误差图像)概率分布image-20200511000401984image-20200511000433263image-20200511000455502image-20200511000508625
熵编码后的文件大小(byte)2237712059201406899362693626
压缩比0.2990.2750.1880.1250.125
PSNR/psnrpsnrpsnrpsnr

  可以看出:DPCM+熵编码比仅进行熵编码编码效率提高,但图像质量无明显差别,告诉我们通过组合编码可以提高效率;都使用DPCM+熵编码的条件下,随着量化比特数的降低,压缩比越来越高,但图像质量越来越差,这也反映了效率和可靠性不能兼得,要折中考虑图像压缩效率和图像质量的关系。

代码实现


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#define WIDTH   464
#define HEIGHT 538
#define  bit 8
void count(unsigned char *data, int *count,int i,double *freq)
{
	int n=0,m=0;
	for(n=0;n<i;n++)
	{
		for(m=0;m<256;m++)
			if(data[n]==m)
				count[m]++;
	}
	for(m=0;m<256;m++)
		freq[m]=(double)count[m]/i;
}

double PSNR( unsigned char* standard, unsigned char* rebuild)
{
	double psnr = 0, MSE = 0;
	for( int i = 0; i < WIDTH*HEIGHT; i++ ) 
		MSE +=pow((rebuild[i] - standard[i])*1.0,2);
	MSE /= WIDTH*HEIGHT;
	psnr = 10 * log10( pow(4.0,8) / MSE);
	return psnr;
}

int main ()
{
	FILE* AFile =NULL;
	FILE* pre_File=NULL;
	FILE* re_File=NULL;
	FILE* fre_File=NULL;
	AFile=fopen(".\\data\\moon.yuv","rb");
	pre_File=fopen(".\\data\\pre.yuv","wb");
	re_File=fopen(".\\data\\rebuild.yuv","wb");
	fre_File=fopen(".\\data\\frequent.txt","wb");
	if(AFile==NULL)
	{
		printf("cannot find moon.yuv\n");
		exit(1);
	}
	if(pre_File==NULL)
	{
		printf("cannot find moon_1.yuv\n");
		exit(1);
	}
	if(re_File==NULL)
	{
		printf("cannot find moon_2.yuv\n");
		exit(1);
	}
	unsigned char *yBuf;
	yBuf=(unsigned char *)malloc(WIDTH*HEIGHT);
	int *pre;
	pre=(int *)malloc(sizeof(int)*WIDTH*HEIGHT);//注意sizeof
	unsigned char *pre_1;
	pre_1=(unsigned char *)malloc(WIDTH*HEIGHT);
	unsigned char *rebuild;
	rebuild=(unsigned char *)malloc(WIDTH*HEIGHT);
	int *rebuild_1;
	rebuild_1=(int *)malloc(sizeof(int)*WIDTH*HEIGHT);
	if (!feof(AFile))
	{
		if(!fread(yBuf,1,WIDTH*HEIGHT,AFile))
		{
			printf("cannot read y%d ");
		}

		for (int j=0; j<HEIGHT; j++)
		{
			for (int i=0;i<WIDTH;i++)
			{
				if (i==0)
				{
					pre_1[j*WIDTH+i]=0;
					pre[j*WIDTH+i]=0;
					rebuild[j*WIDTH+i]=yBuf[j*WIDTH+i];
				}
				else
				{
					/**预测***/
					pre[j*WIDTH+i]=yBuf[j*WIDTH+i]-rebuild[j*WIDTH+i-1];

					/***量化***/
					pre_1[j*WIDTH+i]=((pre[j*WIDTH+i]+256)/2);
					int erta=pow(2.0,(8-bit));
					pre_1[j*WIDTH+i]=(pre_1[j*WIDTH+i]/erta+0.5);

					/***反量化和重建**/
					pre_1[j*WIDTH+i]=pre_1[j*WIDTH+i]*erta;//算量化还是反量化?
					pre[j*WIDTH+i]=pre_1[j*WIDTH+i]*2-256;
// 					pre[j*WIDTH+i]=pre_1[j*WIDTH+i];
// 					pre[j*WIDTH+i]=(pre[j*WIDTH+i]*erta)*2-256;

					rebuild[j*WIDTH+i]=pre[j*WIDTH+i]+rebuild[j*WIDTH+i-1];
				}
			}
 		}
 	}
	int y_count[256]={0};
	double freq[256]={0};
	count(pre_1,y_count,WIDTH*HEIGHT,freq);
	/**输出数据的概率分布**/
	fprintf(fre_File,"Freq_B\tSymol\n"); 
	for (int m=0;m<256;m++)
	{
		fprintf(fre_File,"%.8f\n",freq[m]); 
	}
	/*输出psnr*/
	printf("psnr:%f",PSNR( yBuf, rebuild ));
	/*写入预测误差图像和重建图像*/
	fwrite(rebuild,1,WIDTH*HEIGHT,re_File);
	for (int n=0;n<WIDTH*HEIGHT;n++ )
		rebuild[n]=128;//填充U,V
	fwrite(rebuild,1,WIDTH*HEIGHT,re_File);
	fwrite(rebuild,1,WIDTH*HEIGHT,re_File);
	fwrite(pre_1,1,WIDTH*HEIGHT,pre_File);
	for (int n=0;n<WIDTH*HEIGHT;n++ )
		pre_1[n]=128;//填充U,V
	fwrite(pre_1,1,WIDTH*HEIGHT,pre_File);
	fwrite(pre_1,1,WIDTH*HEIGHT,pre_File);

	free(yBuf);
	free(pre);
	free(pre_1);
	free(rebuild);
	free(rebuild_1);
	fclose(AFile);
	fclose(pre_File);
	fclose(re_File);
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值