1. 算法描述

功能:

  给定概率字典以及待编码字符串,求出该字符串算术编码的结果(最短二进制串),并能根据算数编码结果进行解码,得到原字符串。

2.算法流程:

算术编码流程:

  (1) 首先,初始化概率区间上下界分别为1和0。读入第一个字符,并根据该字符的概率区间更新当前区间,具体方法为:
upper_bound=lower_bound+intervalLength∗probDict[chr][1]lower_bound=lower_bound+intervalLength∗probDict[chr][0]upper\_bound = lower\_bound + intervalLength * probDict[chr][1]\\ lower\_bound = lower\_bound + intervalLength * probDict[chr][0] upper_bound=lower_bound+intervalLength∗probDict[chr][1]lower_bound=lower_bound+intervalLength∗probDict[chr][0]
其中intervalLengthintervalLengthintervalLength表示当前区间长度,probDict[chr][1],probDict[chr][0]probDict[chr][1], probDict[chr][0]probDict[chr][1],probDict[chr][0]分别表示当前字符的概率区间上下界。

  (2) 然后,继续读入下一字符并不断更新当前概率区间,直到最后一个字符处理完毕后退出循环,得到最终的概率区间。

  (3) 根据最终概率区间求出该区间内的最短二进制串,方法如下:从第一个二进制位开始,若当前位置1得到的数大于区间上界,则将该位置0;若当前位置1得到的数恰好在区间内(即恰好大于下界),则该位置1不变,然后直接出循环,无需生成后续的位数;若当前位置1得到的数小于下界,则该位置1。如此可保证求出的二进制串必为该区间内的最短二进制串。

算术解码流程:

  (1) 将编码得到的二进制串转为十进制小数,记作encodedDecencodedDecencodedDec。

  (2) 先看encodedDecencodedDecencodedDec落在哪个字符的概率区间内,若它落在字符ccc的概率区间内,则解码出的第一个字符即为ccc。

  (3) 接下来,继续对当前区间进行划分,得到概率字典中各字符的新概率区间,再看现在encodedDecencodedDecencodedDec落在哪个字符对应的区间内,则第二个解码出的字符就是该字符。

  (4) 重复步骤(3)直到循环次数达到字符串长度,完成解码过程。

求区间内的最短二进制串流程:

  从小数点后第一位开始往后:若该位置1得到的数大于区间上界,则将该位置0;若当前位置1得到的数恰好在区间内(即恰好大于下界),则该位置1不变,然后直接出循环,无需生成后续的位数;若当前位置1得到的数小于下界,则该位置1。

3. 核心代码

# 算术编码函数:输入为字符串和概率字典,返回最终区间的上下界
def arithEncode(string, probDict):lower_bound = Decimal('0.0')upper_bound = Decimal('1.0')for chr in string:intervalLength = upper_bound - lower_bound  # 区间长度# 不断更新区间上下界,注意必须先更新上界,否则会导致上界更新错误(因为上界的计算用的是上一次的下界)upper_bound = lower_bound + intervalLength * probDict[chr][1]lower_bound = lower_bound + intervalLength * probDict[chr][0]print(lower_bound, upper_bound)# 返回最终区间的上下界return lower_bound, upper_bound# 求出最终区间内的最短二进制串
def dec2Bin(lower_bound, upper_bound):binStr = ''# 初始化01串转为的二进制数为0.0temp = Decimal(0.0)  i = 1  # 初始化幂为1while(1):bit = 1# 若当前位 置1 得到的数大于区间上界,则将该位 置0,temp不变if((temp + Decimal(1 / (2 ** i) * bit)) > upper_bound):bit = 0binStr += '0'# 若当前位 置1 得到的数恰好在区间内(即恰好大于下界),则该位 置1 不变,然后直接出循环,无需生成后续的位数else:if((temp + Decimal(1 / (2 ** i) * bit)) > lower_bound):binStr += '1'break# 若当前位 置1 得到的数小于下界,则该位 置1 else:binStr += '1'# 更新temptemp += Decimal(1 / (2 ** i) * bit)# 阶数自增1,下一轮循环时用i += 1return binStr# 二进制串转十进制小数(乘二取整)
def bin2Dec(bin):dec = Decimal(0.0)for i in range(len(bin)):if(bin[i] == '1'):dec += Decimal(1 / (2 ** (i + 1)))# 这里返回的数据类型一定要是Decimalreturn dec# 算术解码函数:输入为已编码二进制串、概率字典、字符串长度,返回解码后的字母串
def arithDecode(encodedBin, probDict, strLength):decodedStr = ''# probDict_copy存放原始的概率字典probDict_copy = deepcopy(probDict)# 二进制串转十进制小数encodedDec = bin2Dec(encodedBin)# 因为要解码出strLength个字符,所以共循环strLength次for _ in range(strLength):# 如果编码数字落在某个字符的概率区间内,则在结果中加入该字符for chr, interval in probDict.items():if((encodedDec >= interval[0]) & (encodedDec < interval[1])):decodedStr += chr# 继续对当前区间划分,看编码数字落在哪个字符对应的区间内# 更新字典中各字符的概率区间temp_lower_bound = interval[0]    # 记录当前区间下界和区间长度intervalLength = interval[1] - interval[0]for chr in probDict.keys():probDict[chr][0] = temp_lower_bound + intervalLength * probDict_copy[chr][0]probDict[chr][1] = temp_lower_bound + intervalLength * probDict_copy[chr][1]breakreturn decodedStr

