文章目录

  • DPCM差分预测编码
    • 算法原理
    • 实现功能
    • 实验代码
    • 实验过程
    • 实验结果

DPCM差分预测编码

算法原理

DPCM编解码的框图如下所示,可以很明显得发现这是一个带有负反馈的算法系统。

如上图所示,首先输入一个像素值,与上一个像素的预测值做差,将得到的差值进行编码,编码后的差值有两个去向:一个是直接输出另一个是通过解码器反解出差值,和上一像素的预测值相加,就得到了当前像素的预测值,为下一个像素的到来做准备。

实现功能

本次采用左侧预测,并且默认最左侧像素前的真实值为均为128。并且实现了如下功能:

  • 进行不同量化bit数的差分预测编码
  • 将编码结果进行输出并进行霍夫曼编码
  • 分别计算原图像和量化后的图像进行概率分布
  • 分别计算原图像经过熵编码和经过DPCM+熵编码的图像的压缩比
  • 比较二者压缩效率
  • 计算重建图像的PSNR

实验代码

#include <iostream>
#include <cstring>
#include <cmath>
#include <fstream>
#include <algorithm>
#define uchar unsigned char
#define ll long longusing namespace std;const string path = "C:\\Users\\sdlwq\\Desktop\\test\\Lena256B.yuv"; // 原始图像4:1:1
const string build_out = "build.yuv"; // 重建
const string code_out = "code.yuv"; // 量化编码
const int width = 256;
const int height = 256;
double freq[256];uchar* input_buffer; //原始图像
uchar* out_buffer;  //重建图
uchar* code_buffer;  //量化输出
uchar* u_buffer;  // 色差信号
uchar* v_buffer;
int bitnum;inline void calculate_freq(uchar* buffer) //计算概率分布
{memset(freq, 0.0, sizeof(freq));for (int i = 0;i < height * width;i ++) freq[buffer[i]] += 1.0;for (double & i : freq) i /= (height * width);
}inline int limit(int val, int low, int high)
{if (val < low) return low;else if (val > high) return high;else return val;
}inline double PSNR(uchar* standard, uchar* image)
{int max = 255;double mse = 0;for (int i = 0; i < height; i ++) {for (int j = 0; j < width; j ++) {mse += (standard[i * width + j] - image[i * width + j]) * (standard[i * width + j] - image[i * width + j]);}}mse = (double)mse / (double)(width * height);double psnr = 10 * log10((double)(max * max) / mse);cout << "PSNR = " << psnr;
}int main()
{int length = width * height;ifstream in(path, ios :: binary);if (!in.is_open()) {cout << "Open failed" << endl;exit(-1);}else cout << "Open Successfully" << endl;input_buffer = new uchar[length];out_buffer = new uchar[length];code_buffer = new uchar[length];u_buffer = new uchar[length / 2];v_buffer = new uchar[length / 2];in.read((char*)input_buffer, length);// 计算一下原始的像素值分布ofstream out;out.open( "original.csv", ios :: out);calculate_freq(input_buffer);if (!out.is_open()) {cout << "CSV Open Failed" << endl;exit(-1);}for (int i = 0;i < 256;i ++) out << i << ',' << freq[i] << endl;out.close();cout << "Write Successfully" << endl;memset(u_buffer, 128, length / 2);memset(v_buffer, 128, length / 2);// 分别进行8bit,4bit,2bit和1bit量化int prediction, preError, enqPreError;for (auto i : {8, 4, 2, 1}) {for (int h = 0;h < height;h ++) {prediction = 128;preError = input_buffer[h * width] - prediction;int temp = (preError + 128) / pow(2, 8 - i);code_buffer[h * width] = limit(temp, 0, pow(2, i) - 1);enqPreError = code_buffer[h * width] * pow(2, 8 - i) - 128;out_buffer[h * width] = limit(enqPreError + prediction, 0, 255);for (int w = 1;w < width;w ++) {prediction = out_buffer[h * width + w - 1];preError = input_buffer[h * width + w] - prediction;int temp = (preError + 255) / pow(2, 9 - i);code_buffer[h * width + w] = limit(temp, 0, (pow(2, i) - 1));enqPreError = code_buffer[h * width + w] * pow(2, 9 - i) - 255;out_buffer[h * width + w] = limit(enqPreError + prediction, 0, 255);}}cout << "Translate Successfully" << endl;string str;str += ('0' + i);str += "bit";cout << str << endl;out.open(str + build_out, ios :: binary);out.write((char*)out_buffer, length);out.write((char*)u_buffer, length / 2);out.write((char*)v_buffer, length / 2);out.close();out.open(str + code_out, ios :: binary);out.write((char*)code_buffer, length);out.write((char*)u_buffer, length / 2);out.write((char*)v_buffer, length / 2);out.close();double residualFre[255] = {0};calculate_freq(code_buffer);out.open(str + "code.csv", ios::out);for( int k = 0; k < (1 << i); k ++) out << k << "," << freq[k] << endl;cout << i << "bit psnr: "<< PSNR( input_buffer, out_buffer) << endl;delete[] input_buffer;delete[] code_buffer;delete[] out_buffer;delete[] u_buffer;delete[] v_buffer;cout << i << "bit complete" << endl;}return 0;
}

