[Data Compression 6] Realization and Analysis of DPCM Compression System

Experimental principle

1. DPCM codec

DPCM is the abbreviation of Differential Predictive Coding Modulation, which is a typical predictive coding system. In the DPCM system, it should be noted that the input of the predictor is the decoded sample. The reason why the original samples are not used for prediction is that the original samples cannot be obtained at the decoding end, only samples with errors can be obtained. Therefore, a decoder is actually embedded in the DPCM encoder, as shown in the dotted box in the encoder.

In a DPCM system, there are two factors to design: predictor and quantizer. Ideally, the predictor and quantizer should be jointly optimized. In practice, a sub-optimal design method is adopted: separately optimize the design of the linear predictor and the quantizer.
insert image description here

2. PSNR Peak Signal to Noise Ratio

PSNR: The abbreviation of "Peak Signal to Noise Ratio", that is, the peak signal-to-noise ratio, is an objective standard for evaluating images. It has limitations and is generally used for an engineering project between the maximum signal and background noise.

First calculate the mean square error MSE (Mean Square Error):
insert image description here

Where M , NM,NM,N are the width and height of the image, f ( i , j ) , f ' ( i , j ) f(i,j),f'(i,j)f(i,j), f'(i,j) is the pixel value of the original image and the reconstructed image at (i, j). PSNR (unit: dB) is calculated as follows:
insert image description here

When PSNR ≥ 40dB, the image quality is very good and close to the original image;
when 30dB ≤ PSNR < 40dB, the image has perceivable distortion, but the quality is still acceptable;
when 20dB ≤ PSNR < 30dB, the image quality is poor;
PSNR < 20dB , the image quality has become unacceptable.

Experimental procedure

1. Read the BMP file, convert it into yuv format, and extract the y component.
2. Predict the grayscale image. The input of the predictor is the reconstruction value of the previous sample point, and calculate the prediction error.
3. Perform 8-bit uniform quantization on the prediction error
4. Dequantize the quantized prediction error and find the reconstruction value
5. Input the prediction error image and the original grayscale image into the Huffman encoder to obtain the necessary information of the codeword and compare the two systems (DPCM+entropy coding and entropy coding only ) between the coding efficiency.

experimental code

1. DPCM

 void DPCM(unsigned char* y_buffer, unsigned char* differ_buffer, unsigned char* rebuild_buffer, int width, int height, int bitnum)
{
    
    
	for (int i = 0; i < height; i++)
	{
    
    
		for (int j = 0; j < width; j++)
		{
    
    
			if (j == 0)
			{
    
    
				differ_buffer[i * width] = ((y_buffer[i * width] - 128) + 255) / pow(2, (double)(9 - bitnum));
				rebuild_buffer[i * width] = differ_buffer[i * width] * pow(2, (double)(9 - bitnum)) - 255 + 128;
			}
			else
			{
    
    
				differ_buffer[i * width + j] = ((y_buffer[i * width + j] - rebuild_buffer[i * width + j - 1]) + 255) / pow(2, (double)(9 - bitnum));
				rebuild_buffer[i * width + j] = differ_buffer[i * width + j] * pow(2, (double)(9 - bitnum)) - 255 + rebuild_buffer[i * width + j - 1];
			}
			if (differ_buffer[i * width + j] > 255)
				differ_buffer[i * width + j] = 255;
			if (differ_buffer[i * width + j] < 0)
				differ_buffer[i * width + j] = 0;
			if (rebuild_buffer[i * width + j] > 255)
				rebuild_buffer[i * width + j] = 255;
			if (rebuild_buffer[i * width + j] < 0)
				rebuild_buffer[i * width + j] = 0;
		}
	}
}

2.PSNR

    double mse = 0;
	double psnr = 0;
	for (int i = 0; i < width * height; i++) {
    
    
 
 
		mse += pow((y_buffer[i] - rebuild_buffer[i]), 2);
 
	}
	mse = mse / (width * height);
	psnr = 10 * log10(pow(255, 2) / mse);
	printf("PSNR=%f", psnr);

3. Calculate the source symbol probability distribution

	double frequency[256] = {
    
     0 };
	calculate_fre(y_buffer, frequency, width, height);
	FILE* orin_fre;
	orin_fre = fopen("ori_frequency.txt", "wb");
	fprintf(orin_fre, "%s\t%s\t", "symbol", "freq");
	for (int i = 0; i < 256; i++)
	{
    
    
		fprintf(orin_fre, "%d\t%f\t", i, frequency[i]);
	}
 
	DPCM(y_buffer, differ_buffer, rebuild_buffer, width, height, bitnum);
 
	double frequency2[256] = {
    
     0 };
	calculate_fre(differ_buffer, frequency2, width, height);
	FILE* differ_fre;
	differ_fre = fopen("differ_frequency.txt", "wb");
	fprintf(differ_fre, "%s\t%s\t", "symbol", "freq");
	for (int i = 0; i < 256; i++)
	{
    
    
		fprintf(differ_fre, "%d\t%f\t", i, frequency2[i]);
	}

4.main.cpp

