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

一、实验目的

掌握DPCM编解码系统的基本原理。初步掌握实验用C/C++/Python等语言编程实现DPCM编码器,并分析其压缩效率。

二、实验原理

在这里插入图片描述
DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中, 需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是 因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实 际内嵌了一个解码器,如编码器中虚线框中所示。

三、实验内容

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

代码实现

此实验DPCM编码阶段中需要创建三个buffer,分别是:

 unsigned char* y_buffer=NULL//当前样本预测值;
 unsigned char* p_buffer=NULL//当前样本重建值;
 unsigned char* d_buffer=NULL//图像预测误差值;

所有代码:

#include<stdio.h>
#include<stdlib.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 *p_filename=NULL;//重建图像
    char *d_filename=NULL;//预测误差
    FILE* yuvfile=NULL;
    FILE* p_file=NULL;
    FILE* d_file=NULL;
    int width=256,height=256;
    yuvfilename=argv[1];
    p_filename=argv[2];
    d_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* p_buffer=NULL;
    unsigned char* d_buffer=NULL;

    yuvfile=fopen("/Users/997xyq/Desktop/down.yuv","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);
    d_buffer=(unsigned char*)malloc(width*height*1.5);
    p_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("/Users/997xyq/Desktop/down_o.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 d;//误差
        if(i%width==0)
        {
            d=float(y_buffer[i])-128;//假设预测值为128
            d_buffer[i]=(unsigned char)(d/2+128);//对预测误差量化
            p_buffer[i]=(unsigned char)(128+(d_buffer[i]-128)*2);//重建值=反量化后的误差+预测值
        }
        else
        {
            d=float(y_buffer[i]-p_buffer[i-1]);//选取前一像素的重建值作为预测值
            d_buffer[i]=(unsigned char)(d/2+128);
            p_buffer[i]=(unsigned char)(p_buffer[i-1]+(d_buffer[i]-128)*2);
        }
    }

    //得到残差的概率分布
    FILE *d;
    d=fopen("/Users/997xyq/Desktop/down_d.txt","wb");
    double frequency_[256]={0};
    GetFrequency(d_buffer,frequency_,height,width);
    for(int i=0;i<256;i++)
    {
        fprintf(d,"%d\t%f\n",i,frequency_[i]);
    }

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


    p_file=fopen("/Users/997xyq/Desktop/down_p.yuv","wb");
    d_file=fopen("/Users/997xyq/Desktop/down_d.yuv","wb");
    fwrite(p_buffer,width*height,1,p_file);
    fwrite(u_buffer,width*height/4,1,p_file);
    fwrite(v_buffer,width*height/4,1,p_file);
    fwrite(d_buffer,width*height,1,d_file);
    fwrite(u_buffer,width*height/4,1,d_file);
    fwrite(v_buffer,width*height/4,1,d_file);
    fclose(p_file);
    fclose(d_file);
}


实验结果

得出图像
在这里插入图片描述

生成的文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
huffman编码器还未完成,未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值