算术编码
一、什么是算术编码
算术编码是图像压缩的主要算法之一。 是一种无损数据压缩方法,也是一种熵编码的方法。和其它熵编码方法不同的地方在于,其他的熵编码方法通常是把输入的消息分割为符号,然后对每个符号进行编码,而算术编码是直接把整个输入的消息编码为一个数,一个满足(0.0 ≤ n < 1.0)的小数n。
二、算术编码的思想
算术编码(Arithmetic coding)的本质思想:对于更高频的符号,使用更短的编码。这样在对整个信息进行编码时,就可以进行大幅度压缩。
三、算术编码的编码过程:
我们假定一串字符序列为A A B A B C A B A B,共十个字符,且概率P(A) = 0.5,P(B) = 0.4,P( C ) = 0.1。
首先,算术编码会在[0,1)区间内对A B C进行区间划分,所以我们会先得到 A:[0, 0.5),B:[0.5, 0.9), C:[0.9, 1)这三个区间,接下来就可以进行算术编码了。
根据A B C初始时的区间和题目中给出的字符序列顺序(从左到右)进行编码。当每更新完一次A B C的区间后,根据下一个字符是A或者B或者C,来进行选择新的目标区间
(1)序列AABABCABAB的第1个字符为A,那么我们先选中了A的区间[0, 0.5)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0, 0.25), B:[0.25, 0.45), C:[0.45, 0.5)
你看,我们已经更新完了一次A B C的区间,则可以进行下一步,由于下一个字符是A,那么我们应该去选择A:[0, 0.25)作为新的目标区间。
(2)序列AABABCABAB的第2个字符为A,那么我们选中A的区间[0, 0.25)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0, 0.125), B:[0.125, 0.225), C:[0.225, 0.25)
(3)序列AABABCABAB的第3个字符为B,那么我们选中B的区间[0.125, 0.225)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.125, 0.175), B:[0.175, 0.215), C:[0.215, 0.225)
(4)序列AABABCABAB的第4个字符为A,那么我们选中A的区间[0.125, 0.175)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.125, 0.15), B:[0.15, 0.17), C:[0.17, 0.175)
(5)序列AABABCABAB的第5个字符为B,那么我们选中B的区间[0.15, 0.17)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.15, 0.16), B:[0.16, 0.168), C:[0.168, 0.17)
(6)序列AABABCABAB的第6个字符为C,那么我们选中C的区间[0.168, 0.17)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.168, 0.169), B:[0.169, 0.1698), C:[0.1698, 0.17)
(7)序列AABABCABAB的第7个字符为A,那么我们选中A的区间[0.168,0.169)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.168, 0.1685), B:[0.1685, 0.1689), C:[0.1689, 0.169)
(8)序列AABABCABAB的第8个字符为B,那么我们选中B的区间[0.1685,0.1689)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.1685, 0.1687), B:[0.1687, 0.16886), C:[0.16886, 0.1689)
(9)序列AABABCABAB的第9个字符为A,那么我们选中A的区间[0.1685, 0.1687)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.1685,0.1686), B:[0.1686, 0.16868), C:[0.16868, 0.1687)
(10)序列AABABCABAB的第10个字符为B,那么我们选中B的区间[0.1686, 0.16868)作为新的目标区间。我们对新目标区间,再按照ABC的概率占比进行划分:
A:[0.1686, 0.16864), B:[0.16864, 0.168672), C:[0.168672, 0.16868)
字符序列 A A B A B C A B A B,红色的区间代表 此区间是下一个目标区间 | |||||
字符顺序 |
当前字符 |
当前目标区间 |
A的区间 |
B的区间 |
C的区间 |
初始 |
初始 |
[0,1) |
[0, 0.5) |
[0.5, 0.9) |
[0.9, 1) |
第1个 |
A |
[0, 0.5) |
[0, 0.25) |
[0.25, 0.45) |
[0.45, 0.5) |
第2个 |
A |
[0, 0.25) |
[0, 0.125) |
[0.125, 0.225) |
[0.225, 0.25) |
第3个 |
B |
[0.125, 0.225) |
[0.125, 0.175) |
[0.175, 0.215) |
[0.215, 0.225) |
第4个 |
A |
[0.125, 0.175) |
[0.125, 0.15) |
[0.15, 0.17) |
[0.17, 0.175) |
第5个 |
B |
[0.15, 0.17) |
[0.15, 0.16) |
[0.16, 0.168) |
[0.168, 0.17) |
第6个 |
C |
[0.168, 0.17) |
[0.168, 0.169) |
[0.169, 0.1698) |
[0.1698, 0.17) |
第7个 |
A |
[0.168,0.169) |
[0.168, 0.1685) |
[0.1685, 0.1689) |
[0.1689, 0.169) |
第8个 |
B |
[0.1685,0.1689) |
[0.1685, 0.1687) |
[0.1687, 0.16886) |
[0.16886, 0.1689) |
第9个 |
A |
[0.1685, 0.1687) |
[0.1685,0.1686) |
[0.1686, 0.16868) |
[0.16868, 0.1687) |
第10个 |
B |
[0.1686, 0.16868) |
[0.1686, 0.16864) |
[0.16864, 0.168672) |
[0.168672, 0.16868) |
希望大家可以自己去算一算哈,当然我知道你们肯定不会去算。
当我们完成最后一个编码后,最终得到的目标区间为:[0.1686, 0.16868)。我们可以在这个区间内任意选一个小数作为最终的编码小数,但是计算机只能识别0和1两个数字,所以我们还需要将小数转成二进制。
我们的思想是:对于更高频的符号,使用更短的编码,这样在对整个信息进行编码时,就可以进行大幅度压缩。因此我们从[0.1686, 0.16868)选一个二进制表示最短的小数。
这里我们可以选择 0.16864013671875 这串小数,其二进制为: 0.00101011001011 。我们去掉整数位0以及小数点,得到最终的二进制编码为00101011001011,长度为14位,比哈夫曼编码更短1位。
四、算术编码的解码过程:
既然我们学了编码过程,那么我们也要学会解码过程
上面得到的二进制编码为00101011001011,加上整数位0以及小数点后还原为 0.00101011001011,通过进制转换可以得到对应的十进制编码小数是0.16864013671875
(1)我们先从初始区间A:[0, 0.5), B:[0.5, 0.9), C:[0.9, 1)中定位第一个字符,可以看出0.16864013671875位于A区间,所以第1个字符为A。
(2)我们接着对A:[0, 0.5) 进行划分:
A:[0, 0.25), B:[0.25, 0.45), C:[0.45, 0.5)
可以发现0.16864013671875仍然位于A区间,所以第2个字符仍然为A。
(3)我们接着对A:[0, 0.25)再进行划分:
A:[0, 0.125), B:[0.125, 0.225), C:[0.225, 0.25)
可以发现0.16864013671875位于B区间,所以第3个字符为B。
(4)我们接着对B:[0.125, 0.225)再进行划分:
A:[0.125, 0.175), B:[0.175, 0.215), C:[0.215, 0.225)
可以发现0.16864013671875 位于 A 区间,所以第4个字符为 A。
……
……
……
……
……
……
好了,这就相当于我们重复上面编码的过程,并依次类推,我们可以从0.16864013671875将整个字符解码出来,得到符号序列(从左侧开始排列)AABABCABAB。
(实际上是我累了不想CV上面的了)
好了,这就我为大家总结的算术编码的整个过程,希望能够帮助大家,博主先去吃饭了,有缘再会!
对了,给我点个赞谢谢!!!