DPCM压缩系统的实现和分析
实验目的
掌握DPCM编解码系统的基本原理。初步掌握实验用C/C++/Python等语言编程实现DPCM编码器,并分析其压缩效率。
实验要求
验证DPCM编码的编码效率。首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差,并对预测误差进行8比特均匀量化(基本要求)。还可对预测误差进行1比特、2比特和4比特的量化设计(提高要求)。
DPCM编解码原理
DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。
DPCM编码系统的设计
在本次实验中,我们采用固定预测器和均匀量化器。预测器采用左侧、上方预测均可。 量化器采用8比特均匀量化。在DPCM编码器实现的过程中可同时输出预测误差图像和重建图像。将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。
实验过程
1.使用图像转换器把BMP文件转换为YUV文件。
2.读取一个256级的灰度图像YUV,提取Y的数据
3.分配缓冲区,存储数据
4.对该灰度图像进行预测,计算预测误差
5.对预测误差进行8bit均匀量化
6.对量化后的预测误差进行反量化,求重建值
7.将预测误差图像写入文件并输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。
8.将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。
9.比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。
实验代码
(1)DPCM.h
void DPCMLeft(int Width,int Height,void *yBuff,void *recBuff,void *errBuff);
int simplest_yuv420_psnr(void *yBuff1,void *yBuff2, int w, int h, int num);
(2)DPCM.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <string.h>
#include"DPCM.h"
//向左预测//
void DPCMLeft(int Width,int Height,void *yBuff,void *recBuff,void *errBuff)//DPCM向左预测
{
unsigned char *yB=NULL;
yB = (unsigned char *)yBuff;
unsigned char *recB=NULL;
recB = (unsigned char *)recBuff;
unsigned char *errB=NULL;
errB = (unsigned char *)errBuff;
int P1,P2;//P1为当前值与预测值的误差,P2为量化后的误差
unsigned char P3;//P3为反量化后的误差
for(int i=0;i<Height;i++)
{
for(int j=0;j<Width;j++)
{
if(j == 0)//向左进行预测时,图像最左边一列的像素值直接输出,无需进行差分预测
{
*(recB+j+i*Width)=*(yB+j+i*Width);//当前值即为重建值,作为下一个像素的参考值
*(errB+j+i*Width)=0;//误差为0
}
else//当不是最左边一列的像素时,进行DPCM
{
P1=*(yB+j+i*Width)-*(recB+(j-1)+i*Width);//求当前值与参考值的差值
if(P1%2==0)//对差值进行8bit均匀量化,并进行+128的偏移以输出
P2=P1/2+128;
else
P2=(P1-1)/2+128;
*(errB+j+i*Width)=unsigned char(P2);//将误差写入errB缓存区域
P3=unsigned char(P2*2);//对量化后的误差反量化
*(recB+j+i*Width)=*(recB+(j-1)+i*Width)+P3;
//将参考值与反量化得到的误差相加,作为当前像素的重建值,即下一个像素的参考值
}
}
}
}
//PSNR//
int simplest_yuv420_psnr(void *yBuff1,void *yBuff2, int w, int h, int num)//计算Y分量的PSNR
{
unsigned char *yB1=NULL;
yB1 = (unsigned char *)yBuff1;
unsigned char *yB2=NULL;
yB2 = (unsigned char *)yBuff2;
for (int i = 0; i < num; i++)
{
double mse_sum = 0, mse = 0, psnr = 0;
for (int j = 0; j < h ; j++)
{
for (int k = 0; k < w; k++)
{
mse_sum += pow((double)(*(yB1+k+j*w) - *(yB2+k+j*w)), 2);//取每个差值的平方,并进行累加
}
}
mse = mse_sum / (w * h); //根据公式计算mse
psnr = 10 * log10(255.0 * 255.0 / mse); //根据公式计算psnr
printf("%5.3f\n", psnr);
}
system("pause");
return 0;
}
实验结果
原图像
预测误差图像
重建图像
概率分布图
结果分析
对-255~255范围的9bit预测误差做8bit量化,量化误差很小,因此中间一列的重建图像与左边一列的原始图像没有明显差别,量化误差可忽略不计。预测误差图像的概率分布更集中, 图像像素之间相关性较强,原始图像概率分布较为均匀,预测压缩比较高,预测误差编码比直接编码效果好