4. 实验结果

  结果分析:用户输入待编码各字符、各字符的概率以及需要编码的字符串,程序会先构造出概率字典,然后输出算数编码的最终结果,即最短二进制串和对应的十进制浮点数。在编码成功后,程序对编码得到的二进制串解码,最终的解码结果与原字符串一致,说明解码准确率为100%。从程序运行的结果可以看到,本实验成功实现了对给定概率字典的字符串的无损算术编码及解码。

5. 分析与总结

 1. 通过本次实验,我掌握了算术编码及解码的基本算法思想,并通过编程实现了算数编码及解码的过程,提高了自己的动手实践能力,对于Python语言中的float、Decimal等数据类型的概念和用途有了更深的理解。

  2. 题目要求我们求出在最终概率区间内的最短二进制串作为算术编码结果,但我一开始没有想到最短二进制串的求法,于是我在草稿纸上从小数位第一位开始逐位向后推算,看每一位上1和上0后得到的十进制数在不在概率区间内,最后推出了求最短二进制串的算法。其实我们在碰到看起来不会解决的问题时,不妨先静下心来拿出纸笔演算几步,说不定就能得出解法,而不是对着电脑在大脑里思考,这样做效率是很低下的。

  3. 在写算术编码函数的时候,按照算法流程,我们需要反复更新概率区间的上下界,在这个过程中我们是利用上一次的概率区间下界以及当前字符的概率区间上下界去更新的。我一开始在写这个函数的时候,没注意到必须要先更新upper_bound再更新lower_bound,而是先更新了lower_bound。这么做会导致新的区间上界是用新的区间下界更新的,而不是用上一次的下界更新的,后来我调试的时候发现了这一错误并且改正了。

  4. 关于数据类型的收获:Python中的float类型无法在任意指定的小数位上保持精确,因此在实验过程中所有的数值均转化为了Decimal类型,以保证精确计算(Decimal的精度默认是28位)。在对于运行效率要求不是很高而对于精度要求很高时,可以使用Decimal保精度,若对于运行效率的要求较高而不怎么在意精度,则使用float类型也无妨。

