声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 1900|回复: 4

[综合讨论] 求教算术编码和解码的程序块

[复制链接]
发表于 2006-4-21 10:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
看了看算术编码和解码的基本原理,但是如何实现程序有些困难,导师叫我去查看David Salomon 的那本书  数字压缩原理与应用,那里有个算术编码很实用,叫我去按那个方法写程序!!<BR>本人也是刚接触MATLAB,还不熟练,请问哪位大虾对次方面很熟悉,感激不尽!~

[ 本帖最后由 lxq 于 2007-6-7 17:49 编辑 ]
回复
分享到:

使用道具 举报

发表于 2006-4-21 22:02 | 显示全部楼层

回复:(jingang159)求教算术编码和解码的程序块

<P>%I=imread('001.bmp') <BR>%imshow(I); <BR>clear <BR>I=[3 3 1 1 3 3 1 2;2 3 3 1 3 2 3 2;1 2 3 3 3 3 1 2]; <BR>%I=[1 1 1 1 0 0 1 0 1 1 1 0]; <BR>[m,n]=size(I); <BR>% 第一列为灰度值,第二列为个数,第三列为概率百分数,应该也可以用imhist <BR>table = tabulate(I(:)); % 注意的是,tabulate要求I的元素必须为非负整数 <BR>% 否则,以采用如下方法求解 <BR>% 如[1 2 3;1 2 2],则统计出结果1是2个,2是3个,3是1个 <BR>% sortM=sort(M(:)); <BR>% uniqueM=([diff(sortM);1]&gt;0); <BR>% count = [sortM(uniqueM) diff(find([1;uniqueM]))] </P>
<P>% 即color,p如下所示 <BR>color = table(:,1)'; <BR>p = table(:,3)'/100; </P>
<P>% 计算上下限 <BR>csump = cumsum(table(:,3)'); <BR>allLow =[0,csump(1:end-1)/100]; <BR>allHigh = csump/100; </P>
<P>numberlow = 0; <BR>numberhigh = 1; </P>
<P>for k = 1:m <BR>for kk = 1:n <BR>data = I(k,kk); <BR>low = allLow(data==color); <BR>high = allHigh(data==color); <BR>range = numberhigh-numberlow; <BR>tmp = numberlow; <BR>numberlow = tmp+range*low; <BR>numberhigh = tmp+range*high; <BR>end <BR>end <BR>% the result range <BR>fprintf('算术编码范围下限为%16.15f\n\n',numberlow); <BR>fprintf('算术编码范围上限为%16.15f\n\n',numberhigh); </P>
<P><BR>% decoding <BR>Mat = zeros(m,n); <BR>for k = 1:m <BR>for kk = 1:n <BR>indx = numberlow indx = [indx 1]; <BR>ind = diff(indx); <BR>ind = logical(ind); <BR>Mat(k,kk) = color(ind); <BR>low = allLow(ind); <BR>high = allHigh(ind); <BR>range = high - low; <BR>numberlow = numberlow-low; <BR>numberlow = numberlow/range; <BR>end <BR>end </P>
<P>fprintf('原矩阵为:\n') <BR>disp(I); <BR>fprintf('\n'); <BR>fprintf('解码矩阵:\n'); <BR>disp(Mat); </P>
<P>附 <BR>算术编码与译码原理: <BR>1、 编码过程 <BR>算术编码方法是将被编码的一则消息或符号串(序列)表示成0和1之间的一个间隔(Interval),即对一串符号直接编码成[0,1]区间上的一个浮点小数。符号序列越长,编码表示它的间隔越小,表示这一间隔所需的位数就越多。信源中的符号序列仍然要根据某种模式生成概率的大小来减少间隔。可能出现的符号概率要比不太可能出现的符号减少范围小,因此,只正加较少的比特位。 <BR>在传输任何符号串之前,0符号串的完整范围设为[0,1]。当一个符号被处理时,这一范围就依据分配给这一符号的那一范围变窄。算术编码的过程,实际上就是依据信源符号的发生概率对码区间分割的过程。 <BR>举例说明如下: <BR>假设一则消息“static_tree”具有如下的概率分布: <BR>             字符                   概率 <BR>     --------------------------------------------------------------- <BR>            _(space)             0.1 <BR>             a                      0.1 <BR>             e                      0.3 <BR>             r                      0.1 <BR>             s                      0.1 <BR>             t                      0.3 <BR>下面用算术编码方法给该消息编码。 <BR>一旦字符的概率已知,就沿着“概率线”为每一个单独的符号设定一个范围,哪一个被设定到哪一段范围并不重要,只要编码和解码都以同样方式进行就可以,这里所用的6个字符被分配的范围(range)如下: <BR>     字符             概率             范围 <BR>   _(space)          0.1            0≤r&lt;0.1 <BR>      a               0.1            0.1≤r&lt;0.2 <BR>      e               0.3            0.2≤r&lt;0.5 <BR>      r               0.1            0.5≤r&lt;0.6 <BR>      s               0.1            0.6≤r&lt;0.7 <BR>      t               0.3            0.7≤r&lt;1.0 <BR>     ---------------------------------------------------------------- <BR>          对“state_tree”的算术编码过程为: <BR>(1) 初始化时,被分割的范围range=high-low=[0,1),下一个范围的低、高端分别由下式计算: <BR>             Low=low+range×range low <BR>             High=low+range×range high <BR>其中等号右边的low为上一个被编码字符的范围低;range low和range high分别为被编码符号已给定的字符出现概率范围的low和high。 <BR>(2) 对消息第一字符s编码:s的range low=0.6,         s的range high=0.7因此,下一个区间的low和high为: <BR>                Low=low+range×range low=0+1×0.6=0.6 <BR>                High=low+range×range high=0+1×0.7=0.7 <BR>                  Range=high-low=0.7-0.6=0.1 <BR>                  S将区间[0,1)=&gt;[0.6,0.7) <BR>      (3)对第二个字符t编码,使用的新生范围为[0.6,0.7),因为t的range low=0.7,range high=1.0,因此下一个low,high分别为 <BR>                   Low=0.6+0.1×0.7=0.67 <BR>                   High=0.6+0.1×1.0=0.70 <BR>                   Range=0.7-0.67=0.03 <BR>                   t将[0.6,0.7)=&gt;[0.67,0.70) <BR>       (4)对第三个字符a编码,在新生成的[0.67,0.70)中进行分割,因为a的range low=0.10,range high=0.2,因此下一个low,high分别为 <BR>                   Low=0.67+0.03×0.1=0.673 <BR>                   High=0.67+0.03×0.2=0.676 <BR>                   Range=0.676-0.673=0.003 <BR>                   a将[0.67,0.70)=&gt;[0.673,0.676) <BR>        (5)对第四个字符t编码,在新生成的[0.673,0.676)上进行分割。因为t的range low=0.70,range high=1.0,则下一个low,high分别为 <BR>                   Low=0.673+0.003×0.7=0.6751 <BR>                   High=0.673+0.003×1.0=0.676 <BR>                   Range=0.0009 <BR>                   t将[0.673,0.676)=&gt;[0.6751,0.676) <BR>         同理得到下面各字符e,_,s,t,r,e,e编码所得到的范围分别为[0.67528,0.67555),[0.67528,0.675307),[0.675 298 9,0.675 307),[0.675 302 95,0.675 303 76),[0.675 303 112,0.675 303 355),[0.675 303 160 6,0.675 303 233 5) <BR>      将编码后的区间范围综合如下: <BR>           <BR>    上述编码过程可以用下面的区间分割过程表示: </P>
<P><BR>      <BR>2、 解码过程 <BR>    解码是编码的逆过程,了解了编码过程后,理解解码过程的操作就相对容易了。通过编码,最后的下界值0.675 303 160 6就是消息“state_tree”的唯一编码。然后解码时,通过判断哪一个符号能拥有我们已编码的消息落在的空间来找出消息中的第一个符号。由于0.675 303 160 6落在[0.6,0.7)之间,因此可解得第一个符号是s。 <BR>在解出s后,由于我们知道s的范围的上界和下界,利用编码的逆作用,首先去掉s的下界值0.6,得0.075 303 160 6,然后用s的范围range=0.1去除所得到的0.075 303 160 6,即得到0.753 031 606,接着找出它所在的区间,就是t的原来范围[0.7,1.0)。去掉t的下界值0.7,得0.053 031 606,然后用t的range=0.3除该数得出0.176 772 02,该值所属范围就是字符a……如此操作下去便得到消息的准确译码。 <BR>综述,可以得到解码公式为: <BR>            (Number-range low)/range=&gt;number <BR>其中,number为字符串的编码。 </P>
<P>来自:山城棒棒儿</P>
发表于 2006-5-3 22:04 | 显示全部楼层

有个地方好像有错吧

请教一下happy<br>在decoding下面有句话<br>indx = numberlow indx = [indx 1];<br>这句话是怎么回事呢?好像有点错吧!<br>是不是应该这样写:<br>indx=numberlow;<br>indx=[indx  1];<br>假若是我上面修改的那样,那么<br>indx=numberlow;<br>indx=[indx  1];<br>ind = diff(indx); <br>ind = logical(ind); <br>Mat(k,kk) = color(ind); <br>这段代码是怎么回事呢?<br>解码所得矩阵元素全是1呀!不能经解码得到原矩阵。<br>谢谢!!迫切希望你能给我指点指点!!!!<br>谢谢!!<br>
[此贴子已经被作者于2006-5-3 22:08:35编辑过]

发表于 2006-5-4 11:06 | 显示全部楼层

想再问一下happy

<P>在统计一幅bmp图像中的各个灰度值出现的次数以及其概率百分数的时候<BR>有没有类似于下面的tabulate函数(tabulate是处理简单的数据矩阵)来处理图像矩阵的matlab函数呢?万分感谢你的赐教!!!</P>
<P><BR>% table的第一列为灰度值,第二列为个数,第三列为概率百分数<BR>table = tabulate(I(:)); </P>
发表于 2006-5-5 09:59 | 显示全部楼层

译码

<P>我按照所述的算法改了一下,但是在译码的时候最后一位偶尔会出现错误,暂时还没有搞清楚是怎么回事情<BR>% decoding <BR>Mat = zeros(m,n); <BR>for k = 1:m <BR>for kk = 1:n <BR>    indx=numberlow<BR>    for x=1:length(color)<BR>       if allLow(x)&lt;indx<BR>           if allHigh(x)&gt;indx<BR>               ind=x<BR>               low=allLow(x)<BR>               high=allHigh(x)<BR>           end<BR>       end<BR>    end<BR>%indx = numberlow <BR>%indx = [indx 1]; <BR>%ind = diff(indx); <BR>%ind = logical(ind); <BR>Mat(k,kk) = color(ind); <BR>%low = allLow(ind); <BR>%high = allHigh(ind); <BR>range = high - low; <BR>numberlow = numberlow-low; <BR>numberlow = numberlow/range; <BR>end <BR>end </P>
<P>fprintf('原矩阵为:\n') <BR>disp(I); <BR>fprintf('\n'); <BR>fprintf('解码矩阵:\n'); <BR>disp(Mat); <BR></P>
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-9-25 21:28 , Processed in 0.051313 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表