DPCM编码实验报告

DPCM编解码原理

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

DPCM编码系统的设计

在本次实验中,我们采用固定预测器和均匀量化器。预测器采用左侧、上方预测均可。

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

代码

#include
using namespace std;

const char* pathin = "moon.yuv";
const char* pathout = "pic.yuv";
const char* patherror = "error.yuv";

unsigned char r,g,b;
unsigned char buffer[464*538];
unsigned char y[464*538], u[464*538], v[464*538],er[464*538];
int e[464*538];
int num;
int main()
{
	
	ifstream in(pathin, ios::binary);
	ofstream out(pathout, ios::binary);
	ofstream error(patherror, ios::binary);		
	in.read((char*)y, 464 * 538);
	in.read((char*)u, 464 * 269);
	unsigned char predictor=y[0];
	for (num=1; num < 464*538; num++)
	{
		e[num] = y[num]- predictor;
		predictor = y[num];
		if (e[num] > 128)e[num] = 128;
		if (e[num] < -128)e[num] = -128;
		er[num] = e[num] +128;
	}
	er[0] = y[0];
	e[0] = y[0];
	error.write((char*)er, 464*538);
	error.write((char*)u, 464*538/2);
	
	unsigned char recons;
	unsigned char off[464*538];
	recons = e[0];
	off[0] = e[0];
	for (num = 1; num < 464*538; num++)
	{
		off[num] = e[num] + recons;
		recons = off[num];

	}
	out.write((char*)off, 464*538);
	out.write((char*)u, 232*538);
	out.close();
	in.close();
	error.close();
	return 0;
}

本次使用的图片为moon,如下
DPCM编码实验报告_第2张图片
处理过后的残差图像如下
DPCM编码实验报告_第3张图片
恢复出的图像如下
DPCM编码实验报告_第4张图片
可见,肉眼几乎看不出来与原图的差别

分析

利用huffman编码程序对残差和原始图像进行编码,其中-i之后的是输入的文件名,-o之后的输出的文件名
DPCM编码实验报告_第5张图片
这两个是编码之后的文件
上图中的两个文件是huffman编码之后的文件
在这里插入图片描述
可以发现残差经过编码后要比原图编码后直接小了一半,与原图的压缩比达到了13.4%,而直接对原图进行huffman编码的压缩比为29.9%,DPCM对于压缩能力的提升可见一斑。

psnr

这次的图像可能比较特殊,psnr为无穷大,我认为可能是由于两个像素点之间的残差绝对值并没有大于128,导致8bit量化不存在误差。经验证后证实这一猜测。验证方法为防溢出语句改为如下形式

int c;
if(e[num]>128){e[num]=128;c++;}
if(e[num]<-128){e[num]=-128;c++;}

最后输出c即可,输出后的c确实为0。

概率分布

原图

DPCM编码实验报告_第6张图片

残差图像

DPCM编码实验报告_第7张图片
利用残差的数据也可以对之前的猜测进行验证,上图展示的为加128之后的残差,在0,255两个点上,概率都为0,说明并没有高过255或小于0的数据,即残差绝对值不大于128,也证明了验证了猜想。
在这里插入图片描述
在这里插入图片描述

恢复的图像

DPCM编码实验报告_第8张图片
可见和原图一毛一样

你可能感兴趣的:(DPCM编码实验报告)