使用C++实现DPCM编码(左向预测8bit、4bit、2bit、1bit和上向预测8bit)

  • 一、DPCM是什么?
  • 二、使用C++实现DPCM编码(左向预测8bit、4bit、2bit、1bit和上向预测8bit)
    • 1、实验数据描述
    • 2、左向预测8bit、4bit、2bit、1bit
      • 1)左向预测8bit
      • 2)左向预测4bit
      • 3)左向预测2bit
      • 4)左向预测1bit
      • 5)左向预测8bit、4bit、2bit、1bit整体代码
    • 3、上向预测8bit
    • 4、整体代码
    • 5、实验结果分析
      • 1)左向预测8bit、4bit、2bit、1bit结果对比
      • 1)上向预测8bit与左向预测8bit对比
  • 三、归纳总结

一、DPCM是什么?

DPCM–差分脉冲编码调制(Differential Pulse code modulation,DPCM),是一种对模拟信号的编码模式,与PCM不同每个抽样值不是独立的编码,而是先根据前一个抽样值计算出一个预测值,再取当前抽样值和预测值之差作编码用。此差值称为预测误差.抽样值和预测值非常接近(因为相关性强),预测误差的可能取值范围比抽样值变化范围小。所以可用少几位编码比特来对预测误差编码,从而降低其比特率.这是利用减小冗余度的办法,降低了编码比特率。
➢ 根据某一模型利用以往的样本值对新样本进行预测,然后将样本的实际值与其预测值相减得到一个误差值,最后对这一误差值进行编码。
➢ 如果模型足够好,且样本序列在时间上相关性较强,则误差信号的幅度将远远小于原始信号,从而得到较大的数据压缩。
在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。

二、使用C++实现DPCM编码(左向预测8bit、4bit、2bit、1bit和上向预测8bit)

1、实验数据描述

此次用的是Lena.yuv,YUV灰度图像,如下图

因为所用图片为灰度图像,所以需要先把文件中所有值赋为128,以便将UV分量填满。

//给Buf128全赋值为128for (int i = 0; i < frameWidth * frameHeight / 2; i++){Buf128[i] = 128;}

2、左向预测8bit、4bit、2bit、1bit

1)左向预测8bit

因为是左向预测,所以图片中每一行的第一个值无法预测,所以直接将预测值设为本身的值,插值设为0。

if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}

若不是每一行的第一个值,那就需要先先计算插值a,将这个像素值减去左侧像素的预测值。但是因为图像是8bit(灰度值为0-255),所以如果相减值就会变为-255——+255因此如果想进行8bit量化,需要将插值a/2+127(更新插值d=a/2+127)(量化插值b=a/2)。之后需要进行反量化值c,将量化插值b乘2(c=b*2)。之后再将反量化值c与左侧像素预测值相加得到本像素预测值

             else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 2;//进行量化c = b * 2;//进行反量化d = b + 128;//进行+128yChazhiBuf[j + i * frameWidth] = d;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}

2)左向预测4bit

4bit量化与8bit量化的区别在于需要将插值a(-255–+255)转变为4bit插值d,所以需要将插值a/32+7(更新插值d=a/32+7)(量化插值b=a/32),。之后需要进行反量化值c,将插值a乘16(c=b*16)。之后再将反量化值c与左侧像素预测值相加得到本像素预测值

if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 32;//进行量化c = b * 32;//进行反量化d = b + 7;//进行+7yChazhiBuf[j + i * frameWidth] = d*16;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}

3)左向预测2bit

2bit量化与8bit量化的区别在于需要将插值a(-255–+255)转变为2bit插值d,所以需要将插值a/128+2(更新插值d=a/128+2)(量化插值b=a/128),。之后需要进行反量化值c,将插值a乘128(c=b*128)。之后再将反量化值c与左侧像素预测值相加得到本像素预测值

if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 128;//进行量化c = b * 128;//进行反量化d = b + 2;//进行+2yChazhiBuf[j + i * frameWidth] = d*64;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}

4)左向预测1bit

1bit量化与8bit量化的区别在于需要将插值a(-255–+255)转变为1bit插值d,所以需要将插值a/256+1(更新插值d=a/256+1)(量化插值b=a/256)。之后需要进行反量化值c,将插值a乘256(c=b*256)。之后再将反量化值c与左侧像素预测值相加得到本像素预测值

if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 256;//进行量化c = b * 256;//进行反量化d = b + 1;//进行+1yChazhiBuf[j + i * frameWidth] = d*256;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}

