一.实验设备
安装 Windows 和 Visual Studio 等编程平台的个人计算机。
二.实验目的
掌握DPCM编解码系统的基本原理。初步掌握实验用C/C++/Python等语言编程实现DPCM
编码器,并分析其压缩效率。
三.实验内容
1.实验原理
1.1 DPCM系统:
xn是输入信号,x^n是重建信号,作为预测器确定下一个信号估计值的输入信号。pn是预测语音信号,dn是预测误差信号,dn=xn-pn。DPCM系统对差值信号dn进行量化编码,用来补偿过去编码中产生的量化误差,它是一个反馈系统,采用这种结构可以避免量化误差的积累。d^n是量化后的差值信号。最后将量化后的差值信号送入编码器编码。有趣的是,该系统内嵌了一个解码器如右上图所示。
1.2 什么是PSRN?
2.具体实现
2.1 代码实现
开辟三个buffer分别用来存放原始图像数据,量化后的预测图像数据,重建图像数据。
qFile = fopen(qFileName, "wb");
reFile = fopen(reFileName, "wb");
qBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
reBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
fillBuf = (u_int8_t*)malloc(frameWidth * frameHeight/2);
fread(yBuf, 1, frameWidth * frameHeight, yuvFile);
调用函数进行量化:
DPCM(frameHeight, frameWidth, yBuf, qBuf, reBuf);
void DPCM(short int height, short int width, unsigned char* yuvBuf, unsigned char* qBuf, unsigned char* reBuf)
{
int size = width * height;
for (int i = 0; i < size; i++) {
if (i % width == 0) { //判断是否是每行第一个像素
qBuf[i] = yuvBuf[i];
reBuf[i] = yuvBuf[i];
}
else {
int dn = yuvBuf[i] - reBuf[i - 1];// dn的范围是-255 — 255
//8比特量化,为0-255
dn >>= 1;//-127 - 127
int temp = dn + 128;//0 - 255
qBuf[i] = temp;
reBuf[i] = qBuf[i] * 2 + reBuf[i - 1];
}
}
}
在此基础上实现1比特,2比特,4比特量化:
/*
//4比特量化
for (int i = 0; i < size; i++) {
if (i % width == 0) { //判断是否是每行第一个像素
int k = 256 / pow(2, 4);
qBuf[i] = int(yuvBuf[i] / k);
reBuf[i] = int(yuvBuf[i] / k);
}
else {
int dn = yuvBuf[i] - reBuf[i - 1];// dn的范围是-255 — 255
//4比特量化
dn >>= 5;//-7 - 7
int temp = dn + 8;//0 - 15
qBuf[i] = temp;
reBuf[i] = qBuf[i] * 16 + reBuf[i - 1];
}
}
}
//2比特量化
for (int i = 0; i < size; i++) {
if (i % width == 0) { //判断是否是每行第一个像素
int k = 256 / pow(2, 6);
qBuf[i] = int(yuvBuf[i] / k);
reBuf[i] = int(yuvBuf[i] / k);
}
else {
int dn = yuvBuf[i] - reBuf[i - 1];// dn的范围是-255 — 255
//2比特量化
dn >>= 7;//-1 - 1
int temp = dn + 2;//0 - 3
qBuf[i] = temp;
reBuf[i] = qBuf[i] * 64 + reBuf[i - 1];
}
}
}
//1比特量化
for (int i = 0; i < size; i++) {
if (i % width == 0) { //判断是否是每行第一个像素
int k = 256 / pow(2, 7);
qBuf[i] = int(yuvBuf[i] / k);
reBuf[i] = int(yuvBuf[i] / k);
}
else {
int dn = yuvBuf[i] - reBuf[i - 1];// dn的范围是-255 — 255
//1比特量化
dn >>=8;
int temp = dn + 1;
qBuf[i] = temp;
reBuf[i] = qBuf[i] * 128 + reBuf[i - 1];
}
}
}
*/
2.2 实验结果展示:
先将选用的RGB图像转为YUV图像再进行后续实验:
原图 | 预测图像 | 重建图像 | |
8比特 | |||
4比特 | |||
2比特 | |||
1比特 |
从结果可以看出,8比特量化完全可以重建图像,随着量化比特数的减少,重建图像效果越来越差。
3.PSNR的计算
根据计算公式编写代码可求得,代码一并提交邮箱:
double thepsnr(unsigned char* buf1, unsigned char* buf2)
{
double mse = 0;
double div = 0;
double psnr = 0;
int width = 768;
int height = 512;
int k = width * height;
for (int i = 0; i < k; i++)
{
div = buf1[i] - buf2[i];
mse += div * div;
}
mse = mse / (width * height);
psnr = 10 * log10(255 * 255 / mse);
return psnr;
}
统计计算所得实验结果为:
图像 | PSNR |
1比特量化 | 8.708083 |
2比特量化 | 6.655150 |
4比特量化 | 7.568289 |
8比特量化 | 51.155397 |
4.比较编码效率
使用huffman编码器进行压缩,比较DPCM+熵编码和只用熵编码的效率:
使用matlab 绘制概率分布图:
原图 | 1比特量化 | 2比特量化 | 4比特量化 | 8比特量化 |
统计结果:
方式 | 压缩比 |
仅进行熵编码压缩比 | 28.125% |
1比特量化+熵编码压缩比 | 81.076% |
2比特量化+熵编码压缩比 | 71.875% |
4比特量化+熵编码压缩比 | 62.326% |
8比特量化+熵编码压缩比 | 67.708% |
四.实验总结与分析
1.根据实验结果可以看出,DPCM+熵编码的压缩效率明显更好,能达到更高的压缩率,而从PSNR可知8比特量化图像效果最好,在利用DPCM进行预测编码时,空间冗余越大,压缩效率越高。
2.注意算法中的先算出量化间隔再取整是下取整,不会导致溢出。