实验四 DPCM 压缩系统的实现和分析

来源:互联网 发布:php和java的混合编程 编辑:程序博客网 时间:2024/06/08 11:56

一、实验原理

1. 预测编码

  在数字图像中,如果不是随机的噪声,那么每个像素与其周围的像素都会存在着一定的关联,像素值很大程度上依赖于其邻域中其它像素的值。也就是预测误差(在这个实验中用当前像素值与前一个像素值的差来表示)应该非常接近,通常比单个的像素值要小。因此如果只存储预测误差,由预测误差也可以重构出原图像,而且这样可以降低图像中的冗余信息,实现图像的压缩。
  如果用前面几个样值的线性组合来预测当前的样值,称为线性预测,只用前一个样值进行预测,就称为 DPCM 。

2. DPCM 编解码框图

这里写图片描述
图 1 线性预测编解码框图
  mk 为数字信号的样值,首先与预测值 m'k 相减得到其预测误差 ek ,预测误差经过量化器量化后得到量化预测误差 rkrk 除了要进行编码输出之外,还用于更新预测值,和原预测值 m'k 相加得到预测器新的输入 m*k1 。预测器的输入输出由下式决定
m'k=i=1paim*k1
式中 p 为预测阶数,ai 为预测系数。本实验中 pa 都为 1 ,也就是仅使用前一个像素值 mi1 进行预测。
  从框图中可以看出,由于需要更新预测值,编码器中已经内嵌了一个解码器。

二、实验流程及代码分析

  从框图可以看出,本实验的编码流程如下

Created with Raphaël 2.1.0当前像素值与前一个像素值(预测值)相减得到预测误差对预测误差按照指定的比特数量化得到量化预测误差量化预测误差值与前一个像素值相加更新当前的像素值,用于下一个像素的预测

  实验用图像均为 BMP 格式,使用实验二中的方法读入 BMP 图像并提取出亮度通道 Y 。在下面的代码中, Y 通道的值已经存在了 yBuf 中。另外在每一行中,由于第一个像素的前面没有像素,因此假设它的预测值为平均灰度值 128 。

//命令行参数:输入图像名、误差图像名、重建图像名、量化比特数unsigned char g(int x) //防止超过 0 到 255 的动态范围{    if (x < 0) return 0;    if (x > 255) return 255;    return x;}...int Qbits = atoi(argv[4]); // Qbits 为量化比特数...unsigned char* diffBuf = (unsigned char*)malloc(width*height); //量化预测误差存储区unsigned char* reBuf = (unsigned char*)malloc(width*height); //重建图像存储区int ek; //原始的预测误差值,范围从 -255 到 +255int scale = 512 / (1<<Qbits); //误差值的压缩比率for (i = 0; i < height; i++) //行循环{    //对每行第一个像素的处理    ek = yBuf[width*i] - 128; //假设第一个像素的预测值为128    diffBuf[width*i] = (ek + 255) / scale; //量化后的预测误差    reBuf[width*i] = g((diffBuf[width*i] - 255 / scale)*scale + 128); //根据预测误差再重建当前电平值    for (j = 1; j < width; j++) //列循环    {        //后面的像素与第一个像素处理方法一样        ek = yBuf[j + width*i] - reBuf[j - 1 + width*i];        diffBuf[j + width*i] = (ek + 255) / scale;        reBuf[j + width*i] = g((diffBuf[j + width*i] - 255 / scale)*scale + reBuf[j - 1 + width*i]);    }}

  代码很短,外层循环为图像中每一行的循环,每行起始像素的预测值设为 128,单独对其进行预测并重建。首先得到差值 ek,像素灰度值范围从 0 到 255,那么两个像素灰度值之差 ek 的范围从 -255 到 255。由于要存储误差图像,那么先把负灰度值变成正的,也就是 ek + 255,在 0 到 510 这个区间内再做量化,区间长度可以看成 9 bit,512 级。
  要将预测误差作为一幅图像显示以观察预测结果,那么最基本的要做 8 bit量化,将误差范围压缩在 0 到 255 之间,也就是误差值除以 2 下取整。 7 bit 量化,误差值要除以 4 下取整。因此定义了变量 scale 用于对误差值进行量化,量化预测误差存储到 diffBuf 中。
  最后要根据量化值重建当前像素值以用于下一个像素的预测。 误差已经量化了,因此要得到原本的误差要先乘以比率 scale 再减去 255 ,就得到了真实的量化误差。但是对比一下这样两种代码