5)左向预测8bit、4bit、2bit、1bit整体代码

//左向预测8bit、4bit、2bit、1bit-计算差值与预测值for (int i = 0; i < frameHeight; i++){for (int j = 0; j < frameWidth; j++){if (x == 8){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 2;//进行量化c = b * 2;//进行反量化d = b + 128;//进行+128yChazhiBuf[j + i * frameWidth] = d;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 4){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 16;//进行量化c = b * 16;//进行反量化d = b + 16;//进行+64yChazhiBuf[j + i * frameWidth] = d*8;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 2){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 64;//进行量化c = b * 64;//进行反量化d = b + 4;//进行+4yChazhiBuf[j + i * frameWidth] = d*32;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 1){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 128;//进行量化c = b * 128;//进行反量化d = b + 2;//进行+2yChazhiBuf[j + i * frameWidth] = d*64;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}}}

3、上向预测8bit

因为是上向预测,所以图片中每一列的第一个值无法预测,所以直接将预测值设为本身的值,插值设为0。
若不是每一列的第一个值,那就需要先先计算插值a,将这个像素值减去上侧像素的预测值。但是因为图像是8bit(灰度值为0-255),所以如果相减值就会变为-255——+255因此如果想进行8bit量化,需要将插值a/2+127(更新插值d=a/2+127)(量化插值b=a/2),。之后需要进行反量化值c,将量化插值b乘2(c=b*2)。之后再将反量化值c与上侧像素预测值相加得到本像素预测值

//上预测8bitfor (int i = 0; i < frameWidth; i++){for (int j = 0; j < frameHeight; j++){if (x == 99){if (j == 0){yYuceBuf[i] = yBuf[i];yChazhiBuf[i] = 0;}else{a = yBuf[i + j * frameWidth] - yYuceBuf[i + (j - 1) * frameWidth];//计算插值b = a / 2;//进行量化c = b * 2;//进行反量化d = b + 127;//进行+127yChazhiBuf[i + j * frameWidth] = d;yYuceBuf[i + j * frameWidth] = yYuceBuf[i + (j - 1) * frameWidth] + c;}}}}

4、整体代码

