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

一.实验要求

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

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

二.实验原理

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第1张图片

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,否则恢复时没有第一个元素值不能恢复。

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第2张图片

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;
    }
}

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第3张图片

三.关键代码及分析

1.缓冲区分配

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第4张图片

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
#include
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

2.4bit量化

#include
#include
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;idata=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

3.2bit量化

#include
#include
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;idata=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

4.1bit量化

#include
#include
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;idata=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

四.实验结果

1.湖面倒影图:

8bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第5张图片

4bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第6张图片

2bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第7张图片

1bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第8张图片

2.Lena图:

8bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第9张图片

4bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第10张图片

2bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第11张图片

1bit:

实验四——DPCM编码(1bit、2bit、4bit、8bit量化)_第12张图片

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

4.湖面倒影图的PSNR值:

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

你可能感兴趣的:(实验四——DPCM编码(1bit、2bit、4bit、8bit量化))