#include<stdlib.h>
#include<stdio.h>
#include"math.h"
#include"DPCM.h"
void calculate_fre(unsigned char* buffer, double* frequency, int width, int height)
{
    
    
	int size = width * height;
	for (int i = 0; i < size; i++)
	{
    
    
		frequency[buffer[i]]++;
	}
	for (int k = 0; k < 256; k++)
	{
    
    
		frequency[k] /= size;
	}
}
int main(int argc, char** argv)
{
    
    
	const char* ori_name = argv[1];
	const char* differ_name = argv[2];
	const char* rebu_name = argv[3];
	int bitnum = atoi(argv[4]);
	FILE* ori_file = NULL;
	FILE* differ_file = NULL;
	FILE* rebu_file = NULL;
	if ((ori_file = fopen(ori_name, "rb")) == NULL)
		printf("Failed to open the original picture\n");
	else
		printf("succeeded to open the original picture\n");
 
	if ((differ_file = fopen(differ_name, "wb")) == NULL)
		printf("Failed to open the difference picture\n");
	else
		printf("succeeded to open the difference picture\n");
 
	if ((rebu_file = fopen(rebu_name, "wb")) == NULL)
		printf("Failed to open the rebulid picture\n");
	else
		printf("succeeded to open the rebulid picture\n");
 
	int width = 256;
	int height = 256;
	unsigned char* y_buffer = new unsigned char[width * height];
	unsigned char* u_buffer = new unsigned char[width * height / 4];
	unsigned char* v_buffer = new unsigned char[width * height / 4];
	unsigned char* differ_buffer = new unsigned char[width * height];
	unsigned char* rebuild_buffer = new unsigned char[width * height];
	fread(y_buffer, 1, width * height, ori_file);
	fread(u_buffer, 1, width * height / 4, ori_file);
	fread(v_buffer, 1, width * height / 4, ori_file);

	double frequency[256] = {
    
     0 };
	calculate_fre(y_buffer, frequency, width, height);
	FILE* orin_fre;
	orin_fre = fopen("ori_frequency.txt", "wb");
	fprintf(orin_fre, "%s\t%s\t", "symbol", "freq");
	for (int i = 0; i < 256; i++)
	{
    
    
		fprintf(orin_fre, "%d\t%f\t", i, frequency[i]);
	}
 
	DPCM(y_buffer, differ_buffer, rebuild_buffer,width,height,bitnum);

	double frequency2[256] = {
    
     0 };
	calculate_fre(differ_buffer, frequency2, width, height);
	FILE* differ_fre;
	differ_fre = fopen("differ_frequency.txt", "wb");
	fprintf(differ_fre, "%s\t%s\t", "symbol", "freq");
	for (int i = 0; i < 256; i++)
	{
    
    
		fprintf(differ_fre, "%d\t%f\t", i, frequency2[i]);
	}

	fwrite(differ_buffer,1,width*height,differ_file);
	fwrite(u_buffer, 1, width * height/4, differ_file);
	fwrite(v_buffer, 1, width * height / 4, differ_file);
 
	fwrite(rebuild_buffer, 1, width * height, rebu_file);
	fwrite(u_buffer, 1, width * height / 4, rebu_file);
	fwrite(v_buffer, 1, width * height / 4, rebu_file);

	double mse = 0;
	double psnr = 0;
	for (int i = 0; i < width*height; i++) {
    
    
 
		
			mse += pow((y_buffer[i]-rebuild_buffer[i]),2);
		
	}
	 mse = mse / (width * height);
	 psnr = 10 * log10(pow(255,2) / mse);
	printf("PSNR=%f", psnr);
 
	fclose(ori_file);
	fclose(differ_file);
	fclose(rebu_file);
 
	delete[] y_buffer;
	delete[] u_buffer;
	delete[] v_buffer;
	delete[] differ_buffer;
	delete[] rebuild_buffer;
 
	return 0;
}

5.DPCM.h

#pragma once
#ifndef DPCM_H_
#define DPCM_H_
 
void DPCM(unsigned char* y_buffer, unsigned char* differ_buffer, unsigned char* rebuild_buffer, int width, int height, int bitnum);
#endif

6.DPCM.cpp

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
 
void DPCM(unsigned char* y_buffer, unsigned char* differ_buffer, unsigned char* rebuild_buffer,int width, int height,int bitnum)
{
    
    
	for (int i = 0; i < height; i++)
	{
    
    
		for (int j = 0; j < width; j++)
		{
    
    
			if (j == 0)
			{
    
    
				differ_buffer[i * width] = ((y_buffer[i * width] - 128)+255)/pow(2,(double)(9-bitnum));
				rebuild_buffer[i * width] = differ_buffer[i * width] * pow(2, (double)(9 - bitnum)) - 255 + 128;
			}
			else
			{
    
    
				differ_buffer[i * width+j] = ((y_buffer[i * width+j] - rebuild_buffer[i * width+j-1]) + 255) / pow(2, (double)(9 - bitnum));
				rebuild_buffer[i * width + j] = differ_buffer[i * width+j] * pow(2, (double)(9 - bitnum)) - 255 + rebuild_buffer[i * width + j-1];
			}
			if (differ_buffer[i * width + j] > 255)
				differ_buffer[i * width + j] = 255;
			if(differ_buffer[i * width + j] <0)
				differ_buffer[i * width + j] = 0;
			if (rebuild_buffer[i * width + j] > 255)
				rebuild_buffer[i * width + j] = 255;
			if (rebuild_buffer[i * width + j] < 0)
				rebuild_buffer[i * width + j] = 0;
		}
	}
}

Experimental results

Quantization bits original image forecast error reconstruction map PSNR
8 insert image description here insert image description here insert image description here 51.153
4 insert image description here insert image description here insert image description here 13.957
2 insert image description here insert image description here insert image description here 8.743

As the number of quantization bits decreases, the PSNR value gradually decreases, and the image is obviously distorted, making it impossible to effectively reconstruct the image.

Guess you like

Origin blog.csdn.net/ppinecone/article/details/125792624