DPCM编码算法实现

目录

一、DPCM编解码原理

二、DPCM编码系统设计

三、算法实现

1.代码

2.运行结果

 3.结果分析


一、DPCM编解码原理

DPCM编码算法实现_第1张图片

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

二、DPCM编码系统设计

在本次实验中,我们采用固定预测器和均匀量化器。

  • 预测器采用左侧、上方预测均可。
  • 量化器采用8比特均匀量化。

本实验的目标是验证验证DPCM的编码效率。

  • 首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差,并对预测误差进行8比特均匀量化。
  • 在DPCM编码器实现的过程中可同时输出预测误差图像和重建图像。
  • 预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流,给出概率分布图并计算压缩比。
  • 原始图像文件输入Huffman编码器,得到输出码流,给出概率分布图并计算压缩比。
  • 最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。

 

三、算法实现

1.代码

#include 
#include 
#include 
#include 
int main(int argc, char** argv)
{
	unsigned __int32 width = 256;
	unsigned __int32 height = 256;
	
	
	// 读取文件 
	char *yuvname = NULL;
	char *newyuvname = NULL;
	FILE* yuvFile = NULL;
	FILE* newyuvFile = NULL;
	char *pname = NULL;
	FILE* pFile = NULL;
	yuvname = argv[1];
	newyuvname = argv[2];
	pname= argv[3];
	yuvFile = fopen(yuvname, "rb");
	if (!yuvFile)
		printf("原YUV文件打开失败\n");
	else
		printf("成功打开YUV文件\n");
	newyuvFile = fopen(newyuvname, "wb");
	if (!newyuvFile)
		printf("重建YUV文件打开失败\n");
	else
		printf("重建YUV文件打开成功\n");
	pFile = fopen(pname, "wb");
	if (!pFile)
		printf("误差文件打开失败\n");
	else
		printf("误差文件打开成功\n");
		
	
	unsigned char* yuvBuf = NULL;
	unsigned char* uBuf = NULL;
	unsigned char* vBuf = NULL;
    unsigned char * pBuf = NULL;
	float* dBuf = NULL;
	unsigned char* rBuf = NULL;
	
	yuvBuf = (unsigned char*)malloc(width*height);
	uBuf = (unsigned char*)malloc(width*height / 4);
	vBuf = (unsigned char*)malloc(width*height / 4);
	pBuf = (unsigned char*)malloc(width*height);//预测误差的量化值
	rBuf = (unsigned char*)malloc(width*height);//重现图像
	dBuf = (float*)malloc(width*height*4);//输入预测误差
	unsigned char* doBuf = (unsigned char*)malloc(width*height * 4);
	
	if (yuvBuf == NULL || uBuf == NULL || vBuf == NULL || pBuf == NULL)
	{
		printf("ERROR");

	}

	fread(yuvBuf, 1, width * height * 1, yuvFile);

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (j == 0) {
				pBuf[i*width + j] = 0;
				rBuf[i*width + j] = yuvBuf[i*width + j];
				dBuf[i*width + j] = 0;
			}
			else {
				dBuf[(i*width + j)] = float(yuvBuf[i*width + j]) - float(rBuf[i*width + j - 1]);
				if (dBuf[ (i*width + j)] >= 0) {
					pBuf[i*width + j] = floor(dBuf[(i*width + j)] + 0.5);
					rBuf[i*width + j] = rBuf[i*width + j - 1] + pBuf[i*width + j] * 1;
				}
				else {
					pBuf[i*width + j] = floor(fabs(float(dBuf[i*width + j]) + 0.5));
					rBuf[i*width + j] = rBuf[i*width + j - 1] - pBuf[i*width + j] * 1;
				}
			}
		}
	}
	
	
	// 写入重建YUV文件和预测误差文件 
	for (int i = 0; i < width*height / 4; i++) {
		uBuf[i] = 128;
		vBuf[i] = 128;
	}
	fwrite(rBuf, 1, width*height, newyuvFile);
	fwrite(uBuf, 1, width*height / 4, newyuvFile);
	fwrite(vBuf, 1, width*height / 4, newyuvFile);
	
	for (int i = 0; i < width*height ; i++) {
		doBuf[i] = (unsigned char)(dBuf[i])+128;
	}
	fwrite(doBuf, 1, width*height, pFile);
	fwrite(uBuf, 1, width*height / 4, pFile);
	fwrite(vBuf, 1, width*height / 4, pFile);
	
	fclose(newyuvFile);
	fclose(yuvFile);
	fclose(pFile);
	
	// 计算PSNR 
	int sum=0;
	for (int i = 0; i < height; i++) {

		for (int j = 0; j < width; j++) {
			sum += abs(pBuf[i*width + j]);
		}
	}
	float MSE = float(sum) / float(width*height);
	float PSNR = 10 * log10(65025 / MSE);
	printf("PSNR=%f", PSNR);

	return 0;
}

2.运行结果

①yuv输出图像

依次为原图像、重建图像和预测误差图像:

DPCM编码算法实现_第2张图片

 ②将预测误差文件写入Huffman编码器

在命令行窗口输入:

huff_run.exe -i Lena256B_error.yuv -o Lena_error.huff -c -t Lena_error.txt

概率分布图:

DPCM编码算法实现_第3张图片

输出txt文件:

DPCM编码算法实现_第4张图片

 ③将原文件写入Huffman编码器

在命令行输入:

huff_run.exe -i Lena256B.yuv -o Lena.huff -c -t Lena.txt

 概率分布图:

DPCM编码算法实现_第5张图片

 输出txt文件:

DPCM编码算法实现_第6张图片

 ④计算压缩比

YUV文件 编码后文件 系统 原文件大小 编码后文件大小 压缩比
Lena256B.yuv Lena.huff 仅熵编码 96KB 69KB 71.875%
Lena256B_error.yuv Lena_error.huff DPCM+熵编码 96KB 55KB 57.292%

⑤计算PSNR

DPCM编码算法实现_第7张图片

 3.结果分析

从概率分布图可以看出,预测误差图像的概率分布更集中,像素之间的关联性更高,使用霍夫曼编码进行熵编码的压缩效率更高,即更加适合这种编码方式。而原始图像的概率分布较为均匀,在进行霍夫曼编码时压缩的效率就没有那么高。
 

你可能感兴趣的:(数据压缩,算法,c++,编程语言,视频编解码)