y[i] = diff * scale - 255 + y[i - 1];y[i] = (diff - 255/scale) * scale + y[i - 1];

  对于量化比特数的不同,误差移动的范围也不同。在对误差的量化,也就是 (ek + 255) / scale 中,如果是 4 bit 量化,scale = 32,那么 ek = 0 对应 7,重建时 7×32-255 = -31,对应上面的第一种写法,重建结果不对。这种问题的原因在于端点值 255 也被量化了,由于取整的存在,重建时的正确表达式应为 (7-255/32)×32 = 0,也就是第二种写法。
  最后还要解决一个问题,就是这样做可能会超出动态范围。考虑图像不使用差分编码,直接量化:

int scale = 256 / (1 << (Qbits - 1));reBuf[j + width*i] = yBuf[j + width*i] / scale*scale;

  如果对误差图像进行量化,也就是要对 512 级灰度进行量化,而对原图像的直接量化是对 256 级灰度量化,因此如果要得到相同的灰度级数,直接量化的量化比特数要比误差的量化比特数少 1。表 1 为一个量化比特数为 3 的示例,也就是直接量化为 2 bit 量化,共有 4 级灰度。

原始图像 直接量化图像 误差量化后重建图像 预测误差 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述

表 1 直接量化与对误差量化的对比
  量化间隔为 512 / 8 = 64,灰度级均匀变化,0,1,2,…,255。第一个像素 0 的预测误差为 -128,重建后还是 0 ,但是下一个像素 1,预测误差为 1 - 0 = 1,按照上面的代码,量化误差为 (1 + 255) / 64 = 4,重建后的像素值为 (4 - 255/64) × 64 = (4 - 3) × 64 = 64,使得整幅图像比直接量化结果偏亮,按照这样的顺序,后面重建的像素值依次为 64,128,192,256,最后一个超过了 255,因此需要定义一个函数 g 对其进行限制。

三、实验结果

1. 两种方法编码效率的对比

  差分预测编码可降低图像中的冗余信息,那么对量化后的误差图像进行实验三中的 Huffman 编码可以得到比直接进行 Huffman 编码更高的压缩效率。表 2 中为几种图像的量化误差分布情况,表 3 为两种压缩方法的对比。

原始图像 量化误差图像 重建图像 误差频率分布 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述

表 2 量化误差的频率分布

原始图像 原始图像大小(KB) 直接压缩后的大小(KB) 压缩率 预测误差图像大小(KB) 预测误差压缩后的大小(KB) 压缩率 1 66 13 5.07 64 9 7.11 2 98 90 1.09 96 47 2.04 3 66 64 1.03 64 34 1.88 4 66 60 1.10 64 63 1.01 5 66 64 1.03 64 64 1.00

表 3 两种压缩编码方式的对比(图像编号与表 2 顺序一致)
  从实验结果看出,对于正常的图像,像素之间存在很强的关联性,量化误差集中在 0 附近(由于将误差从 -255 ~ 255 移动到了 0 ~ 510 再量化到 0 ~ 255,统计图中 127 位置对应原本的 0 误差),这样压缩率就比较高。而第四幅图像为随机噪声,预测误差图中误差分布零散也没有规律,基本不能使用 Huffman 编码进行压缩。第五幅图像虽然不是噪声但是两个极端灰度值 0 和 255 也是交替分布的,因此误差范围也很宽,不易压缩。

2. 不同量化比特数的对比

  上表中都是对误差进行 8 bit 量化,下面的表 4 进行了不同量化比特数之间的对比,图 1 为原始图像。

这里写图片描述
图 1 原始图像

量化比特数 量化误差图像 重建图像 误差频率分布 8 这里写图片描述 这里写图片描述 这里写图片描述 6 这里写图片描述 这里写图片描述 这里写图片描述 4 这里写图片描述 这里写图片描述 这里写图片描述 3 这里写图片描述 这里写图片描述 这里写图片描述 2 这里写图片描述 这里写图片描述 这里写图片描述

表 4 不同量化比特数的对比
  在显示量化图像时,为了能让不同量化比特数的误差图像都能正确显示,使用了这样的方法:

p[j + width*i] = diffBuf[j + width*i] * scale / 2;

  比如 4 bit 量化的误差图像,量化误差全部变换成正值后最大值为 16,那么把最大值乘以之前定义的缩放比率 scale(512 / 2^n),这里是 32 ,再除以 2 之后就变到了 0 ~ 255 区间内。量化比特数越少,误差 0 对应的灰度值就越小,4 bit 量化时误差 0 对应量化值 7,在误差图像中为 7 × 16 = 112,而 8 bit量化时误差 0 对应量化值 127,在误差图像中也为 127,因此表格中从上到下误差图像会越来越暗。

0 0
原创粉丝点击