DPCM差分预测编码原理及实现

这篇具有很好参考价值的文章主要介绍了DPCM差分预测编码原理及实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

DPCM差分预测编码

算法原理

DPCM编解码的框图如下所示,可以很明显得发现这是一个带有负反馈的算法系统。
DPCM差分预测编码原理及实现
如上图所示,首先输入一个像素值,与上一个像素的预测值做差,将得到的差值进行编码,编码后的差值有两个去向:一个是直接输出另一个是通过解码器反解出差值,和上一像素的预测值相加,就得到了当前像素的预测值,为下一个像素的到来做准备。

实现功能

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

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

实验代码

#include <iostream>
#include <cstring>
#include <cmath>
#include <fstream>
#include <algorithm>
#define uchar unsigned char
#define ll long long

using 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

DPCM差分预测编码原理及实现
即可得到经过熵编码后的数据。

实验结果

注意:这里我们压缩比按照 A f t e r H u f f O r i g i n a l \frac{After_{Huff}}{Original} OriginalAfterHuff来计算。

8 bit 4 bit 2 bit 1 bit
量化误差图 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现
重建图像 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现
概率分布图 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现 DPCM差分预测编码原理及实现
压缩比 51.055% 29.075% 25.709% 25.017%
PSNR 51.147 23.139 11.935 9.956

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

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

到了这里,关于DPCM差分预测编码原理及实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 编码器测速原理与实现

    编码器测速原理与实现

    通常情况下编码器旋转一周会输出固定的脉冲数,即编码器的分辨率,通过测量固定时间T内编码器输出的脉冲数即可求得电机的转速。 假设编码器的分辨率为P,T时间内测得脉冲数m个,则单倍频(编码器转动一圈输出的脉冲数与分辨率相同)情况下电机转速为: (其中m/p为

    2024年02月17日
    浏览(12)
  • 【音视频原理】视频帧的 I P B 帧概念 ① ( 码率 / 帧率 / 分辨率 视频信息 | I 帧 - 内部编码帧 | I 帧 - 关键帧压缩法 | P 帧 - 前向预测帧 )

    【音视频原理】视频帧的 I P B 帧概念 ① ( 码率 / 帧率 / 分辨率 视频信息 | I 帧 - 内部编码帧 | I 帧 - 关键帧压缩法 | P 帧 - 前向预测帧 )

    使用 MediaInfo 软件 打开一个 mp4 文件 , 查看其属性 ; 该视频的属性如下 : 码率 : 212kb/s , 这是 视频文件 的 视频信息 在 单位时间内的 数据流量 , 码率越大 , 单位时间内采样率越大 , 数据流精度越高 , 视频质量越高 ; 视频帧率 : 5fps , 1 秒中有 5 帧的信息 , 帧率越高 , 视频越流畅

    2024年02月20日
    浏览(15)
  • Java实现Base64编码以及原理详解

    Java实现Base64编码以及原理详解

    使用java.util.Base64类来实现Base64编码。 该类是Java8引入的。 上面就是java实现的代码,使用起来是很方便的。下面来说说Base64编码的原理。 Base64编码的作用:将字符串转为由64个特定字符组成的编码,这种编码方式适用于不支持特定编码的情况。 一、 首先来看,原字符串是“

    2024年02月14日
    浏览(11)
  • 强化学习9——免模型预测算法介绍(蒙特卡洛方法和时步差分方法)

    强化学习9——免模型预测算法介绍(蒙特卡洛方法和时步差分方法)

    对于大部分情况来说,环境是未知的,也就是说状态转移概率未知,对于这种情况的算法称为 免模型预测 算法。免模型算法与环境不断交互学习,但是需要大量的运算。 蒙特卡罗方法通过重复随机抽选,之后运用统计概率此方法来从抽样结果中归纳我们想要得到的数值估计

    2024年02月02日
    浏览(13)
  • 4路光栅尺磁栅尺编码器5MHz高速差分信号转Modbus TCP网络模块 YL97

    4路光栅尺磁栅尺编码器5MHz高速差分信号转Modbus TCP网络模块 YL97

    特点 : ● 光栅尺磁栅尺解码转换成标准Modbus TCP协议 ● 光栅尺5V差分信号直接输入,4倍频计数 ● 模块可以输出5V的电源给光栅尺供电 ● 高速光栅尺磁栅尺计数,频率可达5MHz ● 支持4个 光栅尺 同时计数,可识别正反转 ● 可网页直接查看所有数据无需其他软件 ● 编码器计

    2024年02月13日
    浏览(11)
  • 数学建模 | 灰色预测原理及python实现

    数学建模 | 灰色预测原理及python实现

    目录 一、灰色预测的原理 二、灰色预测的应用及python实现 灰色预测是以灰色模型为基础,灰色模型GM(n,h)是微分方程模型,可用于描述对象做 长期、连续、动态 的反应。其中,n代表微分方程式的阶数,h代表微分方程式的变化数目。在诸多的灰色模型中,以灰色系统中 单序

    2024年01月16日
    浏览(13)
  • 技术干货 | 一文弄懂差分隐私原理!

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

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

    2024年02月03日
    浏览(10)
  • 51单片机数字旋转编码器内部原理应用与实现------day5

    51单片机数字旋转编码器内部原理应用与实现------day5

    51单片机数字旋转编码器内部原理应用与实现 1.数字旋转编码器 可实现按下确认,旋转加减。 不按状态为高电平,按下为低电平。 时序图: 顺时针 逆时针 A B A B 1 1 1 1 0 1 1 0 0 0 0 0 1 0 0 1 电路原理图如下所示: 实现程序如下图所示:效果不错,无丢数情况,很顺畅。功能顺时

    2024年02月12日
    浏览(13)
  • 隐私保护联邦学习之差分隐私原理

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

    什么是隐私 讲差分隐私前,说一下什么是隐私 其实隐私这个定义,各家有各家的说法,而且各人有各人不同的考量。目前普遍比较接受的是:“单个用户的某一些属性” 可以被看做是隐私。这个说法里所强调的是:单个用户。也就是说,如果是一群用户的某一些属性,那么

    2024年01月17日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包