实验四——DPCM编码(1bit、2bit、4bit、8bit量化)

一.实验要求

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

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

二.实验原理

8bit量化:由于原始Y图像的像素的Y值的取值范围为0~255,故预测误差Pn的取值范围为-255~255,要将其量化限制在0~255的范围内。对于8bit量化,将Pn除2可将Pn的范围变成-128~127(实验中Pn使用int型存储,int型自动取整故范围变为-128~127),再整体加上128则范围变成0~255,刚好可以用8bit表示。故将unsigned char(Pn/2+128)存储到误差图像的当前样本值中。特别注意:原始Y图像每行第一个值直接存储到误差图像和存储器中的图像上,误差图像中每行第一个必须为原始Y图像的每行第一个值而不能为0,否则恢复时没有第一个元素值不能恢复。

4bit量化:4bit量化的难点在于:1)误差图像中存储的每个像素对应4bit,非整数字节,存在非整数字节存取问题,本次实验中使用的解决方法是定义位域结构体。注意每行第一个的误差值仍使用8bit来表示2)4bit表示范围为0000~1111,每个码字的值并不与预测误差的值相等,需要设计规则将-255~255、0000~1111、0~255三者对应起来。解决方法:-255~255转化为0000~1111的方法:对于-255~255区间,处于区间下半段的值令其量化后首位为0,处于上半段的令其量化后首位为1,再在小区间中用此方法,以此类推,伪代码如下:

for(i=0;i<4;i++)
{
    if(Pn>(max+min)/2)
    {
        当位为1;
        min=(max+min)/2;
    }
    else
    {
        当位为0;
        max=(max+min)/2;
    }
}

三.关键代码及分析

1.缓冲区分配

2.当位置1置0的实现

error_buffer_4bit->data=0;
switch(k)
{
	case 0:error_buffer_4bit->data|=0x8; break;
	case 1:error_buffer_4bit->data|=0x4; break;
	case 2:error_buffer_4bit->data|=0x2; break;
	case 3:error_buffer_4bit->data|=0x1; break;
}

先将当前样本误差值置0,则四位均初始化为0,置0时不需要再操作,只需要编写置1的代码。k为0的时候要将首位置1,故将其与1000(0x8)按位或来实现,其余三位同理。

四.完整代码

