数据压缩【实验四】DPCM压缩系统的实现和分析

一、实验目的

掌握DPCM编解码系统的基本原理
用C/C++/Python等语言编程实现DPCM编码器,并分析其压缩效率。

二、实验原理

DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。
在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。
在这里插入图片描述
在这里插入图片描述

三、 实验代码

由于我们采用左侧像素对图像进行DPCM编码,故每行第一个像素需要将原始值传去。其余的像素值进行计算残差、量化;然后重建时反量化。

(1)代码

DPCM

void DPCMLeft(int Width,int Height,void *yBuff,void *recBuff,void *errBuff)//DPCM向左预测
{
   unsigned char *yB=NULL;
   yB = (unsigned char *)yBuff;
   unsigned char *recB=NULL;
   recB = (unsigned char *)recBuff;
   unsigned char *errB=NULL;
   errB = (unsigned char *)errBuff;
   int P1,P2;//P1为当前值与预测值的误差,P2为量化后的误差
   unsigned char P3;//P3为反量化后的误差

   for(int i=0;i<Height;i++)
   {
   	for(int j=0;j<Width;j++)
   	{
   		if(j == 0)//向左进行预测时,图像最左边一列的像素值直接输出,无需进行差分预测
   		{
   			*(recB+j+i*Width)=*(yB+j+i*Width);//当前值即为重建值,作为下一个像素的参考值
   			*(errB+j+i*Width)=0;//误差为0
   		}
   		else//当不是最左边一列的像素时,进行DPCM
   		{
   			P1=*(yB+j+i*Width)-*(recB+(j-1)+i*Width);//求当前值与参考值的差值
   			if(P1%2==0)//对差值进行8bit均匀量化,并进行+128的偏移以输出
   				P2=P1/2+128;
   			else
   				P2=(P1-1)/2+128;
   			*(errB+j+i*Width)=unsigned char(P2);//将误差写入errB缓存区域
   			P3=unsigned char(P2*2);//对量化后的误差反量化
   			*(recB+j+i*Width)=*(recB+(j-1)+i*Width)+P3;
   			//将参考值与反量化得到的误差相加,作为当前像素的重建值,即下一个像素的参考值
   		}
   	}
   }
}

8bit量化

			dpBuf[i] = tmp / 2 + 128;
			out = yBuf[i - 1] + (dpBuf[i] - 128) * 2;
			if (out > 255)
				out = 255;
			if (out < 0)
				out = 0;
			yBuf[i] = out;

4bit量化

			dpBuf[i] = tmp / 32 + 16;
			out = yBuf[i - 1] + (dpBuf[i] - 16) * 32;
			if (out > 255)
				out = 255;
			if (out < 0)
				out = 0;
			yBuf[i] = out;

主函数

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <string.h>
#include"DPCM.h"

int main(int argc, char** argv)
{
	int frameWidth;			
	int frameHeight;		
	
	char* yFileName = NULL;//原始的灰度文件
	FILE* yFile = NULL;
	unsigned char* y_Buf = NULL;
	char* recFileName = NULL;//重建的图像文件
	FILE* recFile = NULL;
	unsigned char* rec_Buf = NULL;
	char* errFileName = NULL;//量化后的预测误差文件
	FILE* errFile = NULL;
	unsigned char* err_Buf = NULL;

	unsigned char* u_Buf = NULL;
	unsigned char* v_Buf = NULL;
		
	yFileName = argv[1];
	recFileName = argv[2];
	errFileName = argv[3];
	frameWidth = atoi(argv[4]);
	frameHeight = atoi(argv[5]);

	fopen_s(&yFile,yFileName, "rb");//打开灰度文件
	if (yFile == NULL)
	{
		printf("cannot find y file\n");
		exit(1);
	}
	recFile = fopen(recFileName, "wb");//打开重建图像文件
	if (recFile == NULL)
	{
		printf("cannot find yuv file\n");
		exit(1);
	}
	errFile = fopen(errFileName, "wb");//打开量化后的误差文件
	if (errFile == NULL)
	{
		printf("cannot find yuv file\n");
		exit(1);
	}

	y_Buf = (unsigned char*)malloc(frameWidth * frameHeight * sizeof(unsigned char));  //开辟5个缓存空间
	u_Buf = (unsigned char*)malloc(frameWidth * frameHeight * sizeof(unsigned char) / 4);
	v_Buf = (unsigned char*)malloc(frameWidth * frameHeight * sizeof(unsigned char) / 4);
	rec_Buf = (unsigned char*)malloc(frameWidth * frameHeight * sizeof(unsigned char));
	err_Buf = (unsigned char*)malloc(frameWidth * frameHeight * sizeof(unsigned char)*1.5);
	if (y_Buf == NULL || rec_Buf == NULL || err_Buf == NULL || u_Buf == NULL ||v_Buf == NULL)
	{
		printf("wrong malloc\n");
		exit(1);
	}

	fread(y_Buf, 1, frameWidth * frameHeight, yFile);//读取灰度文件数据
	if (y_Buf == NULL)
	{
		printf("wrong fread\n");
		exit(1);
	}

	//DPCMLeft(frameWidth,frameHeight,y_Buf,rec_Buf,err_Buf);//向左进行预测
	DPCMUp(frameWidth,frameHeight,y_Buf,rec_Buf,err_Buf);//向上进行预测

	for(int i=0;i<frameHeight/2;i++)
	{
		for(int j=0;j<frameWidth/2;j++)
		{
			*(u_Buf+j+i*frameWidth/2)=128;
			*(v_Buf+j+i*frameWidth/2)=128;
		}
	}
	fwrite(rec_Buf, 1, frameWidth * frameHeight, recFile);//将数据写入文件进行输出
	fwrite(err_Buf, 1, frameWidth * frameHeight, errFile);
	fwrite(u_Buf, 1, frameWidth * frameHeight / 4, errFile);
	fwrite(v_Buf, 1, frameWidth * frameHeight / 4, errFile);

	//计算PSNR
	simplest_yuv420_psnr(y_Buf,rec_Buf,frameWidth,frameHeight,1);

	free(y_Buf);
	free(rec_Buf);
	free(err_Buf);
	free(u_Buf);
	free(v_Buf);
	fclose(yFile);
	fclose(recFile);
	fclose(errFile);
}

