一、实验目的
掌握DPCM编解码系统的基本原理。初步掌握实验用C++语言编程实现DPCM编码器,并分析其压缩效率。
二、实验原理
(一)DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。
在一个DPCM系统中需要设计两个部分
➢ 预测器
➢ 量化器
◼ 理想情况下,应同时优化预测器和量化器,但实际应用中,采用一种次优化方法
➢ 在这种方法中,量化电平数必须足够大(M>=8)才能获得好的性能
本次实验采用固定预测器和均匀量化器。
预测器采用左侧预测。
量化器采用8比特均匀量化器。
在本次实验中,我们采用固定预测器和均匀量化器。预测器采用左侧、上方预测均可 (本实验采用的时左侧编码) 。量化器采用8比特均匀量化。本实验的目标是验证DPCM编码的编码效率。首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差,并对预测误差进行8比特均匀量化,还可对预测误差进行1比特、2比特和4比特的量化设计。
在DPCM编码器实现的过程中可同时输出预测误差图像(通过延时器)和重建图像(预测误差图像反量化再加上左侧重建值)。将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。最后比较两种系统 (1.DPCM+熵编码 2.仅进行熵编码) 之间的编码效率 (压缩比和图像质量)。压缩质量以Psnr 进行计算。
(二)PSNR原理
一般来说
PSNR>40dB:图像质量非常好(非常接近原始图像)
30<PSNR<40dB:图像质量是好的(失真可以察觉但可以接受)
20<PSNR<30dB:图像质量差
PSNR<20:图像不可接受
本实验熵编码使用的是Huffman编码,工具为老师提供的可执行文件huffcode.exe
输入原文件和DPCM编码后输出的error文件,即可判断DPCM+熵编码和只进行熵编码两种方案的优劣,压缩比由.huff文件大小比上原.yuv文件大小。
三.实验过程(代码实现)
实验总体思路:
(1)开辟缓冲区,读取一个yuv文件,计算Y分量的概率分布;
(2)用dpcm函数将Y分量进行DPCM变换,得出预测误差图像并反量化误差加上左侧重建值得到重建图像并输出,DPCM编码后传输的是误差图像,将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比
(3)计算psnr,判断压缩质量;
(4)比较原始图像和不同量化比特数下的预测误差图像的压缩比、psnr的值。
(5)得出实验结论
关键代码部分
DPCM编码部分:
本次实验采用左侧编码的方法,先将原图像第一列的值赋给重建图像第一列,误差值都赋为0,从第二列开始,将该点原图数值与左侧重建值相减之后再进行量化,得到要传输的误差值,再进行反量化,将恢复后的误差值再与左侧重建值相加,(与原样本已不同)得该点重建值;
代码如下:
unsigned char * DpcmCoder(unsigned char buffer[], int bit)
{
int temp;
unsigned char pre[w*h] = { 0 }, d[w*h] = { 0 }, Q_d[w*h] = { 0 };
for (int line = 0; line < h; line++)
{
pre[line*w] = buffer[line*w];
Q_d[line*w] = Quantify(0, bit);
for (int i = 1; i < w; i++)
{
temp = buffer[i + line * w] - pre[i + line * w - 1];
//temp = d[i + line * w];//原始差值
temp = Quantify(temp, bit);//差值量化
Q_d[i + line * w] = temp;
temp = Re_Quantify(temp);//反量化
temp = pre[i + line * w - 1] + temp;
if (temp > 255)
temp = 255;
if (temp < 0)
temp = 0;
pre[i + line * w] = temp;
}
}
//将差值图像和重建图像传回
unsigned char ret[w*h * 2] = { 0 };
for (int i = 0; i < w*h ; i++)
{
ret[i] = Q_d[i];
}
for (int i = 0; i < w*h; i++)
{
ret[i + w * h] = pre[i];
}
return ret;
}
量化:在DPCM编码过程中要实现量化和反量化这两个过程,不同的量化比特数会产生不同的压缩效果(量化比特数越小,压缩比越大,压缩质量越差);
本实验中对误差值(也就是最后传输的数据)进行量化后输出,同时对其进行反量化,将复原后``某点的数值与该点左侧的重建值相加,得该点重建值;
//量化
int Quantify(int temp, int bit)
{
temp = (temp + 255) / 2;
temp = floor(temp / pow(2, 8 - bit));
temp = temp * pow(2, 8 - bit);
if (temp > 255)
temp = 255;
if (temp < 0)
temp = 0;
return temp;
}
//反量化
int Re_Quantify(int temp)
{
temp = temp * 2 - 255;
return temp;
}
PSNR函数
double PSNR(unsigned char* YOrigi, unsigned char* YRestr, int height, int width)
{
int fmax = pow(2, 8) - 1;
int a = fmax * fmax;
double mean_se = MSE(YOrigi, YRestr, height, width);
double peak_SNR = 10 * log10((double)a / mean_se);
return peak_SNR;
}
MSE函数:
double MSE(unsigned char* YOrigi, unsigned char* YRestr, int height, int width)
{
int size = height * width;
long long int sum = 0;
double mean;
for (int i = 0; i < size; i++)
{
long long int temp = (long long int)(YOrigi[i] - YRestr[i]) * (long long int)(YOrigi[i] - YRestr[i]);
sum += temp;
}
mean = (double)sum / (double)size;
return mean;
}
四.实验结果
(一)量化比特数越小,图像质量越差。
量化比特数 | 预测误差图像 |
---|---|
8bit | |
4bit | |
2bit | |
1bit | |
重建图像质量总高到低依次减小
PSNR值:
由上可知,8bit量化图像质量最高,4bit量化时已出现块效应,越往下越差。
(二)Huffman熵编码结果
发现比特数越小,压缩比越低,但通过DPCM+熵编码后的图像压缩比总体比原始图像未经过DPCM编码就熵编码的压缩比低。
通过控制合理的量化比特数可以使压缩比低的情况下保证人眼看到的图像质量。