上一篇文章已经详细介绍了SPIHT算法的编码过程,接下来有关编码和解码的部分就直接把代码写出来啦,我的代码里有详细的中文注释,基本上把程序的每个步骤都作了说明,呵呵,利人也利己!1、首先给出编码的主程序function [T,SnList,RnList,ini_LSP,ini_LIP,ini_LIS,ini_LisFlag]=spihtcoding(DecIm,imDim,codeDim)% 函数 SPIHTCODING() 是SPIHT算法的编码主程序% 输入参数:DecIm ——小波分解系数矩阵;% imDim ——小波分解层数;% codeDim ——编码级数。% 输出参数:T —— 初始阈值,T=2^N,N=floor(log2(max{|c(i,j)|})),c(i,j)为小波系数矩阵的元素% SnList —— 排序扫描输出位流% RnList —— 精细扫描输出位流% ini_L* —— 初始系数(集合)表% LSP:重要系数表% LIP:不重要系数表% LIS:不重要子集表,其中的表项是D型或L型表项的树根点% LisFlag:LIS中各表项的类型,包括D型和L型两种global Mat rMat cMat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用%---------------------------%% ----- Threshold ----- %%---------------------------%Mat=DecIm;MaxMat=max(max(abs(Mat)));N=floor(log2(MaxMat));T=2^N;% 公式:N=floor(log2(max{|c(i,j)|})),c(i,j)为小波系数矩阵的元素%--------------------------------------%% ----- Output Intialization ----- %%--------------------------------------%SnList=[];RnList=[];ini_LSP=[];ini_LIP=coef_H(imDim);rlip=size(ini_LIP,1);ini_LIS=ini_LIP(rlip/4+1:end,:);rlis=size(ini_LIS,1);ini_LisFlag(1:rlis)='D';% ini_LSP:扫描开始前无重要系数,故LSP=[];% ini_LIP:所有树根的坐标集,对于N层小波分解,LIP是LL_N,LH_N,HL_N,HH_N 所有% 系数的坐标集合;% 函数 COEF_H() 用于计算树根坐标集 H% ini_LIS:初始时,LIS是LH_N,HL_N,HH_N 所有系数的坐标集合;在SPIHT算法中,% LL_N 没有孩子。% ini_LisFlag:初始时,LIS列表的表项均为D型。%------------------------------------------------%% ----- Coding Input Initialization ------ %%------------------------------------------------%LSP=ini_LSP;LIP=ini_LIP;LIS=ini_LIS;LisFlag=ini_LisFlag;% 将待输出的各项列表存入相应的编码工作列表%--------------------------------%% ----- Coding Loop ------ %%--------------------------------%for d=1:codeDim %------------------------------------------% % ----- Coding Initialization ------- % %------------------------------------------% Sn=[]; LSP_Old=LSP; % 每级编码产生的Sn都是独立的,故Sn初始化为空表 % 列表LSP_Old用于存储上级编码产生的重要系数列表LSP,作为本级精细扫描的输入 %-------------------------------% % ----- Sorting Pass ----- % %-------------------------------% % ----- LIP Scan -------- % %----------------------------% [Sn,LSP,LIP]=lip_scan(Sn,N,LSP,LIP); % 检查LIP表的小波系数,更新列表LIP、LSP和排序位流 Sn %-------------------------% % ----- LIS Scan ----- % %-------------------------% [LSP,LIP,LIS,LisFlag,Sn,N]=lis_scan(N,Sn,LSP,LIP,LIS,LisFlag); % 这里,作为输出的N比作为输入的N少1,即 out_N=in_N-1 % 各项输出参数均作为下一编码级的输入 %-------------------------------------% % ----- Refinement Pass ----- % %-------------------------------------% Rn=refinement(N+1,LSP_Old); % 精细扫描是在当前阈值T=2^N下,扫描上一编码级产生的LSP,故输入为(N+1,LSP_Old), % 输出为精细位流 Rn %-----------------------------------% % ----- Output Dataflow ----- % %-----------------------------------% SnList=[SnList,Sn,7]; RnList=[RnList,Rn,7]; % 数字‘7’作为区分符,区分不同编码级的Rn、Sn位流end 编码主程序中调用到的子程序有:
COEF_H() :用于计算树根坐标集 H ,生成初始的LIP队列;
LIP_SCAN() :检查LIP表的各个表项是否重要,更新列表LIP、LSP和排序位流 Sn ;
LIS_SCAN() :检查LIS表的各个表项是否重要,更新列表LIP、LSP、LIS、LisFlag和排序位流 Sn ;
REFINEMENT() :精细扫描编码程序,输出精细位流 Rn 。
(1)下面是计算树根坐标集 H 的程序function lp=coef_H(imDim)% 函数 COEF_H() 根据矩阵的行列数rMat、cMat和小波分解层数imDim来计算树根坐标集 H% 输入参数:imDim —— 小波分解层数,也可记作 N% 输出参数:lp —— rMat*cMat矩阵经N层分解后,LL_N,LH_N,HL_N,HH_N 所有系数的坐标集合global rMat cMat% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用row=rMat/2^(imDim-1);col=cMat/2^(imDim-1);% row、col是 LL_N,LH_N,HL_N,HH_N 组成的矩阵的行、列数lp=listorder(row,col,1,1);% 因为 LIP 和 LIS 中元素(r,c)的排列顺序与 EZW 零树结构的扫描顺序相同% 直接调用函数 LISTORDER() 即可获得按EZW扫描顺序排列的LIP列表(2)这里调用了函数 LISTORDER() 来获取按EZW扫描顺序排列的LIP列表,以下是该函数的程序代码:function lsorder=listorder(mr,mc,pr,pc)% 函数 LISTORDER() 生成按‘Z’型递归结构排列的坐标列表% 函数递归原理:对一个mr*mc的矩阵,其左上角元素的坐标为(pr,pc);首先将矩阵按“田”% 字型分成四个对等的子矩阵,每个子矩阵的行、列数均为mr/2、mc/2,左上角元素的坐标% 从上到下、从左到右分别为(pr,pc)、(pr,pc+mc/2)、(pr+mr/2,pc)、(pr+mr/2,pc+mc/2)。% 把每个子矩阵再分裂成四个矩阵,如此递归分裂下去,直至最小矩阵的行列数等于2,获取最小% 矩阵的四个点的坐标值,然后逐步向上回溯,即可得到按‘Z’型递归结构排列的坐标列表。lso=[pr,pc;pr,pc+mc/2;pr+mr/2,pc;pr+mr/2,pc+mc/2];% 列表lso是父矩阵分裂成四个子矩阵后,各子矩阵左上角元素坐标的集合mr=mr/2;mc=mc/2;% 子矩阵的行列数是父矩阵的一半lm1=[];lm2=[];lm3=[];lm4=[];if (mr>1)&&(mc>1)% 按‘Z’型结构递归 ls1=listorder(mr,mc,lso(1,1),lso(1,2)); lm1=[lm1;ls1]; ls2=listorder(mr,mc,lso(2,1),lso(2,2)); lm2=[lm2;ls2]; ls3=listorder(mr,mc,lso(3,1),lso(3,2)); lm3=[lm3;ls3]; ls4=listorder(mr,mc,lso(4,1),lso(4,2)); lm4=[lm4;ls4];endlsorder=[lso;lm1;lm2;lm3;lm4];% 四个子矩阵结束递归回溯到父矩阵时,列表lsorder的头四个坐标值为列表lso的元素% 这四个坐标值与后面的各个子矩阵的坐标元素有重叠,故需消去% 当函数输出的列表长度length(lsorder)与矩阵的元素个数mr*mc*4不相等时,% 就说明有坐标重叠发生。len=length(lsorder);lsorder=lsorder(len-mr*mc*4+1:len,:);