(2)输出结果

8bit
残差图像
在这里插入图片描述
重建图像
在这里插入图片描述
4bit
残差图像
在这里插入图片描述

重建图像
在这里插入图片描述

四、实验结果

(1)压缩

我们将预测误差图像通过霍夫曼编码器压缩,与原图像直接压缩进行比较。
8bit:

压缩前压缩后
96kb43kb

原图与8bit残差图像像素值概率分布图
在这里插入图片描述

4bit:

压缩前压缩后
96kb15kb

原图与4bit残差图像像素值概率分布图
在这里插入图片描述

通过图像像素概率分布图我们可以明显看出残差图的像素值集中分布在一个小像素值区间中,这对霍夫曼编码压缩是极为有利的。

(2) PSNR峰值信噪比

原理

给定一张大小为m × n 的原始干净图像C,和一张同大小的重建的噪声图像N 。我们计算它俩之间的均方误差 MSE。
在这里插入图片描述
然后我们计算出原始图像可能出现的最大像素值。对于8位图像数据,这个值为255 。
最后,我们定义PSNR(dB)为
在这里插入图片描述
PSNR值越大,就代表失真越少
PSNR高于40dB说明图像质量极好(即非常接近原始图像),
在30—40dB通常表示图像质量是好的(即失真可以察觉但可以接受),
在20—30dB说明图像质量差;

算法

int simplest_yuv420_psnr(void *yBuff1,void *yBuff2, int w, int h, int num)//计算Y分量的PSNR
{
	unsigned char *yB1=NULL;
	yB1 = (unsigned char *)yBuff1;
	unsigned char *yB2=NULL;
	yB2 = (unsigned char *)yBuff2;

	for (int i = 0; i < num; i++)
	{
		double mse_sum = 0, mse = 0, psnr = 0;
		for (int j = 0; j < h ; j++)
		{
			for (int k = 0; k < w; k++)
			{
				mse_sum += pow((double)(*(yB1+k+j*w) - *(yB2+k+j*w)), 2);//取每个差值的平方,并进行累加
			}
		}
		mse = mse_sum / (w * h); //根据公式计算mse
		psnr = 10 * log10(255.0 * 255.0 / mse); //根据公式计算psnr
		printf("%5.3f\n", psnr);
	}
	system("pause");
	return 0;
}


重建图像

8bit:PSNR=51.177
4bit:PSNR=24.263

五、实验分析

(1)在这里插入图片描述
(2)DPCM系统需要设计预测器、量化器,量化电平数要足够大(M>=8)(3)经过DPCM+熵编码之后,图像大小比直接使用熵编码减小的更多。
(4)经过DPCM+熵编码的PSNR值比只经过熵编码的PSNR值小,表明经过DPCM预测编码后重建出的图像质量比原始图像的质量差。

(5)和实际信号的分布相比,预测误差是关于0的高尖峰。因此,预测误差具有比原始密度更小的熵。这意味着预测的过程把样值间的大部分冗余去掉了。
(6)失真分析
在这里插入图片描述
斜率过载:量化步长跟不上信号变换的速度,量化bit越小,这个现象越明显。
粒状噪声:量化步长相当于信号变化的幅度来说太大了。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DPCM(差分脉冲编码调制)是一种数据压缩系统,其目的是在尽量不失真的情况下减少数据存储或传输所需的带宽。DPCM 压缩系统实现主要是在传输前对原始信号进行差分编码,将每一个样本值与它前面的样本值的差值编码传输。在解码端,将编码的差值与前一个样本值相加,得到解码后的样本值。 DPCM 压缩系统的性能取决于差分编码器的性能和采样率。通常,差分编码器需要对原始信号进行线性预测,并将其与实际样本值的差异编码。预测器的设计和参数设置是影响性能的关键因素。 DPCM 压缩系统主要有以下优点:首先,DPCM 采用差分编码,可以将一系列相邻的样本压缩成差分值,从而减少需要传输的数据量。其次,由于 DPCM 是一种有损压缩策略,可以通过控制压缩后的失真来有效地减少数据量。再者,DPCM 压缩系统的计算和编码速度较快,可以在硬件中实现,适用于实时视频或音频传输。 然而,DPCM 压缩系统也有一些缺点。首先,差分编码容易受到干扰和噪声的影响,从而导致误差传播和失真的增加。此外,DPCM 不适用于大多数不规则信号,如图片和文本等。 总之,DPCM 压缩系统是一种有损压缩策略,可以通过对原始信号进行差分编码来减少数据量。其性能主要取决于差分编码器的设计和采样率,适用于实时音视频传输和存储等场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值