【数据压缩7】Lab4 DPCM压缩系统的实现和分析

本文介绍了如何实现DPCM压缩系统,包括量化器、DPCM编解码原理、编码器设计以及PSNR评估。实验通过对比不同量化比特数和压缩系统,探讨了图像质量和压缩效率的关系,以及预测编码在提高压缩性能中的作用。
摘要由CSDN通过智能技术生成

【数据压缩7】Lab4 DPCM压缩系统的实现和分析

一、实验项目名称

DPCM 压缩系统的实现和分析

二、实验目的

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

三、主要设备

安装 Windows 和 Visual Studio 等编程平台的个人计算机

四、实验内容和原理

1. 量化器

在这里插入图片描述
**量化:**用一个很小的集合表示一个大集合。

描述:
1. 量 化 区 间 的 数 目 : M = 2 n 2. 量 化 区 间 的 索 引 : i 3. 决 策 边 界 : b i 4. 重 构 水 平 : y i = b i + b i − 1 2 5. 量 化 间 隔 ( 步 长 ) : Δ = 2 ∗ X m a x M , 信 源 的 取 值 范 围 [ − X m a x , X m a x ] 6. 量 化 失 真 的 度 量 : e ( x ) = x − x ′ 1.量化区间的数目:M=2^n\\ 2.量化区间的索引:i\\ 3.决策边界:b_i\\ 4.重构水平:y_i=\frac {b_i+b_{i-1}} 2\\ 5.量化间隔(步长):\Delta=\frac {2*X_{max}} M ,信源的取值范围[-X_{max},X_{max}]\\ 6. 量化失真的度量:e(x)=x-x' 1.M=2n2.i3.bi4.yi=2bi+bi15.()Δ=M2Xmax[Xmax,Xmax]6.e(x)=xx

2. DPCM编解码原理

DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。
在这里插入图片描述
本实验中,DPCM对当前值和预测值的差值(预测误差)进行量化,预测误差值的范围为[-255,255],因此用9bit表示且需要单极性化(+255)。残差值的量化映射方法是除以量化间隔再取整,这种量化方法相当于每次取下电平。

3. DPCM编码系统的设计

本实验的目标是验证DPCM编码的编码效率。在本次实验中,我们采用:

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

4. 压缩质量客观评价(PSNR)

通常用来评价一幅图像压缩后和原图像相比质量的好坏,压缩后图像一定会比原图像质量差的,PSNR越高,压缩后失真越小。这里主要定义了两个值,一个是均方差MSE,另一个是峰值信噪比PSNR(dB),这里的MAX通常是图像的灰度级,一般就是255。

img
img

PSNR值评价
高于40dB:说明图像质量极好(即非常接近原始图像)
30—40dB:通常表示图像质量是好的(即失真可以察觉但可以接受)
20—30dB:说明图像质量差

五、实验步骤

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

1. 主函数

  1. 设置文件参数
  2. 开辟缓冲区
  3. 打开文件(输入文件和输出文件)
  4. 左向差分预测编码,计算压缩质量
  5. 统计残差的概率分布(matlab画图)
  6. 结果写入
  7. 释放缓冲区,关闭文件
int main()
{
	// 1. 文件参数
	const int width = 256; 
	const int height = 256;
	int bitdepth = 8;//量化比特数
    
	// 2. 缓冲区
	unsigned char* ybuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height); // 原图
	unsigned char* ubuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height * 0.25); //4:2:0
	unsigned char* vbuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height * 0.25);
	unsigned char* ebuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height); // 预测误差图像
	unsigned char* rebuf = (unsigned char*)malloc(sizeof(unsigned char) * width * height); // 重建图像
	
	double* freq_y = (double*)malloc(sizeof(double) * 256);// 原图概率分布
	double* freq_e= (double*)malloc(sizeof(double) * 256);// 残差图概率分布

	// 3. 定义文件指针,打开文件
    // input
	FILE* yuv = fopen("lena.yuv", "rb");// 打开原图
	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);
    
    // output
    FILE* qyuv = fopen("lena_q.yuv", "wb");// 预测误差图像
	FILE* reyuv = fopen("lena_re.yuv", "wb");// 重建图像
	FILE* efile = fopen("e.txt", "w"); // 残差图概率分布
	FILE* yfile = fopen("y.txt", "w");// 原图概率分布
	
    // 4. 左向差分预测编码,计算压缩质量
	Left_DPCM(ybuf, ebuf, rebuf, width, height, bitdepth);

	PSNR(ybuf, rebuf, height, width, bitdepth);
	
	// 5. 统计概率分布
	int cout_y[256] = { 0 };
	int cout_e[256] = { 0 };
	for (int i = 0; i < width * height; i++){
		cout_y[ybuf[i]]++;
		freq_y[ybuf[i]] = double(cout_y[ybuf[i]]) / (width * height);// 原图概率分布
	}
	for (int i = 0; i < width * height; i++) {
		cout_e[ebuf[i]]++;
		freq_e[ebuf[i]] = double(cout_e[ebuf[i]]) / (width * height);// 残差图概率分布
	}
	
	// 6. 结果写入
	fwrite(ebuf, 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);

	for (int i = 0; i < 256; i++){  // 概率分布
		fprintf(yfile, "%f\n",freq_y[i]);
		fprintf(efile, "%f\n", freq_e[i]);
	}

	// 7. 释放缓冲区,关闭文件
	free(ybuf); free(ubuf); free(vbuf);free(ebuf); free(rebuf);
	fclose(yuv);fclose(qyuv);fclose(reyuv);fclose(efile);fclose(yfile);
}

