天天看點

資料壓縮實驗4——DPCM編碼

1 實驗目的

掌握DPCM編解碼系統的基本原理。初步掌握實驗用C/C++/Python等語言程式設計實作DPCM編碼器,并分析其壓縮效率。

2 實驗原理

2.1 DPCM

資料壓縮實驗4——DPCM編碼

DPCM是差分預測編碼調制的縮寫,是比較典型的預測編碼系統。在DPCM系統中,需要注意的是預測器的輸入是已經解碼以後的樣本。之是以不用原始樣本來做預測,是因為在解碼端無法得到原始樣本,隻能得到存在誤差的樣本。是以,在DPCM編碼器中實際内嵌了一個解碼器,如編碼器中虛線框中所示。

首先輸入一個圖像,與上一個圖像的預測值做差,将內插補點進行編碼。

編碼後的內插補點有兩個去向,一是直接輸出,二是通過解碼器解出內插補點,再與上一幀的預測值相加,就得到了目前圖像的預測值,為下一幀圖像到來時做好準備。

2.2 PSNR(Peak Signal Noise Ratio)

PSNR(峰值信噪比)是一種度量圖像失真的方式,本實驗使用PSNR作為圖像品質評價的名額。峰值信噪比與圖像品質近似成正比關系。

計算公式如下:

資料壓縮實驗4——DPCM編碼

3 實驗内容

在本次實驗中,我們采用固定預測器和均勻量化器。預測器采用左側預測。量化器采用8比特均勻量化。

在DPCM編碼器實作的過程中同時輸出預測誤差圖像和重建圖像。将預測誤差圖像寫入檔案并将該檔案輸入Huffman編碼器,得到輸出碼流、給出機率分布圖并計算壓縮比。将原始圖像檔案輸入Huffman編碼器,得到輸出碼流、給出機率分布圖并計算壓縮比。比較兩種系統(DPCM+熵編碼和僅進行熵編碼)之間的編碼效率(壓縮比和圖像品質)。壓縮品質以PSNR進行計算。

3.1 實驗代碼

得到重建圖像以及預測誤差圖像,計算PSNR,得到頻率分布。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>
#include<iostream>
using namespace std;


//計算PSNR
double PSNR( unsigned char* standard, unsigned char* image,int height,int width,int bitNum )
{
    double psnr = 0, MSE = 0;
    for( int i = 0; i < height * width; i++ ) 
	{
		MSE += 1ll* (image[i] - standard[i]) * (image[i] - standard[i]);
	}
    MSE /= height * width;
    long long t = 1 << bitNum; t -= 1; t *= t;
    psnr = 10 * log10( t / MSE);
    return psnr;
}
//得到頻率分布
void GetFrequency( unsigned char* buffer, double* frequency,int height,int width )
{
    int length = height * width;
    for( int i = 0; i < length; i++ ) frequency[buffer[i]] ++;
    for( int i = 0; i < 256; i++ ) frequency[i] /= length;
}


