文章目录
一、实验内容
DPCM编码,简称差值编码,是对模拟信号幅度抽样的差值进行量化编码的调制方式(抽样差值的含义请参见“增量调制”)。这种方式是用已经过去的抽样值来预测当前的抽样值,对它们的差值进行编码。
在本次实验中,我们采用固定预测器和均匀量化器。预测器采用左侧、上方预测均可。量化器采用8比特均匀量化。
本实验的目标是验证DPCM编码的编码效率。首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差,并对预测误差进行8比特均匀量化(基本要求)。还可对预测误差进行1比特、2比特和4比特的量化设计(提高要求)。
在DPCM编码器实现的过程中可同时输出预测误差图像和重建图像。将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。
二、实验原理
本实验为8bit量化,因为差值的取值范围为-255~255,所以要将差值加上255再除以2^(9-8),从而使最后得到的量化值区间在0到255之间。
如图所示:dn是预测误差,Q是量化器,P是重建图像。
psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准,PSNR值越大失真越小。
三、代码部分
1. main.c
#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
#include"DPCM.h"
using namespace std;
int main(int argc, char* argv[]) {
char* yuvaddr = argv[1];
char* yuv2addr = argv[2];
int W = atoi(argv[3]);
int H = atoi(argv[4]);
char* yuverraddr = argv[5];
int imgsize = W * H * 3 / 2;
int q = atoi(argv[6]);
unsigned char* yuvbuffer = new unsigned char[imgsize];
unsigned char* ybuffer = new unsigned char[imgsize * 2 / 3];
unsigned char* ubuffer = new unsigned char[imgsize / 6];
unsigned char* vbuffer = new unsigned char[imgsize / 6];
unsigned char* preerrbuffer = new unsigned char[imgsize * 2 / 3];
unsigned char* levelbuffer = new unsigned char[imgsize * 2 / 3];
FILE* imgopen = fopen(yuvaddr, "rb");
if (imgopen == NULL) {
cout << "打开yuv文件失败" << endl;
}
FILE* yuvsave = fopen(yuv2addr, "w");
if (yuvsave == NULL) {
cout << "创建yuv空白文件失败" << endl;
}
FILE* yuvsave2 = fopen(yuverraddr, "w");
if (yuvsave2 == NULL) {
cout << "创建yuv空白文件失败" << endl;
}
fread(yuvbuffer, sizeof(unsigned char), imgsize, imgopen);
int i;
for (i = 0; i < imgsize * 2 / 3; i++) {
ybuffer[i] = yuvbuffer[i];
}
for (i = 0; i < imgsize / 6; i++) {
ubuffer[i] = yuvbuffer[i + imgsize * 2 / 3];
}
for (i = 0; i < imgsize / 6; i++) {
vbuffer[i] = yuvbuffer[i + imgsize * 2 / 3 + imgsize / 6];
}
DpcmEn(ybuffer, preerrbuffer, levelbuffer, H, W, q);
fwrite(levelbuffer, sizeof(unsigned char), W * H, yuvsave);
fwrite(ubuffer, sizeof(unsigned char), W * H / 4, yuvsave);
fwrite(vbuffer, sizeof(unsigned char), W * H / 4, yuvsave);
for (i = 0; i < imgsize / 6; i++) {
ubuffer[i] = 128;
}
for (i = 0; i < imgsize / 6; i++) {
ubuffer[i] = 128;
}
fwrite(preerrbuffer, sizeof(unsigned char), W * H, yuvsave2);
fwrite(ubuffer, sizeof(unsigned char), W * H / 4, yuvsave2);
fwrite(vbuffer, sizeof(unsigned char), W * H / 4, yuvsave2);
PrintPSNR(ybuffer, levelbuffer, W, H);
}
2. DPCM.h
#define DPCM_H_INCLUDED
#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
using namespace std;
void DpcmEn(unsigned char* yBuff, unsigned char* preerr, unsigned char* level, int h, int w, int q) {
int prediction;
int err;
int i;
int j;
int a;
int b;
for (i = 0; i < h; i++) {
prediction = 128;
err = yBuff[i * w] - prediction;
a = (err + 128) / pow(2, 8 - q);
if (a > pow(2, q) - 1) {
a = pow(2, q) - 1;
}
if (a < 0) {
a = 0;
}
preerr[i * w] = a;
b = preerr[i * w] * pow(2, 8 - q) - 128 + prediction;
if (b > 255) {
b = 255;
}
if (b < 0) {
b = 0;
}
level[i * w] = b;
for (j = 1; j < w; j++) {
prediction = level[i * w + j - 1];
err = yBuff[i * w + j] - prediction;
a = (err + 255) / pow(2, 9 - q);
if (a > pow(2, q) - 1) {
a = pow(2, q) - 1;
}
if (a < 0) {
a = 0;
}
preerr[i * w + j] = a;
b = preerr[i * w + j] * pow(2, 9 - q) - 255 + prediction;
if (b > 255) {
b = 255;
}
if (b < 0) {
b = 0;
}
level[i * w + j] = b;
}
}
}
void PrintPSNR(unsigned char* ybuffer, unsigned char* levelbuffer, int w, int h) {
double mse;
double psnr;
double sum = 0;
double temp;
int i;
for (i = 0; i < w * h; i++) {
temp = pow((ybuffer[i] - levelbuffer[i]), 2);
sum += temp;
}
mse = sum / (w * h);
psnr = 10 * log10((pow(2, 8) - 1) * (pow(2, 8) - 1) / mse);
cout << "the psnr is: " << psnr << endl;
}
四、结果分析
1. 重建图像与误差图像
原图如下:
8bit量化的重建图片以及预测差值图片如下:
在进行 7~1bit 量化时,7bit图片没有太明显的差别,但 6bit 之后出现了块效应。且bit数越小,失真越明显。
2. PSNR
PSNR的结果如下:
量化bit数 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---|---|---|---|---|---|---|---|---|
PSNR | 51.15 | 42.72 | 35.73 | 29.24 | 23.14 | 17.65 | 11.94 | 9.96 |
可以看出,量化bit数越大,重建的图像质量越好,这与我们的常识相符。
3. 预测误差图像概率分布图
可以看到量化后的预测误差值大多集中在2的n bits次方处。
4. Huffman编码器
将原图和8bit至1bit量化输出的yuv文件输入Huffman编码器:
输出是.huff文件和.txt文件。比较生成的.huff文件的文件大小。文件大小和压缩比计算如下表所示:
文件(bit) | 原文件 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---|---|---|---|---|---|---|---|---|---|
结果(kb) | 68.2 | 46.9 | 45.2 | 37.7 | 31.3 | 26.6 | 21.9 | 19.6 | 18.3 |
压缩比 | 100.0% | 68.8% | 66.3% | 55.3% | 45.9% | 39.0% | 32.1% | 28.7% | 26.8% |
可以发现,进行了量化后的文件的压缩比随着量化比特数的减小而减小。即量化比特数越小,压缩效果越差。