实验过程

通过运行上面的代码,我们可以得到8,4,2,1bit下的重建图像和量化误差图像。同时得到了每种bit量化下的编码概率分布及其PSNR值,下面我们来分别对原图和量化后的编码进行熵编码,本次实验采用Huffman编码。

使用以下bat指令:

huff_run.exe -i 8bitcode.yuv -o 8bitcode.huff -c -t 8bitcode.txt
huff_run.exe -i 4bitcode.yuv -o 4bitcode.huff -c -t 4bitcode.txt
huff_run.exe -i 2bitcode.yuv -o 2bitcode.huff -c -t 2bitcode.txt
huff_run.exe -i 1bitcode.yuv -o 1bitcode.huff -c -t 1bitcode.txt
huff_run.exe -i Lena256B.yuv -o standard.huff -c -t standard.txt


即可得到经过熵编码后的数据。

实验结果

注意:这里我们压缩比按照AfterHuffOriginal\frac{After_{Huff}}{Original}OriginalAfterHuff​​来计算。

8 bit 4 bit 2 bit 1 bit
量化误差图
重建图像
概率分布图
压缩比 51.055% 29.075% 25.709% 25.017%
PSNR 51.147 23.139 11.935 9.956

如果将原始图像直接进行熵编码,压缩比为71.09%。

可见经过熵编码之后,图像的大小会减小。
经过DCMP+熵编码之后,图像大小比直接使用熵编码减小的更多,随着量化比特数的减小,压缩效率越来越高,但是变化越来越缓慢;于此同时,图像质量,也就是PSNR的值迅速恶化,重建出的图像质量越来越差,到1bit是就已经很模糊了。
综上,量化应采用合适的量化比特数,使之既不至于太影响画面,又可以达到较高的压缩效率。

