DPCM编码

DPCM编码

原理

在这里插入图片描述
DPCM即差分预测编码调制。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。

预测器与量化器设计

在本次实验中,采用了固定预测器和均匀量化器。预测器采用了左侧一个像素预测。
量化器采用8比特的均匀量化。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
int main(int argc, char** argv)
{
	unsigned __int32 width = 256;
	unsigned __int32 height = 256;
	//创建数组,申请内存,读取文件
	char *yuvname = NULL;
	char *newyuvname = NULL;
	FILE* yuvFile = NULL;
	FILE* newyuvFile = NULL;
	char *pname = NULL;
	FILE* pFile = NULL;
	yuvname = argv[1];
	newyuvname = argv[2];
	pname= argv[3];
	yuvFile = fopen(yuvname, "rb");
	if (!yuvFile)
		printf("open yuv fail");
	else
		printf("open yuv success\n");
	newyuvFile = fopen(newyuvname, "wb");
	if (!newyuvFile)
		printf("open rgb fail");
	else
		printf("create rgb success\n");
	pFile = fopen(pname, "wb");
	if (!pFile)
		printf("open p fail");
	else
		printf("create p success\n");
	//建立缓冲区准备读取数组
	unsigned char* yuvBuf = NULL;
	unsigned char* uBuf = NULL;
	unsigned char* vBuf = NULL;
    unsigned char * pBuf = NULL;
	float* dBuf = NULL;
	unsigned char* rBuf = NULL;
	yuvBuf = (unsigned char*)malloc(width*height);
	uBuf = (unsigned char*)malloc(width*height / 4);
	vBuf = (unsigned char*)malloc(width*height / 4);
	pBuf = (unsigned char*)malloc(width*height);//预测误差的量化值
	rBuf = (unsigned char*)malloc(width*height);//重现图像
	dBuf = (float*)malloc(width*height*4);//输入预测误差
	unsigned char* doBuf = (unsigned char*)malloc(width*height * 4);
	if (yuvBuf == NULL || uBuf == NULL || vBuf == NULL || pBuf == NULL)
	{
		printf("ASK MEMORY FAIL");

	}

	fread(yuvBuf, 1, width * height * 1, yuvFile);

	for (int i = 0; i < height; i++) {

		for (int j = 0; j < width; j++) {
			if (j == 0) {
				pBuf[i*width + j] = 0;
				rBuf[i*width + j] = yuvBuf[i*width + j];
				dBuf[i*width + j] = 0;
			}
			else {
				dBuf[(i*width + j)] = float(yuvBuf[i*width + j]) - float(rBuf[i*width + j - 1]);
				if (dBuf[ (i*width + j)] >= 0) {
					pBuf[i*width + j] = floor(dBuf[(i*width + j)] + 0.5);
					rBuf[i*width + j] = rBuf[i*width + j - 1] + pBuf[i*width + j] * 1;
				}
				else {
					pBuf[i*width + j] = floor(fabs(float(dBuf[i*width + j]) + 0.5));
					rBuf[i*width + j] = rBuf[i*width + j - 1] - pBuf[i*width + j] * 1;
				}
			}

		}
	}
		for (int i = 0; i < width*height / 4; i++) {
			uBuf[i] = 128;
			vBuf[i] = 128;
		}
		fwrite(rBuf, 1, width*height, newyuvFile);
		fwrite(uBuf, 1, width*height / 4, newyuvFile);
		fwrite(vBuf, 1, width*height / 4, newyuvFile);
		for (int i = 0; i < width*height ; i++) {
			doBuf[i] = unsigned char(dBuf[i])+128;
		}
		fwrite(doBuf, 1, width*height, pFile);
		fwrite(uBuf, 1, width*height / 4, pFile);
		fwrite(vBuf, 1, width*height / 4, pFile);
		fclose(newyuvFile);
		fclose(yuvFile);
		fclose(pFile);
		return 0;
}

从左到右依次为原图像,恢复图像,误差图像
从左到右依次为原图像,恢复图像,误差图像

编码结果的分析

分析步骤

将预测误差图像写入文件并将该文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。
将原始图像文件输入Huffman编码器,得到输出码流、给出概率分布图并计算压缩比。最后比较两种系统(1.DPCM+熵编码和2.仅进行熵编码)之间的编码效率(压缩比和图像质量)。压缩质量以PSNR进行计算。

分析结果

项目压缩比PSNR
原图像87.92%
8bit预测误差图像47.58%79.76

计算PSNR代码如下

	for (int i = 0; i < height; i++) {

		for (int j = 0; j < width; j++) {
			sum += abs(pBuf[i*width + j]);
		}
	}
	MSE = float(sum) / float(width*height);
	PSNR = 10 * log10(65025 / MSE);
	printf("PSNR=%f", PSNR);

观察生成的huffman编码文件
发现编码后的预测编码文件只有部分电平被编码,且概率分布大量集中在128(0)附近,128(0)附近的码长较短,在3-7之间,节约了很多码长。0附近是y预测误差集中的区域,128则是uv设置的值。而原图像则无序较为均匀的分布在了0-255之间,码长除了16的码长为3以外,全部分布在7以上,导致了压缩效率不高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值