#include "iostream"
#include"stdio.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include"math.h"
#pragma warning (disable:4996)
using namespace std;
#define u_int8_t    unsigned __int8
#define u_int       unsigned __int32int main(int argc, char** argv)
{char* yuvFileName = NULL;char* yuceFileName = NULL;char* chazhiFileName = NULL;u_int8_t* yBuf = NULL;u_int8_t* yuvBuf = NULL;u_int8_t* yYuceBuf = NULL;u_int8_t* yChazhiBuf = NULL;u_int8_t* Buf128 = NULL;FILE* yuvFile = NULL;FILE* chazhiFile = NULL;FILE* yuceFile = NULL;u_int frameWidth = 0;u_int frameHeight = 0;int a = 0;//量化前插值int b = 0;//量化后值int c = 0;//反量化后值int d = 0;//+128之后值int x = 0;//选择4bit,8bit量化//读取数据yuv文件数据yuvFileName = argv[1];yuceFileName = argv[2];chazhiFileName = argv[3];frameWidth = atoi(argv[4]);frameHeight = atoi(argv[5]);yuvFile = fopen(yuvFileName, "rb");yuvBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3 / 2);yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);yYuceBuf = (u_int8_t*)malloc(frameWidth * frameHeight);yChazhiBuf = (u_int8_t*)malloc(frameWidth * frameHeight);Buf128 = (u_int8_t*)malloc(frameWidth * frameHeight / 2);fread(yuvBuf, 1, frameWidth * frameHeight * 3 / 2, yuvFile);yuceFile = fopen(yuceFileName, "wb");chazhiFile = fopen(chazhiFileName, "wb");//给Buf128全赋值为128for (int i = 0; i < frameWidth * frameHeight / 2; i++){Buf128[i] = 128;}//读取y数据for (int i = 0; i < frameWidth * frameHeight; i++){yBuf[i] = yuvBuf[i];}//选择4bit,8bit量化,2bit量化,1bit量化while ((x != 4) && (x != 8) && (x != 2) && (x != 1) && (x != 99)){cout << "如想左向预测:选择8bit量化或者4bit量化或者2bit量化或者1bit量化,请输入“8”或“4”或“2”或“1”" << endl<< "如想上向预测请输入“99”(8bit)" << endl;cin >> x;if (x == 8){cout << "您选择了左向预测8bit量化";}else if (x == 4){cout << "您选择了左向预测4bit量化";}else if (x == 2){cout << "您选择了左向预测2bit量化";}else if (x == 1){cout << "您选择了左向预测1bit量化";}if (x == 99){cout << "您选择了上向预测";}else{cout << "您输入有误请重新输入";}}//左向预测8bit、4bit、2bit、1bit-计算差值与预测值for (int i = 0; i < frameHeight; i++){for (int j = 0; j < frameWidth; j++){if (x == 8){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 2;//进行量化c = b * 2;//进行反量化d = b + 128;//进行+128yChazhiBuf[j + i * frameWidth] = d;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 4){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 16;//进行量化c = b * 16;//进行反量化d = b + 16;//进行+64yChazhiBuf[j + i * frameWidth] = d*8;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 2){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 64;//进行量化c = b * 64;//进行反量化d = b + 4;//进行+4yChazhiBuf[j + i * frameWidth] = d*32;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}if (x == 1){if (j == 0){yYuceBuf[j + i * frameWidth] = yBuf[j + i * frameWidth];yChazhiBuf[j + i * frameWidth] = 0;}else{a = yBuf[j + i * frameWidth] - yYuceBuf[j + i * frameWidth - 1];//计算插值b = a / 128;//进行量化c = b * 128;//进行反量化d = b + 2;//进行+2yChazhiBuf[j + i * frameWidth] = d*64;yYuceBuf[j + i * frameWidth] = yYuceBuf[j + i * frameWidth - 1] + c;}}}}//上预测for (int i = 0; i < frameWidth; i++){for (int j = 0; j < frameHeight; j++){if (x == 99){if (j == 0){yYuceBuf[i] = yBuf[i];yChazhiBuf[i] = 0;}else{a = yBuf[i + j * frameWidth] - yYuceBuf[i + (j - 1) * frameWidth];//计算插值b = a / 2;//进行量化c = b * 2;//进行反量化d = b + 128;//进行+128yChazhiBuf[i + j * frameWidth] = d;yYuceBuf[i + j * frameWidth] = yYuceBuf[i + (j - 1) * frameWidth] + c;}}}}fwrite(yYuceBuf, frameWidth * frameHeight, 1, yuceFile);fwrite(yChazhiBuf, frameWidth * frameHeight, 1, chazhiFile);fwrite(Buf128, frameWidth * frameHeight / 2, 1, chazhiFile);fwrite(Buf128, frameWidth * frameHeight / 2, 1, yuceFile);fclose(chazhiFile);fclose(yuceFile);fclose(yuvFile);free(yBuf);free(yuvBuf);free(yYuceBuf);free(yChazhiBuf);free(Buf128);return 0;
}

5、实验结果分析

1)左向预测8bit、4bit、2bit、1bit结果对比


由图像可知,量化bit数的减少会导致插值边缘越来越不明显,并且得到的恢复图像与原始图像的差距也越来越大,与预期相符

1)上向预测8bit与左向预测8bit对比


由图可知,圈出的地方,上向预测是白,左向预测是黑,因为通过原图可看出,在这个部分,下侧像素比上侧像素要白,也就是下侧灰度值(down)大于上册灰度值(up),所以up-down为正值因此为白;而这个部分的右侧像素比左侧像素黑,也就是右侧像素值(right)小于左侧像素值(left),所以right-left为负值因此为黑。这样也就能分辨出上向预测与左向预测。

三、归纳总结

通过此次实验进一步了解DPCM编码,并完成了DPCM左向8bit、4bit、2bit、1bit以及上向8bit的代码实现。同时,经过详细分析左向预测8bit、4bit、2bit、1bit和上向预测8bit的实验结果,明白了其之间的差异,并会通过结果区分左向预测与上向预测。并且熟悉巩固了C++语言的使用,为后续进一步学习数据压缩打下了基础。