DPCM差分预测编码原理及实现相关推荐

  1. mipi差分信号原理

    差分信号,什么是差分信号 一个差分信号是用一个数值来表示两个物理量之间的差异.从严格意义上来讲,所有电压信号都是差分的,因为一个电压只能是相对于另一个电压而言的.在某些系统里,系统'地'被用作电压基准 ...

  2. Android差分升级原理和实现方式

    增量升级概述 增量升级的原理很简单,即首先将应用的旧版本Apk与新版本Apk做差分,得到更新的部分的补丁,例如旧版本的APK有20M,新版的有21M,更新的部分则可能只有1M左右,这里需要说明的是,得 ...

  3. android差分升级原理,BigNews Android 增量更新框架差分包升级 @codeKK c开源站

    支持增量包/差分包/升级包 原理:在服务器端使用 bsdiff 工具将新老安装包的差异打包为一个体积较小的差分包/升级包,然后在 App 端通过 bspatch 工具(和 bsdiff 配套的)用差分 ...

  4. 技术干货 | 一文弄懂差分隐私原理!

    随着互联网的迅猛发展,网络早已融进人们日常生活的方方面面,我们的个人隐私在互联网时代几乎已经不是秘密.在数据时代,如何保护自己的隐私呢?差分隐私又是什么?小编用一篇文章带领大家了解什么是差分隐私,背后 ...

  5. 秘密共享差分隐私原理解析

    1. 隐私计算全貌  可以看到,隐私计算技术从1979年就开始了,历经四代从安全多方计算(MPC).到差分隐私(DP).到集中加密技术(TEE),再到联邦学习(FL). 2. 秘密共享 secre ...

  6. 短基线(SBL)差分定位原理及仿真分析

    采用差分定位方式的短基线仅需要4个水听器即可实现定位,同时还不需要同步时钟,简化了系统设计,这是它的优点:但是,它的缺点也是显而易见的,其定位精度很低,且存在定位误差极大的"死点" ...

  7. 隐私保护联邦学习之差分隐私原理

    背景 什么是隐私 讲差分隐私前,说一下什么是隐私 其实隐私这个定义,各家有各家的说法,而且各人有各人不同的考量.目前普遍比较接受的是:"单个用户的某一些属性" 可以被看做是隐私.这 ...

  8. 驱动lvds双8位时钟_LVDS低压差分信号原理

    差分信号有别于单端信号一根信号线传输信号然后参考GND作为高(H).低(L)逻辑电平的参考并作为镜像流量路径的做法,差分传输在两根传输线上都传输信号,这两个信号的振幅相等,相位相差180度,极性相反, ...

  9. 输出电压为什么要偏移?差分电路原理解析

    差分运算放大电路,对共模信号得到有效抑制,而只对差分信号进行放大,因而得到广泛的应用. 差分电路的电路构型 图1 差分电路 目标处理电压:是采集处理电压,比如在系统中像母线电压的采集处理,还有像交流电 ...

  10. (干货分享)差分电路原理解析

    差分运算放大电路,对共模信号得到有效抑制,而只对差分信号进行放大,因而得到广泛的应用. 01 差分电路的电路构型 图1 差分电路 目标处理电压:是采集处理电压,比如在系统中像母线电压的采集处理,还有像 ...

最新文章

  1. 零基础的前端开发初学者应如何系统地学习?
  2. 好记性不如烂博客之 Quartz InterruptableJob 可拦截任务
  3. 用.NET 2.0压缩解压功能处理大型数据
  4. java解决跨域问题
  5. VC6.0下opencv1.0的环境配置
  6. Java Web应用小案例:猜数小游戏
  7. java语言中application异常退出和线程异常崩溃的捕获方法,并且在捕获的钩子方法中进行异常处理
  8. 十二客推出新版邮箱批量注册
  9. 对 /etc/rc.d/init.d 目录的一点理解
  10. python 推荐系统库_python-recsys:一款实现推荐系统的python库
  11. STM32F103ZET6硬件资源简介
  12. python ar_四种AR的实现方式
  13. thinkphp3.1.3框架手册
  14. SQL SERVER 日期时间 格式
  15. 湖北职称英语和职称计算机考试,湖北职称英语考试
  16. PaddleSpeech 流式语音合成系统 PP-TTS
  17. 网站进入前10名的需要的操作
  18. C#遇到 错误:不可访问,因为它具有一定的保护级别
  19. 今夕何夕 HDU - 6112 ( 模拟 )
  20. 微软crm mscrm 区域城市联动 用 js+查找列 实现

热门文章

  1. 将bat文件转化成exe
  2. Linux命令之udhcpc,自动获取IP地址
  3. 红米开发版刷机教程_红米K20开发版刷机包(官方系统最新完整固件升级包V20.1.9MIUI开发版)...
  4. 红米k30pro刷机鸿蒙,红米k30pro最严重缺点_红米k30pro建不建议买
  5. win7如何安装IIS,三种方法任你选(图文教程)
  6. pandas用法-全网最详细教程
  7. java ppt模板_java循环ppt模板
  8. [信号]预加重与去加重--转
  9. 分布式定时任务的解决方案
  10. python打印网页成pdf_如何使用Python将网页转换为PDF