DPCM压缩编码原理及C++实现

DPCM基本原理

DPCM(差分脉冲编码调制)是一种典型的预测编码系统。在传输图像、视频数据的时候,相邻的像素点的值往往差别很小,在空间上存在很大的冗余,DPCM便是利用这种冗余,通过相邻像素对当前像素的值进行预测,对图像进行数据压缩。
DPCM编解码原理图示:DPCM压缩编码原理及C++实现_第1张图片

量化:

DPCM当前像素和预测像素相减得误差值进行量化,以8bit量化为例,误差值的范围在【-255,255】之间,所需要的容量为9bit。
将值为负的像素进行单极性化,即加255,故Nbit量化便为加255再除以2^(9-n)。重建图像时,将差值和预测值相加即可得到。

PSNR:

为对重建图像进行性能评价,引入PSNR(峰值信噪比)的概念。
PSNR的计算公式:
DPCM压缩编码原理及C++实现_第2张图片
其中MSE为图像的均方误差:
在这里插入图片描述
其中M为图像的长x高,ym与y^m分别为原始图像和重建图像在相应位置的像素值。
经过PSNR的计算便能够对图像质量进行评判。

C++ 代码:

实验以左侧像素为参考值,对第一列像素的误差值设为128处理,得到输出码流、给出概率分布图并计算压缩比。

#include
#include
#include
#pragma warning(disable:4996);

void dpcm_encode(unsigned char*ybuf, unsigned char*qbuf, unsigned char*rebuf, int width, int height,int bitdepth)
{
	for (int i = 0; i < height; i++)
	{
		qbuf[i*width] = (ybuf[i*width] - 128 + 255) / pow(2, (9 - bitdepth));
		rebuf[i*width] = qbuf[i*width] * pow(2, (9 - bitdepth))+255 - 128;
	}
	for (int i = 0; i < width; i++)
	{
		for (int j = 1; j < height; j++)
		{
			qbuf[i*width+j] = (ybuf[i*width+j] - rebuf[i*width + j-1] + 255) / pow(2, (9 - bitdepth));
			rebuf[i*width+j] = qbuf[i*width+j] * pow(2, (9 - bitdepth)) - 255 + rebuf[i*width + j - 1];
		}
	}
	for (int i = 0; i < width*height; i++)
	{
		if (qbuf[i] > 255)
			qbuf[i] = 255;
		if (qbuf[i] < 0 )
			qbuf[i] = 0;
		if (rebuf[i] > 255)
			rebuf[i] = 255;
		if (rebuf[i] < 0)
			rebuf[i] = 0;
	}
}

int main()
{
	FILE *yuv = NULL; FILE *qyuv = NULL; FILE *reyuv = NULL;
	const int width = 256; const int height = 256;
	if (!(yuv = fopen("lena.yuv", "rb")))
	{
		printf("open file error!");
		exit(-1);
	}
	else
	{
		printf("open file success");
	}
	if (!(qyuv = fopen("lena_q.yuv", "wb")))
	{
		printf("open file error!");
		exit(-1);
	}
	else
	{
		printf("open file success");
	}
	if (!(reyuv = fopen("lena_re.yuv", "wb")))
	{
		printf("open file error!");
		exit(-1);
	}
	else
	{
		printf("open file success");
	}
	unsigned char *ybuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height);

	unsigned char *ubuf= (unsigned char*)malloc(sizeof(unsigned char) * width * height*0.25);

	unsigned char *vbuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height*0.25);

	unsigned char *qbuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height);

	unsigned char *rebuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
	fread(ybuf, sizeof(unsigned char), width* height, yuv);
	fread(ubuf, sizeof(unsigned char), width* height*0.25, yuv);
	fread(vbuf, sizeof(unsigned char), width* height*0.25, yuv);
    
	int bitdepth = 8;
	dpcm_encode(ybuf, qbuf, rebuf,  width, height, bitdepth);

	double freq_q[256] = { 0 };double freq_lena[256] = { 0 };
	for (int i = 0; i < 256; i++)

	{
		freq_q[i] = double(qbuf[i]) / (width*height);

		freq_lena[i] = double(ybuf[i]) / (width*height);

	}
	
	FILE *qfile; FILE *lenafile;
	if ((qfile = fopen("q.txt", "w")) == NULL)

		printf("fail\n");

	else

		printf("success\n");

	if ((lenafile = fopen("lena.txt", "w")) == NULL)

		printf("fail\n");

	else

		printf("success\n");
	char s[] = "symbol\frequency\n";
	fprintf(qfile, s); fprintf(lenafile, s); 
	for (int i = 0; i < 256; i++)

	{
		fprintf(qfile, "%d\t%f\n", i, freq_q[i]);
		fprintf(lenafile, "%d\t%f\n", i, freq_lena[i]);

	}
	

	fwrite(qbuf, sizeof(unsigned char), width * height, qyuv);
	fwrite(ubuf, sizeof(unsigned char), width * height*0.25, qyuv);
	fwrite(vbuf, sizeof(unsigned char), width * height*0.25, qyuv);
	fwrite(rebuf, sizeof(unsigned char), width * height, reyuv);
	fwrite(ubuf, sizeof(unsigned char), width * height*0.25, reyuv);
	fwrite(vbuf, sizeof(unsigned char), width * height*0.25, reyuv);
	free(ybuf); free(ubuf); free(vbuf);
	free(qbuf); free(rebuf);
	fclose(yuv);
	fclose(qyuv);
	fclose(reyuv);
	fclose(qfile);
	fclose(lenafile);
}

实验结果如图,从左至右分别为原始图像、8bit量化预测误差图像、重建图像:
DPCM压缩编码原理及C++实现_第3张图片
原始图像和误差值图像的概率分布图如下:
DPCM压缩编码原理及C++实现_第4张图片

接着进行6bit、4bit、2bit量化的对比:

DPCM压缩编码原理及C++实现_第5张图片DPCM压缩编码原理及C++实现_第6张图片DPCM压缩编码原理及C++实现_第7张图片

可以看出,4bit以上量化时,图像没有出现明显的失真现象;4bit量化时,重建图像的失真现象可以分辨;在2bit量化时,图像的失真已经让人难以忍受。

对8bit、6bit、4bit、2bit的图像进行PSNR计算得到

量化比特数 8 6 4 2
PSNR(db) 51.12 35.04 18.23 11.64

PSNR的值越小,则图像的质量越差,和我们肉眼的观感相吻合。

编码效率比较

在DPCM编码器实现的过程中可同时输出预测误差图像和重建图像。

  1. 将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。
  2. 将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。

最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率。

使用已有的Huffman编码器,在命令界面输入huffcode-i lena.yuv-o lena.huff-c>encode.txt

DPCM压缩编码原理及C++实现_第8张图片
结果表明经过DPCM编码的图像进行熵编码后比原始图像的压缩比有明显的提升。

你可能感兴趣的:(数据压缩,c++)