使用C++实现DPCM编码(左向预测8bit、4bit、2bit、1bit和上向预测8bit)(更新过)相关推荐

  1. [数据压缩]实验四 DPCM编码

    目录 一.实验框架 1.分析并实践DPCM压缩系统 2.掌握DPCM编解码系统原理,使用编程语言实现DPCM编码器. 二.DPCM编解码原理 DPCM函数(附) 三.DPCM编码系统设计 PSNR函数 ...

  2. DPCM编码算法实现

    目录 一.DPCM编解码原理 二.DPCM编码系统设计 三.算法实现 1.代码 2.运行结果 3.结果分析 一.DPCM编解码原理 DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统.在DPC ...

  3. 实验四——DPCM编码(1bit、2bit、4bit、8bit量化)

    一.实验要求 本实验的目标是验证DPCM编码的编码效率.首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差(本次实验报告使用左向预测),并对预测误差进行8比特均匀量化(基本要求).还可 ...

  4. [数据压缩]_实验③ DPCM编码

    实验4 DPCM压缩 文章目录 实验4 DPCM压缩 一.实验名称 二.实验目的 三.实验内容 1.DPCM编码原理 2.DPCM编码系统的设计 四.实验步骤 1.method.h头文件 2.main ...

  5. 6.1 Python图像处理之图像编码技术和标准-DPCM编码

    6.1 Python图像处理之图像编码技术和标准-DPCM编码 文章目录 6.1 Python图像处理之图像编码技术和标准-DPCM编码 1 算法原理 2 代码 3 效果 1 算法原理 预测编码利用的 ...

  6. dpcm matlab,matlab实现DPCM编码和游长编码

    实验2:编码解码 使用matlab实现对lena灰度图像和二值图像的DPCM编码和解码,以及游长编码的实现. 在进行编码之前,首先应该理解两种编码方式的原理.过程,梳理好之后再落实到代码上. 将图片的 ...

  7. DPCM编码进行图像压缩

    一.实验要求 本实验的目标是验证DPCM编码的编码效率.首先读取一个256级的灰度图像,采用自己设定的预测方法计算预测误差(本次实验报告使用左向预测),并对预测误差进行8比特均匀量化(基本要求).还可 ...

  8. 利用DPCM编码进行图像压缩

    一幅图像往往像素与像素之间是有关联的,比如说一张人脸的照片,肉色像素的隔壁基本还是肉色像素,那么这两个像素之间的差别就会很小.因此当我们处理一幅图片的时候,可以考虑到这种特性,在压缩时减小这种相关的空 ...

  9. DPCM编码算法的实现与分析

    目录 DPCM编解码原理 DPCM编码系统的设计 量化误差PSNR DPCM main.cpp 实验结果 实验总结 DPCM编解码原理 DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统.在D ...

最新文章

  1. Symfony学习笔记
  2. UA MATH566 统计理论 推导卡方拟合优度检验
  3. 深入浅出数据库设计三范式
  4. lol韩服游戏内设置_lol韩服游戏内设置界面翻译
  5. 关于数字证书理解的简单整理以及12306站点证书简单分析
  6. 【剑指 offer】—— 快速排序
  7. 59.Linux/Unix 系统编程手册(下) -- SOCKET: Internet Domain
  8. 掌门教育微服务体系 Solar(中)
  9. 【原创工具 | NetSM】开源跨平台命令行网速监测(纯 Python 开发)
  10. 市场上常见电阻阻值表
  11. 二元函数洛必达求极限_利用洛必达法则求二元函数的极限
  12. H3C IRF2的三种配置情况「转载」
  13. 【渝粤题库】陕西师范大学165109 绩效管理 作业(高起专)
  14. python爬取学籍信息_小学 学生学籍信息汇总及自动检查代码(Python)
  15. 淘宝618超级红包可以叠加使用吗?
  16. 播布客视频-Auditing笔记
  17. 《如何让你爱的人爱上你》第三部分:自尊
  18. 百度ueditor粘贴word图片且图片文件自动上传功能
  19. IOS TableViewCell分割线设置和隐藏多余cell
  20. DSO(1)——DSO论文详细解读

热门文章

  1. 服务器性能瓶颈分析方法
  2. Windows7查看本地Java安装是否成功和路径的方法
  3. Qt Creator基本快捷键
  4. 缩进一个字符_解析Word——Word段落格式中的几种缩进(中)
  5. ajax请求获取服务器数据,jquery.ajax发布从app引擎服务器获取数据的请求
  6. 云鲸扫拖一体机器人说明书_比老公更好用的扫拖一体机—自动洗拖布的云鲸扫拖机器人使用体验...
  7. Java黑皮书课后题第7章:***7.35(游戏:猜字词游戏)编写一个猜字词游戏,随机产生一个单词,当用户猜测正确后,正确的字母显示出来。当用户猜出一个单词,显示猜错的次数,并询问用户是否继续猜测
  8. Perfect World
  9. “==”和equals()那些事
  10. 【bzoj3442】学习小组 费用流