2. DPCM左向预测函数

采用左向预测的方法,第一列像素的误差值设为128。输入原图指针,残差图指针,重建图指针,宽,高,量化比特数。

残差图:当前值 - 前一个像素的重建值
e ( n ) = y ( n ) − r e ( n − 1 ) e ^ ( n ) = e ( n ) + 255 Δ ∗ 0.5 Δ e(n)=y(n)-re(n-1)\\ \hat e(n)=\frac {e(n)+255} \Delta *0.5\Delta e(n)=y(n)re(n1)e^(n)=Δe(n)+2550.5Δ
重建图:预测误差值 + 前一个像素的重建值
r e ( n ) = e ^ ( n ) + r e ( n − 1 ) re(n)=\hat e(n)+re(n-1) re(n)=e^(n)+re(n1)

void DPCM(unsigned char* ybuf, unsigned char* ebuf, unsigned char* rebuf, int width, int height, int bitNum)
{
	int quantized_interval = 512 / pow(2, bitNum);// 量化间隔
	int error; // 差值
	int rebuild_value;// 重建值

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++)
		{
			if (j == 0) { //第一列
				error = ybuf[width * i + j] - 128;
				ebuf[width * i + j] = int((error + 255) / quantized_interval) * quantized_interval / 2;
				rebuild_value = (ebuf[width * i + j] * 2) - 255 + 128;
			}
			else {
				error = ybuf[width * i + j] - rebuf[width * i + j - 1];
				ebuf[width * i + j] = int((error + 255) / quantized_interval) * quantized_interval / 2;
				rebuild_value = (ebuf[width * i + j] * 2) - 255 + rebuf[j - 1 + width * i];
			}

			if (rebuild_value > 255)
				rebuild_value = 255;
			if (rebuild_value < 0)
				rebuild_value = 0;

			rebuf[width * i + j] = rebuild_value;
			
		}
	}
}

3. PSNR峰值信噪比函数

先计算量化的均方误差 MSE ,再计算PSNR。

int PSNR(unsigned char* ybuf, unsigned char* rebuf, int height, int width, int dep)
{
	double max = 255;
	double mse = 0;
	double psnr;

	for (int i = 0; i < height; i++)
		for (int j = 0; j < width; j++){
			mse += (ybuf[i * width + j] - rebuf[i * width + j]) * (ybuf[i * width + j] - rebuf[i * width + j]);
		}
	mse = mse / (double)(width * height);
	psnr = 10 * log10((double)(max * max) / mse);
	cout << dep << "比特量化时PSNR = " << psnr << endl;

	return 0;
}

4. Huffman熵编码

准备:在这里插入图片描述
transfer.bat文件内容如下:

huff_run.exe -i lena.yuv -o lena.huff -c -t lena.txt
huff_run.exe -i lena_e8.yuv -o lena_e8.huff -c -t lena_e8.txt
huff_run.exe -i lena_e4.yuv -o lena_e4.huff -c -t lena_e4.txt
huff_run.exe -i lena_e2.yuv -o lena_e2.huff -c -t lena_e2.txt

熵编码结果:
在这里插入图片描述

六、实验结果

1. 图像质量

原图:

在这里插入图片描述

熵编码是无损编码,图片质量最好;量化比特数越高,压缩后的图片质量越高。即:熵编码>8bit DPCM+熵编码>4bit DPCM+熵编码>2bit DPCM+熵编码。
在这里插入图片描述

2. 压缩比

压缩比=输入/输出,压缩比越高说明压缩效率越高。

熵编码是无损编码,压缩效率比较低;量化比特数越低,压缩效率越高。即:熵编码<8bit DPCM+熵编码<4bit DPCM+熵编码<2bit DPCM+熵编码。

熵编码输入图像灰度的概率分布图压缩比
仅进行熵编码在这里插入图片描述1.39
8bit DPCM+熵编码在这里插入图片描述2.09
4bit DPCM+熵编码在这里插入图片描述4.36
2bit DPCM+熵编码在这里插入图片描述5.33

3. 结论

(1)量化区间数目的对比

根据重建图像主客观评价,量化区间数目(量化比特数)越小,图像失真越明显;根据概率分布图,量化区间数目(量化比特数)越小,压缩效率越高。量化器是失真和码率的折中,需要8bit及其以上的量化器才能保证图像质量。

颗粒噪声:平坦区域的随机噪声。出现在灰度值变化慢的区域。

斜率过载:边缘模糊。出现在灰度值变化快的区域,量化比特数越小越明显。

(2)压缩系统的对比
  • 对比两种压缩系统,仅有熵编码的压缩比远不如DPCM+熵编码的压缩比。

  • 先预测编码再无失真编码的原因:对于无失真编码来讲(Huffman编码),根据香农第一定理(无失真变长信源编码定理),信源熵决定平均码长的下界,即输入信源熵越小,平均码长越可能小,压缩效率越高。

    如果使信源熵变小,就需要概率分布不均匀。利用信号之间的相关性(差分预测编码)或者去除信号的相关性(变化编码),即可将均匀分布的信号转化为不均匀的信号。

  • 和实际信号的分布相比,预测误差是关于0的高尖峰。因此,预测误差具有比原始密度更小的熵。这意味着预测的过程把样值间的大部分冗余去掉了。

综上所述,无失真编码之前进行预测编码,能够提高系统性能;而且量化误差合适的情况下,可以几乎不引起失真。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值