第四次实验:DPCM编码

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

DPCM编码原理:

第四次实验:DPCM编码_第1张图片

 

在一个DPCM系统中,需要设计预测器和量化器两部分,在本次实验中,采用固定预测器和均匀量化器

代码部分:

#include
#include
#include
using namespace std;
 
int main(int argc, char** argv)
{
	char* orifilename = NULL;
	char* prefilename = NULL;
	char* recfilename = NULL;
 
	orifilename = argv[1];
	prefilename = argv[2];
	recfilename = argv[3];
 
	FILE* fp1 = fopen(orifilename, "rb");
	FILE* fp2 = fopen(prefilename, "wb");
	FILE* fp3 = fopen(recfilename, "wb");
 
	if (fp1 == NULL)
		cout << "cannot find oriyuv" << endl;
	if (fp2 == NULL)
		cout << "cannot find preyuv" << endl;
	if (fp3 == NULL)
		cout << "cannot find recyubv" << endl;
 
	unsigned char* oribuffer;
	unsigned char* prebuffer;
	unsigned char* recbuffer;
	unsigned char* u_buffer;
	unsigned char* v_buffer;
 
	int width = atoi(argv[4]);
	int height = atoi(argv[5]);
 
	oribuffer = (unsigned char*)malloc(width * height * 1.5);
	prebuffer = (unsigned char*)malloc(width * height * 1.5);
	recbuffer = (unsigned char*)malloc(width * height);
	u_buffer = (unsigned char*)malloc(width * height * 1 / 4);
	v_buffer = (unsigned char*)malloc(width * height * 1 / 4);
 
	fread(oribuffer, sizeof(unsigned char), width * height, fp1);
 
	int p1;
	int p2;
	unsigned char p3;
 
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			if (j == 0)
			{
				*(recbuffer + i * width + j) = 128;
				*(prebuffer + i * width + j) = *(oribuffer + i * width + j) - 128;
			}
			else
			{
				p1 = *(oribuffer + i * width + j) - *(oribuffer + i * width + j - 1);//误差
				if (p1 % 2 == 0)
					p2 = p1 / 2 + 128;//8bit量化
				else
					p2 = (p1 - 1) / 2 + 128;//8bit量化
				*(prebuffer + i * width + j) = unsigned char(p2);
				p3 = unsigned char(p2 * 2);//反量化
				*(recbuffer + i * width + j) = *(oribuffer + i * width + j - 1) + p3;
			}
		}
	}
 
	for (int i = 0; i < height / 2; i++)
	{
		for (int j = 0; j < width / 2; j++)
		{
			*(u_buffer + i * width / 2 + j) = 128;
			*(v_buffer + i * width / 2 + j) = 128;
		}
	}
 
 
	fwrite(recbuffer, 1, width * height, fp3);
	fwrite(u_buffer, 1, width * height / 4, fp3);
	fwrite(v_buffer, 1, width * height / 4, fp3);
 
	fwrite(prebuffer, 1, width * height, fp2);
	fwrite(u_buffer, 1, width * height / 4, fp2);
	fwrite(v_buffer, 1, width * height / 4, fp2);
 
	int max = 255;
	double mse = 0;
	for (int i = 0; i < width * height; i++)
	{
		mse += (double(oribuffer[i]) - double(recbuffer[i])) * (double(oribuffer[i]) - double(recbuffer[i]));  //分子
	}
	mse = (double)mse / (double)(width * height);
	double psnr = 10 * log10((double)(max * max) / mse);
	cout << "PSNR = " << psnr;
 
	return 0;
}

dpcm编码

for(int i=0;i < frameWidth*frameHeight;i++)
	{
		if(i % frameWidth==0)
	{   
			prebuf[i]=(yBuf[i]-128)/2+128;
		resconbuf[i]=(prebuf[i]-128)*2+ 128;//重现信号为预测信号反量化后的值+0
		}
		else{
				prebuf[i]=(yBuf[i]- resconbuf[i-1])/2+128;// 预测信号为当前输入的y信号与上一个重现信号的差值做量化
				resconbuf[i]=((prebuf[i]-128)*2+resconbuf[i-1]);//重现信号为当前预测信号反量化后的值与上个重现信号的和的值
		}}

psnr代码

double MSE = 0;
	double sub = 0;
	double sum = 0;
	for (int j = 0; j < 256; j++)
	{
		for (int i = 0; i <256; i++)
		{
			sub = yBuf[i] - resconbuf[i];
			sum = sum + pow(sub, 2);
		}
	}
	MSE = (sum) / (256 * 256);
	double psnr = 10 * log10 ((255 * 255) / MSE);
	cout<<"PSNR="<

实验结果及分析:

8bit:

第四次实验:DPCM编码_第2张图片第四次实验:DPCM编码_第3张图片第四次实验:DPCM编码_第4张图片

4bit :

第四次实验:DPCM编码_第5张图片第四次实验:DPCM编码_第6张图片第四次实验:DPCM编码_第7张图片

  

 2bit:

第四次实验:DPCM编码_第8张图片 第四次实验:DPCM编码_第9张图片第四次实验:DPCM编码_第10张图片

 

 

 

1、从预测误差图像概率分布与原始图像的概率分布对比可以看出,预测误差图像的概率分布更集中,大部分像素都集中在灰度值为100-150之间,像素之间的关联性更高分布的很集中,很适合用霍夫曼编码进行熵编码,压缩的时候更加容易,而原始图像的概率分布则更均匀,在进行霍夫曼编码时压缩的效率就没有那么高。

2、PSNR越大,图像质量越好,8bit量化的重现图像的PSNR=51.1411dB,比4/2/1bit要好

你可能感兴趣的:(大数据)