熵编码.docx
《熵编码.docx》由会员分享,可在线阅读,更多相关《熵编码.docx(21页珍藏版)》请在冰豆网上搜索。
熵编码
熵编码
熵编码(entropyencoding)是一类利用数据的统计信息进行压缩的无语义数据流之无损编码。
本章先介绍熵的基本概念,然后介绍香农-范诺(Shannon-Fano)编码、哈夫曼(Huffman)编码、算术编码(arithmeticcoding)、行程编码(RLE)和LZW编码等常用的熵编码方法。
1熵
熵(entropy)本来是热力学中用来度量热力学系统无序性的一种物理量(热力学第二定律:
孤立系统内的熵恒增):
对可逆过程,
(孤立系统)
其中,S为熵、Q为热量、T为绝对温度。
(信息)熵H的概念则是美国数学家ClaudeElwoodShannon(香农/仙农/向农)于1948年在他所创建的信息论中引进的,用来度量信息中所含的信息量:
(为自信息量
的均值/数学期望)
其中,H为信息熵(单位为bit),S为信源,pi为符号si在S中出现的概率。
例如,一幅256级灰度图像,如果每种灰度的像素点出现的概率均为pi=1/256,则
即编码每一个像素点都需要8位(I),平均每一个像素点也需要8位(H)。
2Shannon-Fano编码
按照Shannon所提出的信息理论,1948年和1949年分别由Shannon和MIT的数学教授RobertFano描述和实现了一种被称之为香农-范诺(Shannon-Fano)算法的编码方法,它是一种变码长的符号编码。
●算法
Shannon-Fano算法采用从上到下的方法进行编码:
首先按照符号出现的概率排序,然后从上到下使用递归方法将符号组分成两个部分,使每一部分具有近似相同的频率,在两边分别标记0和1,最后每个符号从顶至底的0/1序列就是它的二进制编码。
●
表2符号在图像中出现的数目
例子
符号
A
B
C
D
E
出现的次数
15
7
7
6
5
例如,有一幅40个像素组成的灰度图像,灰度共有5级,分别用符号A、B、C、D和E表示,40个像素中各级灰度出现次数见表2。
如果直接用二进制编码,则5个等级的灰度值需要3位表示,也就是每个像素用3位表示,编码这幅图像总共需要40*3=120位。
按照香农理论,这幅图像的熵为
H=(15/40)×log2(40/15)+(7/40)×log2(40/7)+(7/40)×log2(40/7)
+(6/40)×log2(40/6)+(5/40)×log2(40/5)≈2.196
这就是说平均每个符号用2.196位表示就够了,40个像素共需用87.85位,压缩比约为3/2.196≈1.366:
1。
按照Shannon-Fano算法,先按照符号出现的频度或概率排序:
A、B、C、D、E,然后分成次数相近的左右两个部分——AB(22)与CDE(18),并在两边分别标记0和1(见图1)。
表3Shannon-Fano算法举例表
然后类似地再将AB分成A(15)与B(7)、CDE分成C(7)与DE(11),最后再把DE分成D(6)与E(5),参见图2和表3。
符号
次数(pi)
log2(1/pi)
编码
需位数
A
15(0.375)
1.4150
00
30
B
7(0.175)
2.5145
01
14
C
7(0.175)
2.5145
10
14
D
6(0.150)
2.7369
110
18
E
5(0.125)
3.0000
111
15
合计
40
(1)
12.1809
91
图2香农-范诺算法编码举例图
按照这种方法进行编码得到的总位数为91,平均码长为91/40=2.275,实际的压缩比为120/91≈1.319:
1。
3Huffman编码
●哈夫曼编码
Fano的学生DavidAlbertHuffman(哈夫曼/赫夫曼/霍夫曼)在1952年提出了一种从下到上的编码方法,它是一种统计最优的变码长符号编码,让最频繁出现的符号具有最短的编码。
1.编码过程
Huffman编码的过程=生成一棵二叉树(H树),树中的叶节点为被编码符号及其概率、中间节点为两个概率最小符号(串)的并所构成的符号串及其概率所组成的父节点、根节点为所有符号之串及其概率1。
2.编码步骤
(1)将符号按概率从小到大顺序从左至右排列叶节点;
(2)连接两个概率最小的顶层节点来组成一个父节点,并在到左右子节点的两条连线上分别标记0和1;
(3)重复步骤2,直到得到根节点,形成一棵二叉树;
(4)从根节点开始到相应于每个符号的叶节点的0/1串,就是该符号的二进制编码。
由于符号按概率大小的排列既可以从左至右、又可以从右至左,而且左右分枝哪个标记为0哪个标记为1是无关紧要的,所以最后的编码结果可能不唯一,但这仅仅是分配的代码不同,而代码的平均长度是相同的。
3.例子
仍以上小节的40像素的图像为例,来进行Huffman编码,参见图3和表4。
符号
次数(pi)
log2(1/pi)
编码
需位数
A
15(0.375)
1.4150
1
15
B
7(0.175)
2.5145
011
21
C
7(0.175)
2.5145
010
21
D
6(0.150)
2.7369
001
18
E
5(0.125)
3.0000
000
15
合计
40
(1)
12.1809
90
表4Huffman算法举例表
ABCDE
(1)
01
BCDE(0.625)
01
DE(0.275)BC(0.35)
0101
E(0.125)D(0.15)C(0.175)B(0.175)A(0.375)
图3Huffman编码过程例
平均码长为90/40=2.25,压缩比也为120/90=4/3≈1.333:
1。
●香农-范诺编码与哈夫曼编码
香农-范诺编码和哈夫曼编码都属于不对称、无损、变码长的熵编码。
1.同步代码
它们的码长虽然都是可变的,但却都不需要另外附加同步代码(即在译码时分割符号的特殊代码)。
如上例中,若哈夫曼编码的码串中的头两位为01,那末肯定是符号A,因为表示其他符号的代码没有一个是以01开始的,因此下一位就表示下一个符号代码的第1位。
同样,如果出现“000”,那么它就代表符号C。
如果事先编写出一本解释各种代码意义的“词典”,即码簿(H表),那么就可以根据码簿一个码一个码地依次进行译码。
2.问题
采用香农-范诺编码和哈夫曼编码时有两个问题值得注意:
⏹没有错误保护功能,在译码时,如果码串中有哪怕仅仅是1位出现错误,则不但这个码本身译错,而且后面的码都会跟着错。
称这种现象为错误传播(errorpropagation),计算机对这种错误也无能为力,不能知道错误出在哪里,更谈不上去纠正它。
⏹是可变长度码,因此很难在压缩文件中直接对指定音频或图像位置的内容进行译码,这就需要在存储代码之前加以考虑。
3.比较
与香农-范诺编码相比,哈夫曼编码方法的编码效率一般会更高一些。
尽管存在上面这些问题,但哈夫曼编码还是得到了广泛应用。
●H表与自适应哈夫曼编码
1.H表
利用哈夫曼方法进行编解码,在编码时需要计算造H表(哈夫曼表),存储和传输时需要存储和传输H表,解码时则需要查H表。
有时为了加快编码速度、减少存储空间和传输带宽,可以对多媒体数据使用标准的H表,但其压缩率一般比计算所造的表稍低。
所以,如果只关心编码速度、存储空间和传输带宽,可以采用标准H表方法;如果更关心压缩质量和压缩比,则可以自己计算造H表。
即使是计算造表,也一般只对高频符号计算编码,而对其他符号则直接编码。
这种方法尤其适用于有大量不同的输入符号,但只有少数高频符号的情况。
2.自适应哈夫曼编码
还有一种自适应哈夫曼编码(adaptiveHuffmancoding),不需要存储和传输H表,而是按与编码严格一致的方法建立同样的H表,还可以利用兄弟节点的特征来加快更新H树的过程。
由于时间有限,这里就不做详细介绍。
4算术编码
算术编码(arithmeticcoding)是由P.Elias于1960年提出雏形、R.Pasco和J.Rissanen于1976年提出算法,由Rissanen和G.G.Langdon于1979年系统化并于1981年实现,最后由Rissanen于1984年完善并发布的一种无损压缩算法。
从信息论上讲是与Huffman编码一样的最优变码长的熵编码。
其主要优点是,克服了Huffman编码必须为整数位,这与实数的概率值相差大的缺点。
如在Huffman编码中,本来只需要0.1位就可以表示的符号,却必须用1位来表示,结果造成10倍的浪费。
算术编码所采用的解决办法是,不用二进制代码来表示符号,而改用[0,1)中的一个宽度等于其出现概率的实数区间来表示一个符号,符号表中的所有符号刚好布满整个[0,1)区间(概率之和为1)。
把输入符号串(数据流)映射成[0,1)区间中的一个实数值。
●编码方法
符号串编码方法:
将串中使用的符号表按原编码(如字符的ASCII编码、数字的二进制编码)从小到大顺序排列成表,计算表中每种符号si出现的概率pi,然后依次根据这些符号概率大小pi来确定其在[0,1)期间中对应的小区间范围[xi,yi):
其中,p0=0。
显然,符号si所对应的小区间的宽度就是其概率pi。
参见图4。
s1s2......si......sm
0|x1p1y1|x2p2y2......xipiyi......xmpmym|1
图4算术编码的字符概率区间
然后对输入符号串进行编码:
设串中第j个符号cj为符号表中的第i个符号si,则可根据si在符号表中所对应区间的上下限xi和yi,来计算编码区间Ij=[lj,rj):
表5符号表
(符号及其概率与区间)
序号
符号
pi
[xi,yi)
1
d
0.1
[0.0,0.1)
2
e
0.1
[0.1,0.2)
3
h
0.1
[0.2,0.3)
4
l
0.3
[0.3,0.6)
5
o
0.2
[0.6,0.8)
6
r
0.1
[0.8,0.9)
7
w
0.1
[0.9,1.0)
其中,dj=rj-lj为区间Ij的宽度,l0=0,r0=1,d0=1。
显然,lj↑而dj与rj↓。
串的最后一个符号所对应区间的下限ln就是该符号串的算术编码值。
例如:
输入符号串为“helloworld”(10个字符),符号表含7个符号,按字母顺序排列,容易计算它们各自出现概率和所对应的区间,参见表5。
表6是对输入符号串“helloworld”的编码过程。
表6算术编码的编码过程表
序号
符号
li
ri
di
0
初值
0.0
1.0
1.0
1
h
(0.0+1.0*0.2=)0.2
(0.0+1.0*0.3=)0.3
(0.3-0.2=)0.1
2
e
(0.2+0.1*0.1=)0.21
(0.2+0.1*0.2=)0.22
(0.22-0.21=)0.01
3
l
(0.21+0.01*0.3=)0.213
(0.21+0.01*0.6=)0.216
(0.216-0.213=)0.003
4
l
(0.213+0.003*0.3=)0.2139
(0.213+0.003*0.6=)0.2148
(0.2148-0.2139=)0.0009
5
o
(0.2139+0.0009*0.6=)0.21444
(0.2139+0.0009*0.8=)0.21462
(0.21462-0.21444=)0.00018
6
w
0.214602
0.214620
0.0000018
7
o
0.2146128
0.2146164
0.00000036
8
r
0.21461568
0.21461604
0.000000036
9
l
0.214615788
0.214615896
0.0000000108
10
d
0.2146157880
0.2146157988
0.00000000108
编码输出为l10=0.2146157880。
算术编码的过程,也可以用图5的映射来表示。
dehlorw
0.00.10.20.30.60.80.91.0
hdhehhhlhohrhw
0.20.210.220.230.260.280.290.3
hedheehehhelheoherhew
0.210.2110.2120.2130.2160.2180.2190.22
heldhelehelhhellhelohelrhelw
0.2130.21330.21360.21390.21480.21540.21570.216
…………
helloworl
0.214615680.2146157880.2146158960.21461604
helloworld
0.2146157880.214615896
0.2146157880←输出0.2146157988
图5算术编码的过程
●解码方法
j
vj
i
cj=si
1
0.2146157880
3
h
2
(0.2146157880-0.2)/0.1=0.14615788
2
e
3
(0.14615788-0.1)/0.1=0.4615788
4
l
4
(0.4615788-0.3)/0.3=0.538596
4
l
5
(0.538596-0.3)/0.3=0.79532
5
o
6
(0.79532-0.6)/0.2=0.9766
7
w
7
(0.9766-0.9)/0.1=0.766
5
o
8
(0.766-0.6)/0.2=0.83
6
r
9
(0.83-0.8)/0.1=0.3
4
l
10
(0.3-0.3)/0.3=0.0
1
d
表7算术编码的解码过程表
由符号表(包括符号对应的概率与区间)和实数编码ln,可以按下面的解码算法来重构输入符号串:
设v1=ln=码值
若vj∈[xi,yi)→cj=si,j=1,…,n
vj+1=(vj-xi)/pi,j=1,…,n-1
例如上例的解码过程见下表7,重构输入符号串为v10=“helloworld”。
●若干说明
1.问题
在算术编码中需要注意的几个问题:
(1)由于实际计算机的浮点运算器不够长(一般为80位),可用定长的整数寄存器低进高出来接收码串,用整数差近似实数差来表示范围,但可能会导致误差积累。
(2)算术编码器对整个消息只产生一个码字,这个码字是在间隔[0,1)中的一个实数,因此译码器在接受到表示这个实数的所有位之前不能进行译码。
(3)算术编码也是一种对错误很敏感的编码方法,如果有一位发生错误就会导致整个字符序列被译错。
2.静态与自适应
算术编码可以是静态的或者自适应的。
在静态算术编码中,信源符号的概率是固定的。
在自适应算术编码中,信源符号的概率根据编码时符号出现的频繁程度动态地进行修改。
需要开发动态算术编码的原因是因为事先知道精确的信源概率是很难的,而且是不切实际的。
当压缩数据时,我们不能期待一个算术编码器获得最大的效率,所能做的最有效的方法是在编码过程中估算概率,它成为确定编码器压缩效率的关键。
5RLE
行程编码RLE(RunLengthEncoding游程长度编码)是一种使用广泛的简单熵编码。
它被用于BMP、JPEG/MPEG、TIFF和PDF等编码之中,还被用于传真机。
●RLE的编码方法
RLE视数字信息为无语义的字符序列(字节流),对相邻重复的字符,用一个数字表示连续相同字符的数目(称为行程长度),可达到压缩信息的目的。
如
未压缩的数据:
ABCCCCCCCCDEFFGGG
RLE编码:
AB8CDEFF3G
对比该RLE编码例前后的代码数可以发现,在编码前要用17个代码表示的数据,而编码后只要用10个代码,压缩比为1.7:
1。
这说明RLE确实是一种压缩技术,而且这种编码技术相当直观,也非常经济。
RLE所能获得的压缩比有多大,这主要是取决于数据本身的特点。
如果图像数据(如人工图形)中具有相同颜色的图像块越大,图像块数目越少,获得的压缩比就越高。
反之(如自然照片),压缩比就越小。
RLE译码采用与编码相同的规则,还原后得到的数据与压缩前的数据完全相同。
因此,RLE是一种无损压缩技术。
RLE压缩编码特别适用于计算机生成的图形,对减少这类图像文件的存储空间非常有效。
然而,RLE对颜色丰富多变的自然图像就显得力不从心,这时在同一行上具有相同颜色的连续像素往往很少,而连续几行都具有相同颜色值的连续行数就更少。
如果仍然使用RLE编码方法,不仅不能压缩图像数据,反而可能使原来的图像数据变得更大。
表8BMP的RLE编码信息单位的组成1
但是,这并不意味着RLE编码方法在自然图像的压缩中毫无用处,恰恰相反,在各种自然图像的压缩方法中(如JPEG),仍然不可缺少RLE。
只不过,不是单独使用RLE一种编码方法,而是和其他压缩技术联合应用。
第一字节
>0:
重复的像素数
第二字节
BI_RLE8:
一个颜色索引值(8b)
BI_RLE4:
两个颜色索引值(各4b,高4位为第一个像素,低4位为第二个像素)
●BMP中的RLE
1.编码
在BMP文件中,对16色和256色的普通格式的位图可进行RLE压缩(BI_RLE4和BI_RLE8),编码由若干信息单位构成,每个信息单位有2个字节。
信息单位的第一个字节一般为同一颜色索引的像素数,这时第二个字节对BI_RLE8为一个颜色索引(8b),对BI_RLE4为两个颜色索引(各4b,高4位为第一个像素,低4位为第二个像素)。
参见表8。
第一字节
0:
特殊含义
第二字节
0:
线结束
1:
位图结束
2:
偏移(后跟的两个字节分别表示从当前位置向右和向下偏移的像素数)?
3~255:
后跟的未压缩的像素(色索引)数
表9BMP的RLE编码信息单位的组成2
若信息单位的第一个字节为0,这时,第二个字节表示特殊意义:
0—线结束、1—位图结束、2—偏移(后跟的两个字节分别表示从当前位置向右和向下偏移的像素数)、3~255—后跟的未压缩的像素(颜色索引)数(填充到双字节边界,不足时补0)。
参见表9。
2.例子
1)BI_RLE8
CompresseddataExpandeddata
0304040404
05060606060606
000345566700455667
02787878
00020501Move5rightand1down
02787878
0000Endofline
091E1E1E1E1E1E1E1E1E1E
0001EndofRLEbitmap
2)BI_RLE4
CompresseddataExpandeddata
0304040
050606060
000645566700455667
04787878
00020501Move5rightand1down
04787878
0000Endofline
091E1E1E1E1E1
0001EndofRLEbitmap
6LZW算法
LZW算法被GIF和PNG格式的图像压缩所采用,并被广泛应用于文件的压缩打包(如ZIP和RAR)和磁盘压缩。
因为它不需要执行那么多的缀符串比较操作,所以LZW算法的速度比LZ77算法的快。
对LZW算法进一步的改进是增加可变的码字长度,以及在词典中删除老的缀符串。
在GIF图像格式和各种文件和磁盘压缩程序中已经采用了这些改进措施之后的LZW算法。
LZW是一种专利算法,专利权的所有者是美国的一个大型计算机公司——Unisys(优利系统公司)。
不过,除了商业软件生产公司需要支付专利费外,个人则是可以免费使用LZW算法的。
●概述
1977年以色列JakobZiv和AbrahamLempel提出了一种基于词典编码的压缩缩法,称为LZ77算法;1978年他们对该算法作了改进,称为LZ78;1984年TerryA.Weltch又对LZ78进行了实用性修正,因此把这种编码方法称为LZW(Lempel-ZivWalch)算法。
1.词典编码的思想
词典编码(dictionaryencoding)的根据是数据(字符串)本身包含有重复代码块(词汇)这个特性。
词典编码法的种类很多,可以分成两大类。
第一类词典编码的想法,是试图查找正在压缩的字符序列(词汇)是否在以前输入的数据中出现过,然后用已经出现过的字符串替代重复的部分,它的输出仅仅是指向早期出现过的字符串(词汇)的“指针”,参见图6。
图6第一类词典编码概念
第二类词典编码的想法,是试图从输入的数据中创建一个“短语词典(dictionaryofthephrases)”,这种“短语”(词汇/单词)不一定是像“computer计算机”和“programming程序设计”这类具有具体含义的短语,它可以是任意字符的组合。
编码数据过程中当遇到已经在词典中出现的“短语”时,编码器就输出这个词典中的短语的“索引号”,而不是短语本身,参见图7。
图7第二类词典编码概念
2.LZW与LZ78
LZ78是首个第二类词典编码,1984年提出的LZW压缩编码也属于这类编码,它是对LZ78进行了实用性修正后提出的一种逻辑简单、速度快、硬件实现廉价的压缩算法,并首先在高速硬盘控制器上应用了这种算法。
在LZW算法中使用的术语与LZ78使用的相同,仅增加了一个术语—前缀根(Root),它是由单个字符串组成的缀符串(String)。
在编码原理上,LZW与LZ78相比有如下差别:
①LZW只输出代表词典中的缀符串(String)的码字(codeword)。
这就意味在开始时词典不能是空的,它必须包含可能在字符流出现中的所有单个字符,即前缀根(Root)。
②由于所有可能出现的单个字符都事先包含在词典中,每个编码步骤开始时都使用1个字符的前缀(one-characterprefi