1.8bit量化

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv)
{
	int height,width;
	char *filename_yuv,*filename_error,*filename_decoding;
	filename_yuv=argv[1];
	height=atoi(argv[2]);
	width=atoi(argv[3]);
	filename_error=argv[4];
	filename_decoding=argv[5];
	unsigned char *YUV_buffer=NULL,*Y_buffer;
	unsigned char *YUV_buffer_del;
	YUV_buffer=new unsigned char[height*width*3/2];
	YUV_buffer_del=YUV_buffer;
	if((width%2==1)||(height%2==1))
	{
		printf("please input the right height and width/n");
	}
	FILE *fp_yuv=NULL,*fp_error=NULL,*fp_decoding=NULL;
	fp_yuv=fopen(filename_yuv,"rb");
	fp_error=fopen(filename_error,"wb");
	fp_decoding=fopen(filename_decoding,"wb");
	if((fp_yuv==NULL)||(fp_error==NULL)||(fp_decoding==NULL))
	{
		printf("can not open the file/n");
		exit(1);
	}
	fread(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
	Y_buffer=YUV_buffer;
	unsigned char *error_buffer,*decoding_buffer;
	error_buffer=new unsigned char[height*width*3/2];
	decoding_buffer=new unsigned char[height*width*3/2];
	unsigned char *Y_buffer_operate,*error_buffer_operate,*decoding_buffer_operate;
	unsigned char *Y_buffer_del,*error_buffer_del,*decoding_buffer_del;
	Y_buffer_del=Y_buffer;
	error_buffer_del=error_buffer;
	decoding_buffer_del=decoding_buffer;
	Y_buffer_operate=Y_buffer;
	error_buffer_operate=error_buffer;
	decoding_buffer_operate=decoding_buffer;
	for(int i=0;i<height;i++)
	{
		for(int j=0;j<width;j++)
		{
			if(j==0)
			{
				*error_buffer_operate=*Y_buffer;
				*decoding_buffer_operate=*Y_buffer_operate;
				Y_buffer_operate++;
				error_buffer_operate++;
				decoding_buffer_operate++;
			}
			else
			{
				unsigned char temp_last_xn;
				temp_last_xn=decoding_buffer[i*width+j-1];
				int temp_pn;
				temp_pn=int(*Y_buffer_operate-temp_last_xn);
				*error_buffer_operate=unsigned char(temp_pn/2+128);
				*decoding_buffer_operate=(*error_buffer_operate-128)*2+temp_last_xn;
				Y_buffer_operate++;
				error_buffer_operate++;
				decoding_buffer_operate++;
			}
		}
	}
	for(int i=0;i<height*width/2;i++)
	{

		*error_buffer_operate=128;
		*decoding_buffer_operate=128;
		error_buffer_operate++;
		decoding_buffer_operate++;
	}
	fwrite(decoding_buffer,sizeof(unsigned char),height*width*3/2,fp_decoding);
	fwrite(error_buffer,sizeof(unsigned char),height*width*3/2,fp_error);
	fclose(fp_yuv);
	fclose(fp_error);
	fclose(fp_decoding);
	delete[] Y_buffer_del;
	delete[] error_buffer_del;
	delete[] decoding_buffer_del;
	return 0;
}

2.4bit量化

#include<stdio.h>
#include<stdlib.h>
typedef struct definedtype
{
	unsigned char data:4;//定义4bit类型
}Bit4;
int main(int argc, char** argv)
{
	int height,width;
	char *filename_yuv,*filename_error,*filename_decoding;
	filename_yuv=argv[1];
	height=atoi(argv[2]);
	width=atoi(argv[3]);
	filename_error=argv[4];
	filename_decoding=argv[5];
	unsigned char *YUV_buffer=NULL,*Y_buffer;
	unsigned char *YUV_buffer_del;
	YUV_buffer=new unsigned char[height*width*3/2];
	YUV_buffer_del=YUV_buffer;
	if((width%2==1)||(height%2==1))
	{
		printf("please input the right height and width/n");
	}
	FILE *fp_yuv=NULL,*fp_error=NULL,*fp_decoding=NULL;
	fp_yuv=fopen(filename_yuv,"rb");
	fp_error=fopen(filename_error,"wb");
	fp_decoding=fopen(filename_decoding,"wb");
	if((fp_yuv==NULL)||(fp_error==NULL)||(fp_decoding==NULL))
	{
		printf("can not open the file/n");
		exit(1);
	}
	fread(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
	Y_buffer=YUV_buffer;
	unsigned char *error_buffer,*decoding_buffer;
	error_buffer=new unsigned char[height*width*3/2];
	decoding_buffer=new unsigned char[height*width*3/2];
	unsigned char *Y_buffer_operate,*error_buffer_operate,*decoding_buffer_operate;
	unsigned char *Y_buffer_del,*error_buffer_del,*decoding_buffer_del;
	Y_buffer_del=Y_buffer;
	error_buffer_del=error_buffer;
	decoding_buffer_del=decoding_buffer;
	Y_buffer_operate=Y_buffer;
	error_buffer_operate=error_buffer;
	decoding_buffer_operate=decoding_buffer;

	//定义用来存储4bit量化的预测误差
	Bit4 *error_buffer_4bit,*error_buffer_4bit_del;
	error_buffer_4bit=new Bit4[height*width+height];
	error_buffer_4bit_del=error_buffer_4bit;

	for(int i=0;i<height;i++)
	{
		for(int j=0;j<width;j++)
		{
			if(j==0)
			{
				
				//每行第一个量化误差仍然使用8bit存储
				unsigned char *first_tier;
				first_tier=(unsigned char *)error_buffer_4bit;
				*first_tier=*Y_buffer;
				*error_buffer_operate=*Y_buffer;

				*decoding_buffer_operate=*Y_buffer;
				Y_buffer_operate++;
				error_buffer_operate++;
				decoding_buffer_operate++;
				error_buffer_4bit+=2;//每行第一个存储完之后4bit量化误差的缓冲区指针要后移两位
			}
			else
			{
				unsigned char temp_last_xn;
				temp_last_xn=decoding_buffer[i*width+j-1];
				int temp_pn;
				temp_pn=int(*Y_buffer_operate-temp_last_xn);
				//temp_pn+=255;
				
				//4bit量化
				int max,min;
				max=255;
				min=-255;


				error_buffer_4bit->data=0;
				for(int k=0;k<4;k++)
				{
					if(temp_pn>(max+min)/2)
					{
						switch(k)
						{
						case 0:error_buffer_4bit->data|=0x8; break;
						case 1:error_buffer_4bit->data|=0x4; break;
						case 2:error_buffer_4bit->data|=0x2; break;
						case 3:error_buffer_4bit->data|=0x1; break;
						}
						min=(max+min)/2;
					}
					else
					{
						max=(max+min)/2;
					}
				}

				//4bit转化为[0~255]可输出的存储到error_buffer_operate
				*error_buffer_operate=16*((*error_buffer_4bit).data);

				//反量化
				*decoding_buffer_operate=16*((*error_buffer_4bit).data)-128+temp_last_xn;
	

				Y_buffer_operate++;
				error_buffer_4bit++;
				error_buffer_operate++;
				decoding_buffer_operate++;
			}
		}
	}
	for(int i=0;i<height*width/2;i++)
	{

		*error_buffer_operate=128;
		*decoding_buffer_operate=128;
		error_buffer_operate++;
		decoding_buffer_operate++;
	}
	fwrite(decoding_buffer,sizeof(unsigned char),height*width*3/2,fp_decoding);
	fwrite(error_buffer,sizeof(unsigned char),height*width*3/2,fp_error);
	fclose(fp_yuv);
	fclose(fp_error);
	fclose(fp_decoding);
	delete[] Y_buffer_del;
	delete[] error_buffer_del;
	delete[] decoding_buffer_del;
	delete[] error_buffer_4bit_del;
	return 0;
}

3.2bit量化

#include<stdio.h>
#include<stdlib.h>
typedef struct definedtype
{
	unsigned char data:2;//定义2bit类型
}Bit2;
int main(int argc, char** argv)
{
	int height,width;
	char *filename_yuv,*filename_error,*filename_decoding;
	filename_yuv=argv[1];
	height=atoi(argv[2]);
	width=atoi(argv[3]);
	filename_error=argv[4];
	filename_decoding=argv[5];
	unsigned char *YUV_buffer=NULL,*Y_buffer;
	unsigned char *YUV_buffer_del;
	YUV_buffer=new unsigned char[height*width*3/2];
	YUV_buffer_del=YUV_buffer;
	if((width%2==1)||(height%2==1))
	{
		printf("please input the right height and width/n");
	}
	FILE *fp_yuv=NULL,*fp_error=NULL,*fp_decoding=NULL;
	fp_yuv=fopen(filename_yuv,"rb");
	fp_error=fopen(filename_error,"wb");
	fp_decoding=fopen(filename_decoding,"wb");
	if((fp_yuv==NULL)||(fp_error==NULL)||(fp_decoding==NULL))
	{
		printf("can not open the file/n");
		exit(1);
	}
	fread(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
	Y_buffer=YUV_buffer;
	unsigned char *error_buffer,*decoding_buffer;
	error_buffer=new unsigned char[height*width*3/2];
	decoding_buffer=new unsigned char[height*width*3/2];
	unsigned char *Y_buffer_operate,*error_buffer_operate,*decoding_buffer_operate;
	unsigned char *Y_buffer_del,*error_buffer_del,*decoding_buffer_del;
	Y_buffer_del=Y_buffer;
	error_buffer_del=error_buffer;
	decoding_buffer_del=decoding_buffer;
	Y_buffer_operate=Y_buffer;
	error_buffer_operate=error_buffer;
	decoding_buffer_operate=decoding_buffer;

	//定义用来存储2bit量化的预测误差
	Bit2 *error_buffer_2bit,*error_buffer_2bit_del;
	error_buffer_2bit=new Bit2[height*width+height*3];
	error_buffer_2bit_del=error_buffer_2bit;

	for(int i=0;i<height;i++)
	{
		for(int j=0;j<width;j++)
		{
			if(j==0)
			{
				
				//每行第一个量化误差仍然使用8bit存储
				unsigned char *first_tier;
				first_tier=(unsigned char *)error_buffer_2bit;
				*first_tier=*Y_buffer;
				*error_buffer_operate=*Y_buffer;

				*decoding_buffer_operate=*Y_buffer;
				Y_buffer_operate++;
				error_buffer_operate++;
				decoding_buffer_operate++;
				error_buffer_2bit+=4;//每行第一个存储完之后2bit量化误差的缓冲区指针要后移4位
			}
			else
			{
				unsigned char temp_last_xn;
				temp_last_xn=decoding_buffer[i*width+j-1];
				int temp_pn;
				temp_pn=int(*Y_buffer_operate-temp_last_xn);
				//temp_pn+=255;
				
				//2bit量化
				int max,min;
				max=255;
				min=-255;


				error_buffer_2bit->data=0;
				for(int k=0;k<2;k++)
				{
					if(temp_pn>(max+min)/2)
					{
						switch(k)
						{
						case 0:error_buffer_2bit->data|=0x2; break;
						case 1:error_buffer_2bit->data|=0x1; break;
						}
						min=(max+min)/2;
					}
					else
					{
						max=(max+min)/2;
					}
				}

				//4bit转化为[0~255]可输出的存储到error_buffer_operate
				*error_buffer_operate=64*((*error_buffer_2bit).data);

				//反量化
				*decoding_buffer_operate=64*((*error_buffer_2bit).data)-128+temp_last_xn;
	

				Y_buffer_operate++;
				error_buffer_2bit++;
				error_buffer_operate++;
				decoding_buffer_operate++;
			}
		}
	}
	for(int i=0;i<height*width/2;i++)
	{

		*error_buffer_operate=128;
		*decoding_buffer_operate=128;
		error_buffer_operate++;
		decoding_buffer_operate++;
	}
	fwrite(decoding_buffer,sizeof(unsigned char),height*width*3/2,fp_decoding);
	fwrite(error_buffer,sizeof(unsigned char),height*width*3/2,fp_error);
	fclose(fp_yuv);
	fclose(fp_error);
	fclose(fp_decoding);
	delete[] Y_buffer_del;
	delete[] error_buffer_del;
	delete[] decoding_buffer_del;
	delete[] error_buffer_2bit_del;
	return 0;
}

4.1bit量化

#include<stdio.h>
#include<stdlib.h>
typedef struct definedtype
{
	unsigned char data:1;//定义2bit类型
}Bit1;
int main(int argc, char** argv)
{
	int height,width;
	char *filename_yuv,*filename_error,*filename_decoding;
	filename_yuv=argv[1];
	height=atoi(argv[2]);
	width=atoi(argv[3]);
	filename_error=argv[4];
	filename_decoding=argv[5];
	unsigned char *YUV_buffer=NULL,*Y_buffer;
	unsigned char *YUV_buffer_del;
	YUV_buffer=new unsigned char[height*width*3/2];
	YUV_buffer_del=YUV_buffer;
	if((width%2==1)||(height%2==1))
	{
		printf("please input the right height and width/n");
	}
	FILE *fp_yuv=NULL,*fp_error=NULL,*fp_decoding=NULL;
	fp_yuv=fopen(filename_yuv,"rb");
	fp_error=fopen(filename_error,"wb");
	fp_decoding=fopen(filename_decoding,"wb");
	if((fp_yuv==NULL)||(fp_error==NULL)||(fp_decoding==NULL))
	{
		printf("can not open the file/n");
		exit(1);
	}
	fread(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
	Y_buffer=YUV_buffer;
	unsigned char *error_buffer,*decoding_buffer;
	error_buffer=new unsigned char[height*width*3/2];
	decoding_buffer=new unsigned char[height*width*3/2];
	unsigned char *Y_buffer_operate,*error_buffer_operate,*decoding_buffer_operate;
	unsigned char *Y_buffer_del,*error_buffer_del,*decoding_buffer_del;
	Y_buffer_del=Y_buffer;
	error_buffer_del=error_buffer;
	decoding_buffer_del=decoding_buffer;
	Y_buffer_operate=Y_buffer;
	error_buffer_operate=error_buffer;
	decoding_buffer_operate=decoding_buffer;

	//定义用来存储2bit量化的预测误差
	Bit1 *error_buffer_1bit,*error_buffer_1bit_del;
	error_buffer_1bit=new Bit1[height*width+height*7];
	error_buffer_1bit_del=error_buffer_1bit;

	for(int i=0;i<height;i++)
	{
		for(int j=0;j<width;j++)
		{
			if(j==0)
			{
				
				//每行第一个量化误差仍然使用8bit存储
				unsigned char *first_tier;
				first_tier=(unsigned char *)error_buffer_1bit;
				*first_tier=*Y_buffer;
				*error_buffer_operate=*Y_buffer;

				*decoding_buffer_operate=*Y_buffer;
				Y_buffer_operate++;
				error_buffer_operate++;
				decoding_buffer_operate++;
				error_buffer_1bit+=8;//每行第一个存储完之后1bit量化误差的缓冲区指针要后移8位
			}
			else
			{
				unsigned char temp_last_xn;
				temp_last_xn=decoding_buffer[i*width+j-1];
				int temp_pn;
				temp_pn=int(*Y_buffer_operate-temp_last_xn);
				//temp_pn+=255;
				
				//1bit量化
				int max,min;
				max=255;
				min=-255;


				error_buffer_1bit->data=0;
				if(temp_pn>(max+min)/2)
					{
						
						error_buffer_1bit->data|=0x1;
						
						min=(max+min)/2;
					}
					else
					{
						max=(max+min)/2;
					}
				

				//1bit转化为[0~255]可输出的存储到error_buffer_operate
				*error_buffer_operate=128*((*error_buffer_1bit).data);

				//反量化
				*decoding_buffer_operate=128*((*error_buffer_1bit).data)-128+temp_last_xn;
	

				Y_buffer_operate++;
				error_buffer_1bit++;
				error_buffer_operate++;
				decoding_buffer_operate++;
			}
		}
	}
	for(int i=0;i<height*width/2;i++)
	{

		*error_buffer_operate=128;
		*decoding_buffer_operate=128;
		error_buffer_operate++;
		decoding_buffer_operate++;
	}
	fwrite(decoding_buffer,sizeof(unsigned char),height*width*3/2,fp_decoding);
	fwrite(error_buffer,sizeof(unsigned char),height*width*3/2,fp_error);
	fclose(fp_yuv);
	fclose(fp_error);
	fclose(fp_decoding);
	delete[] Y_buffer_del;
	delete[] error_buffer_del;
	delete[] decoding_buffer_del;
	delete[] error_buffer_1bit_del;
	return 0;
}

四.实验结果

1.湖面倒影图:

8bit:

4bit:

2bit:

1bit:

2.Lena图:

8bit:

4bit:

2bit:

1bit:

3.湖面倒影图的haffcode比较:

4.湖面倒影图的PSNR值:

8bit、4bit恢复图像相对于原始图像的psnr

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值