多媒体数据处理实验1:算术编码相关推荐

  1. 算术编码 matlab程序,实验二算术编码及MATLAB实现.doc

    实验二算术编码及MATLAB实现 武夷学院实验报告 课程名称: 多媒体通信技术 项目名称: 算术编码及MATLAB实现 姓名: _专业:__通信工程___ 班级: 学号:____同组成员_无_ 实验准 ...

  2. 算术编码(多媒体实验一)

    算术编码(xdu多媒体实验一) 前言 详细原理 源代码 前言 算术编码(多媒体实验一) sklearn主成分分析pca用python实现(多媒体实验二) BOW图像检索corel数据集(多媒体实验三) ...

  3. 信息论与编码实验报告——MATLAB实现算术编码

    一.实验内容 试用MATLAB编制算术编码算法实现程序. 二.实验过程 2.1 算术编码实现原理 算术编码的算法思想如下: (1)对一组信源符号按照符号的概率从大到小排序,将[0,1)设为当前分析区间 ...

  4. 数据处理方法-算术编码(香农算法、java编码实现)

    一.算术编码起源 早在1948年,香农就提出将信源符号依美出现的概率降序排序,用符号序列累计概率的二进值作为对信源的编码,并从理论上论证了它的优越性.1960年,Peter Elias 发现无需排序, ...

  5. 算术编码(matlab)上课实验

    clear all format long symbol='abcd'; pr=[0.1 0.4 0.2 0.3]; seqin='aabccddcd'; codeword=arenc(symbol, ...

  6. (Matlab源码)Matlab实现算术编码(Arithmetic coding)超级详解(每一段代码都可以看懂)

    1.代码功能 输入:一个字符串 输出: codeword(码值) codeword所占的位数 2.代码框图 3.代码超详解 统计字符串中的字符种类,调用函数,放入数组b中. b=unique(str1 ...

  7. 算术编码算法的程序实现

    实验目的     本实验通过编程实现简单的算术编码解码过程,加深对视频编码中熵编码原理及过程的理解,锻炼理论与实践相联系的能力. 实验任务 理解算术编码的有关原理,尤其是自适应二元算术编码的原理及编码 ...

  8. 基于Python的算术编码的设计与实现

    基于Python的算数编码实验 一.实验目的 给出算术编码实现的详细原理. 编制编解码程序 设计并实现自适应算术编码(选做) 二.实验环境 硬件环境:windows 10; VScode 编程语言:p ...

  9. 机器学习类别/标称(categorical)数据处理:独热编码(One Hot Encoding)

    机器学习类别/标称(categorical)数据处理:独热编码(One Hot Encoding) 序号编码:序号编码通常用于处理类别间具有大小关系的数据 可以通过导入sklearn.preproce ...

  10. matlab怎么求残余误差,误差理论与数据处理实验报告.doc

    误差理论与数据处理实验报告 <误差理论与数据处理>实 验 指 导 书 姓名 学号 机械工程学院 2016年05月 实验一 误差的基本性质与处理 一.实验内容 1.对某一轴径等精度测量8次, ...

最新文章

  1. 面向Mobile device的CNN模型手工设计与NAS分析总结,MobileNet V1,V2,V3,Efficient,MNasNet以及Efficient network design
  2. 上传文本到hdfs上的一些命令
  3. 教你一招看清编程语言的发展趋势及未来方向
  4. 【算法】剑指 Offer 40. 最小的k个数 【重刷】
  5. SAP自学指南:案例公司的特点
  6. SQL Server数据库迁移–将数据库克隆到另一个排序规则
  7. Go、Java、C++,下一代测序工具开发谁更强?
  8. django开发-在Docker中部署django项目
  9. html当当图书榜页面,2019书排行榜_当当网图书排行榜
  10. Springboot毕设项目会议预约系统设计与实现3if68(java+VUE+Mybatis+Maven+Mysql)
  11. 亿佰特Wifi模块、蓝牙模块和Zigbee模块协议在物联网智能家居上的应用指南
  12. CSS 3之网页背景颜色
  13. HackTheBox-Chaos-CTF_解题过程
  14. SECOND点云检测代码详解
  15. html5及CSS的学习2
  16. 东华大学计算机学院刘国华,东华大学计算机科学与技术学院研究生导师简介-刘国华??(教授)...
  17. 多语种互译批量中英文翻译插件
  18. 但愿能带给你们一丝丝的温暖
  19. 力扣第185场周赛总结——字节跳动专场
  20. Linux 中 4 款炫酷的终端应用程序

热门文章

  1. HCNA学习的第二天
  2. 在万能地图下载器中如何不显示谷歌电子地图上的地名文字?
  3. Spring定时器 cron详解
  4. linux连接苹果鼠标,Linux 5.13添加对苹果Magic Mouse 2和微软SAM的支持
  5. 朋友圈加粗字体数字_如何让你的朋友圈骚到脱颖而出?
  6. freewitch测试信息-cdr
  7. C语言每个语句的最后必须有一个分号,C语言选择题附答案
  8. DHCPv6 snooping
  9. 自媒体采集平台免费,免费的自媒体采集平台
  10. catia重心主惯量矩 m1_CATIA_Knowledge_Advisor_help