欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DPCM编码进行图像压缩

程序员文章站 2022-07-14 19:06:12
...

DPCM的编解码原理如下:DPCM编码进行图像压缩
编码思路:

主程序代码:main.cpp

#include "pch.h"
#include <iostream>
#include<math.h>
#include<malloc.h>
using namespace std;
const int w = 500;
const int h = 500;
const int depth = 5;
const int N = w * h;

int main(int argc, char *argv[])
{
	FILE* yuvFile = NULL;
	FILE* reFile = NULL;
	FILE* peFile = NULL;

	errno_t err;
	err = fopen_s(&yuvFile, "seed.yuv", "rb");
	if (err != 0)
	{
		printf("cannot open yuv file\n");
	}
	errno_t err1;
	err1 = fopen_s(&reFile, "re.yuv", "wb");
	if (err1 != 0)
	{
		printf("cannot open refile\n");
	}
	errno_t err2;
	err2 = fopen_s(&peFile, "pe.yuv", "wb");
	if (err2 != 0)
	{
		printf("cannot open prediction error file\n");
	}
	
	unsigned char* yBuf = (unsigned char*)malloc(sizeof(unsigned char) * N);
	unsigned char* uBuf = (unsigned char*)malloc(sizeof(unsigned char) * N );
	unsigned char* vBuf = (unsigned char*)malloc(sizeof(unsigned char) * N );
	unsigned char* reBuf = (unsigned char*)malloc(sizeof(unsigned char) * N);//重建图像
	unsigned char* peBuf = (unsigned char*)malloc(sizeof(unsigned char) * N);//预测误差  prediction error

	fread(yBuf, sizeof(unsigned char), N, yuvFile);
	fread(uBuf, sizeof(unsigned char), N , yuvFile);
	fread(vBuf, sizeof(unsigned char), N , yuvFile);

	dpcm(h, w, yBuf, depth, reBuf, peBuf);

	fwrite(reBuf, sizeof(unsigned char), N, reFile);
	fwrite(uBuf, sizeof(unsigned char), N , reFile);
	fwrite(vBuf, sizeof(unsigned char), N , reFile);
	fwrite(peBuf, sizeof(unsigned char), N, peFile);
	fwrite(uBuf, sizeof(unsigned char), N, peFile);
	fwrite(vBuf, sizeof(unsigned char), N, peFile);

	fclose(yuvFile);
	fclose(reFile);
	free(yBuf);
	free(vBuf);
	free(uBuf);
	free(reBuf);
	free(peBuf);
}

DPCM编码代码:DPCM.cpp

void dpcm(int h,int w,unsigned char *Y_Buf,int depth,unsigned char *reBuf,unsigned char *preErr)
{
	int prediction,err,inerr;//预测值和差值
	int extend;
	for (int i = 0; i < h; i++){
		for (int j = 0; j < w; j++){
			if (j == 0) {
				prediction = 128;
				err = Y_Buf[i*w] - prediction;
				extend = (err + 128) / pow(2, 8 - depth);
				preErr[i*w + j] = extend;
				if (preErr[i*w + j] < 0) {
					preErr[i*w + j] = 0;
				}
				else if (preErr[i*w + j] > pow(2, depth) - 1) {
					preErr[i*w + j] = pow(2, depth) - 1;
				}
				inerr = preErr[i*w] * pow(2, 8 - depth);
				reBuf[i*w + j] = inerr;
				if (reBuf[i*w + j] < 0) {
					reBuf[i*w + j] = 0;
				}
				else if (reBuf[i*w + j] > 255) {
					reBuf[i*w + j] = 255;
				}
			}
			else {
				prediction = reBuf[i*w + j - 1];
				err = Y_Buf[i*w + j] - prediction;
				extend = (err + 255) / pow(2, 9 - depth);//拓展为8bit量化
				preErr[i*w + j] = extend;
				if (preErr[i*w + j] < 0) {
					preErr[i*w+j] = 0;
				}
				else if (preErr[i*w + j] > pow(2, depth) - 1) {
					preErr[i*w+j] = pow(2, depth) - 1;
				}
				inerr = preErr[i*w + j] * pow(2, 9 - depth) - 255 + prediction;
				reBuf[i*w + j] = inerr;
				if (reBuf[i*w + j] < 0) {
					reBuf[i*w+j] = 0;
				}
				else if (reBuf[i*w + j] > 255) {
					reBuf[i*w+j] = 255;
				}
			}
		}
	}
}

计算PSNR

void psnr(int w,int h,unsigned char *Y_Buf,unsigned char *reBuf,int depth) //计算图像的压缩质量
{
	FILE* psnrtxt;
	fopen_s(&psnrtxt, "psnr.txt", "ab");
	double psnr = 0;
	double mse = 0;
	for (int i = 0; i < w*h; i++) {
		mse += pow((Y_Buf[i] - reBuf[i]), 2);
	}
	mse = mse / (w * h);
	psnr = 10 * log10(255 * 255 / mse);
	fprintf(psnrtxt,"Bit=%d,psnr=%lf\n", depth,psnr);//写入文件
}

本次选用了两张图来看结果。
一张为56*256的4:2:0的yuv文件
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
由此可见,量化系数越大,图像质量越佳。

量化系数 PSNR
8bit 30.035363
7bit 30.201576
6bit 29.375232
5bit 26.893395
4bit 19.217079
3bit 11.516803
2bit 8.467440
1bit 9.448466

在1bit时psnr会突然上涨。

下面的是436*538的4:4:4的yuv文件,下面是1-8bit量化的结果
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
DPCM编码进行图像压缩
同样可以从图中看出量化系数越大,图片质量越好。

量化系数 PSNR
8bit 5.478266
7bit 3.519651
6bit 2.757276
5bit 2.505715
4bit 2.575068
3bit 2.973797
2bit 4.045500
1bit 7.024183

由于使用的图黑色占了大部分占比,所以最后1bit量化时出现了明显误差。