int main(int argc,char** argv)
{
	char *yuvfilename=NULL;
	char *re_y_filename=NULL;
	char *err_filename=NULL;
	FILE* yuvfile=NULL;
	FILE* re_y_file=NULL;
	FILE* err_file=NULL;
	int width,height;
	yuvfilename=argv[1];
	re_y_filename=argv[2];
	err_filename=argv[3];
	width=atoi(argv[4]);
	height=atoi(argv[5]);
	unsigned char* u_buffer=NULL;
	unsigned char* v_buffer=NULL;
	unsigned char* y_buffer=NULL;//原始圖像
	unsigned char* re_y_buffer=NULL;//重建值
	unsigned char* err_buffer=NULL;//預測誤差

	yuvfile=fopen(yuvfilename,"rb");
	if(yuvfile==0)
	{
		printf("cannot find yuv file.\n");
	}
	else
	{
		printf("open yuv file successfully!\n");
	}

	y_buffer=(unsigned char*)malloc(width*height);
	u_buffer=(unsigned char*)malloc(width*height/4);
	v_buffer=(unsigned char*)malloc(width*height/4);
	err_buffer=(unsigned char*)malloc(width*height*1.5);
	re_y_buffer=(unsigned char*)malloc(width*height*1.5);
	
	fread(y_buffer,1,width*height,yuvfile);
	fread(u_buffer,1,width*height/4,yuvfile);
	fread(v_buffer,1,width*height/4,yuvfile);

	//得到原始圖像的機率分布
	FILE *orig;
	orig=fopen("C:/Users/15643/Desktop/DPCM/DPCM/DPCM/orig.txt","wb");
	double frequency[256]={0};
	GetFrequency(y_buffer,frequency,height,width);
	for(int i=0;i<256;i++)
	{
		fprintf(orig,"%d\t%f\n",i,frequency[i]);
	}
	
	//DPCM編碼
	for(int i=0;i<width*height;i++)
	{
		float err;//誤差
		if(i%width==0)
		{
			err=float(y_buffer[i])-128;//假設預測值為128
			err_buffer[i]=(unsigned char)(err/2+128);//對預測誤差量化
			re_y_buffer[i]=(unsigned char)(128+(err_buffer[i]-128)*2);//重建值=反量化後的誤差+預測值
		}
		else
		{
			err=float(y_buffer[i]-re_y_buffer[i-1]);//選取前一像素的重建值作為預測值
			err_buffer[i]=(unsigned char)(err/2+128);
			re_y_buffer[i]=(unsigned char)(re_y_buffer[i-1]+(err_buffer[i]-128)*2);
		}
	}

	//得到殘差的機率分布
	FILE *err;
	err=fopen("C:/Users/15643/Desktop/DPCM/DPCM/DPCM/err.txt","wb");
	double frequency_[256]={0};
	GetFrequency(err_buffer,frequency_,height,width);
	for(int i=0;i<256;i++)
	{
		fprintf(err,"%d\t%f\n",i,frequency_[i]);
	}

	//計算PSNR
	cout<<"psnr="<<PSNR(y_buffer,re_y_buffer,height,width,8)<<endl;


	re_y_file=fopen(re_y_filename,"wb");
	err_file=fopen(err_filename,"wb");
	fwrite(re_y_buffer,width*height,1,re_y_file);
	fwrite(u_buffer,width*height/4,1,re_y_file);
	fwrite(v_buffer,width*height/4,1,re_y_file);
	fwrite(err_buffer,width*height,1,err_file);
	fwrite(u_buffer,width*height/4,1,err_file);
	fwrite(v_buffer,width*height/4,1,err_file);
	fclose(re_y_file);
	fclose(err_file);

}
           

設定指令參數:

資料壓縮實驗4——DPCM編碼

執行結果:

資料壓縮實驗4——DPCM編碼
資料壓縮實驗4——DPCM編碼

使用YUVviewer檢視生成的結果:

資料壓縮實驗4——DPCM編碼

利用origin軟體繪制頻率分布圖:

1.原始圖像:

資料壓縮實驗4——DPCM編碼

2.殘差圖像

資料壓縮實驗4——DPCM編碼

3.2 利用Huffman編碼器進行熵編碼

1. DPCM+熵編碼

在指令行中輸入:

資料壓縮實驗4——DPCM編碼

結果:

資料壓縮實驗4——DPCM編碼

2. 僅進行熵編碼

在指令行輸入:

資料壓縮實驗4——DPCM編碼

結果:

資料壓縮實驗4——DPCM編碼

3. 對比

DPCM+熵編碼 僅進行熵編碼
編碼對象 殘差圖像 Lena_err.yuv 原始圖像 Lena256B.yuv
原始大小(KB) 96 96
壓縮後大小(KB) 46 69
壓縮比 47.9% 71.9%

繼續閱讀