熵编码系列目录
熵编码-熵编码概述
熵编码-指数哥伦布熵编码
熵编码-算数编码
1. 前言
通过熵编码系列第一篇文章熵编码-熵编码概述,我们了解了熵编码的概念和分类。本篇文章主要介绍算术编码。
2. 什么是算术编码
算术编码是图像压缩的主要算法之一,是一种熵编码算法。和其他熵编码方法不同,其他熵编码采用将输入信号分割成符号再对每个符号进行编码,而算术编码是直接将整个输入信号编码为一个满足(0.0<=n<1)的浮点数n。
3. 算术编码步骤
输入序列: aabbc, 概率p(a)=0.4, p(b)=0.4, p©=0.2
算术编码会在初始编码区间[0,1)按照概率对符号进行编码区间划分
a:[0, 0.4), b:[0.4, 0.8), c:[0.8, 1.0)
根据字符初始编码区间和输入序列顺序进行编码。通过输入字符选择新的目标编码区间,并按照字符概率重新更新字符编码区间。
1.字符序列第1个字符a,选择a的区间[0, 0.4)作为新的目标编码区间,并按照字符概率重新划分字符编码区间
a:[0, 0.16), b:[0.16, 0.32), c:[0.32, 0.4)
2.字符序列第2个字符a,选择a的区间[0, 0.16)作为新的目标编码区间,并按照字符概率重新划分字符编码区间
a:[0, 0.064), b:[0.064, 0.128), c:[0.128, 0.16)
3.字符序列第3个字符b,选择a的区间[0.064, 0.128)作为新的目标编码区间,并按照字符概率重新划分字符编码区间
a:[0.064, 0.0896), b:[0.0896, 0.1152), c:[0.1152, 0.128)
4.字符序列第4个字符b,选择b的区间[0.0896 0.1152)作为新的目标编码区间,并按照字符概率重新划分字符编码区间
a:[0.0896, 0.09984), b:[0.09984, 0.111008), c:[0.111008, 0.1152)
5.字符序列第5个字符c,选择c的区间[0.111008, 0.1152)作为新的目标编码区间
算数编码
序列 | 目标编码区间 | a编码区间 | b编码区间 | c编码区间 |
---|---|---|---|---|
初始 | [0, 1) | [0, 0.4) | [0.4, 0.8) | [0.8, 1.0) |
a | [0, 0.4) | [0, 0.16) | [0.16, 0.32) | [0.32, 0.4) |
a | [0, 0.16) | [0, 0.064) | [0.064, 0.128) | [0.128, 0.16) |
b | [0…064, 0.128) | [0,.064, 0.0896) | [0.0896, 0.1152) | [0.1152, 0.128) |
b | [0.0896 0.1152) | [0.0896, 0.09984) | [0.09984, 0.111008) | [0.111008, 0.1152)) |
c | [0.111008, 0.1152) |
完成最后一个字符编码得到最终编码区间[0.111008, 0.1152),可以在该区间选择任意一个小数作为最终的编码小数。由于计算机智能识别二进制码,因此我们还需要将小数转化为二进制码。
因为是最短压缩,所以需要在[0.111008, 0.1152)选择一个二进制最短的小数
选择最短二进制小数
将10进制区间[0.111008, 0.1152)转换为二进制区间[0.0001110001101011, 0.0001110101111101), 取区间起点终点二进制相同部分,直到不相同为止(0.0001110)并尾部添加1,小数二进制是0.00011101(0.11328125),去掉整数位最终的二进制码是00011101,比特长度是8位。
4. 算术解码步骤
理解了上述编码流程之后,那么解码流程也就可以实现了。上文的浮点数二进制00011101,加上小数点还原成10进制数是0.11328125,概率p(a)=0.4, p(b)=0.4, p©=0.2,输入序列有5个字符
算术解码会在初始编码区间[0,1)按照概率对符号进行编码区间划分
a:[0, 0.4), b:[0.4, 0.8), c:[0.8, 1.0)
根据浮点数判断选择对应的目标区间和确认输入字符,再按照字符概率重新更新字符编码区间
- 浮点数0.11328125选择a的区间[0, 0.4)新的编码区间,确认输入序列1个字符a;按照字符概率重新划分字符编码区间
a:[0, 0.16), b:[0.16, 0.32), c:[0.32, 0.4)
- 浮点数0.11328125选择a的区间[0, 0.16)新的编码区间,确认输入序列2个字符a;按照字符概率重新划分字符编码区间
a:[0, 0.064), b:[0.064, 0.128), c:[0.128, 0.16)
- 浮点数0.11328125选择b的区间[0.064, 0.128)新的编码区间,确认输入序列3个字符b;按照字符概率重新划分字符编码区间
a:[0.064, 0.0896), b:[0.0896, 0.1152), c:[0.1152, 0.128)
4.浮点数0.11328125选择b的区间[0.0896, 0.1152)作为新的编码区间,确认输入序列4个字符b;按照字符概率重新划分字符编码区间
a:[0.0896, 0.09984), b:[0.09984, 0.111008), c:[0.111008, 0.1152)
5.浮点数0.11328125选择c的区间[0.111008, 0.1152)作为新的编码区间,确认输入序列5个字符c;按照字符概率重新划分字符编码区间
最终确定输入序列是aabbc
5. 算数编码的原理
通过上文我们实现了算数编码&解码的步骤。但是为什么算数编码可以压缩数据呢?
算数编码的目的是要在最终的目标区间内找出最短二进制编码作为最终编码。最终目标区间越大,可容纳小数精度越低,从而找到的最终二进制小数越短。例如[0.4, 0.5)区间和[0.44532689,0.52345678)区间各找一个最短二进制小数,肯定是[0.4, 0.5)区间找到的最短二进制编码
因此算数编码的实现方式就是:尽量使最终的目标区间更大。因为高频字符出现多,低频字符出现少。因此给高频字符分配较大的编码区间,低频字符分配较小的编码区间,从而使得最终的目标区间更大。
总结:算数编码的压缩本质是对高频字符赋予更大的编码区间,从而实现压缩数据的目的