Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1649143
  • 博文数量: 13833
  • 博客积分: 1041400
  • 博客等级: 大元帅
  • 技术积分: 127080
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-13 10:12
文章分类

全部博文(13833)

文章存档

2008年(13833)

我的朋友

分类:

2008-06-13 10:25:51

 本文给出SPIHT编码的排序扫描代码,排序扫描分为LIP队列扫描和LIS队列扫描两个步骤,其中LIS队列扫描较为复杂,在编程时容易出现错误,要倍加注意。2、LIP队列扫描程序function [Sn,LSP,LIP]=lip_scan(Sn,N,LSP,LIP)% 函数 LIP_SCAN() 检查LIP表的各个表项是否重要,更新列表LIP、LSP和排序位流 Sn% 输入参数:Sn —— 本级编码排序位流,为空表%                     N —— 本级编码阈值的指数%                     LSP —— 上一级编码生成的重要系数列表%                     LIP —— 上一级编码生成的不重要系数列表% 输出参数:Sn —— 对上一级编码生成的LIP列表扫描后更新的排序位流%                     LSP —— 对上一级编码生成的LIP列表扫描后更新的重要系数列表%                     LIP —— 经本级LIP扫描处理后更新的不重要系数列表global Mat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用rlip=size(LIP,1);% r 是指向 LIP 当前读入表项位置的指针r=1;% 由于循环过程中列表 LIP 的表长会变化,不适合用 for 循环,故采用 while 循环while r<=rlip% 读入当前表项的坐标值    rN=LIP(r,1);    cN=LIP(r,2);% 调用 SNOUT() 函数来判断该表项是否重要    if SnOut(LIP(r,:),N)        % 若重要,则输入‘1’到 Sn        Sn=[Sn,1];        % 输入正负符号‘1’或‘0’到 Sn        if Mat(rN,cN)>=0            Sn=[Sn,1];        else            Sn=[Sn,0];        end        % 将该表项添加到重要系数列表 LSP        LSP=[LSP;LIP(r,:)];        % 将该表项从 LIP 中删除        LIP(r,:)=[];    else        % 若不重要,则输入‘0’到 Sn        Sn=[Sn,0];        % 将指针指向下一个表项        r=r+1;    end    % 判断当前 LIP 的表长    rlip=size(LIP,1);end3、LIS队列扫描程序function [LSP,LIP,LIS,LisFlag,Sn,N]=lis_scan(N,Sn,LSP,LIP,LIS,LisFlag)% 函数 LIS_SCAN() 检查LIS表的各个表项是否重要,更新列表LIP、LSP、LIS、LisFlag和排序位流 Sn% 输入参数:N —— 本级编码阈值的指数%                     Sn —— 本级编码排序位流,为空表%                     LSP —— 上一级编码生成的重要系数列表%                     LIP —— 上一级编码生成的不重要系数列表%                     LIS —— 上一级编码生成的不重要子集列表%                     LisFlag —— 上一级编码生成的不重要子集表项类型列表% 输出参数:LSP —— 本级LIS列表扫描后更新的重要系数列表%                     LIP —— 经本级LIS扫描处理后更新的不重要系数列表%                     LIS —— 本级LIS列表扫描后更新的不重要子集列表%                     LisFlag —— 本级LIS列表扫描后更新的不重要子集表项类型列表%                     Sn —— 本级LIS列表扫描后更新的排序位流%                     N —— 下一级编码阈值的指数global Mat rMat cMat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用% 读入当前 LIS 的表长rlis=size(LIS,1);% ls 是指向 LIS 当前表项位置的指针,初始位置为1ls=1;% 由于循环过程中列表 LIS 的表长会变化,不适合用 for 循环,故采用 while 循环while ls<=rlis    % 读入当前 LIS 表项的类型    switch LisFlag(ls)        % ‘D’类表项,包含孩子和非直系子孙        case 'D'            % 读入该表项的坐标值            rP=LIS(ls,1);            cP=LIS(ls,2);            % 生成‘D’型子孙树            chD=coef_DOL(rP,cP,'D');            % 判断该子孙树是否重要            isImt=SnOut(chD,N);            if isImt                % 如果该子孙树重要,就输入‘1’到 Sn                Sn=[Sn,1];                % 生成该表项的孩子树                chO=coef_DOL(rP,cP,'O');                % 分别判断每个孩子的重要性                for r=1:4                    % 判断该孩子的重要性和正负符号                    [isImt,Sign]=SnOut(chO(r,:),N);                    if isImt                        % 如果重要,就输入‘1’和正负标志到 Sn                        Sn=[Sn,1];                        if Sign                            Sn=[Sn,1];                        else                            Sn=[Sn,0];                        end                        % 将该孩子添加到重要系数列表 LSP                        LSP=[LSP;chO(r,:)];                    else                        % 如果不重要,就输入‘0’到 Sn                        Sn=[Sn,0];                        % 将该孩子添加到不重要系数列表 LIP                        % 本级阈值下不重要的系数在下一级编码中可能是重要的                        LIP=[LIP;chO(r,:)];                    end                end                % 生成该表项的非直系子孙树                chL=coef_DOL(rP,cP,'L');                if ~isempty(chL)                    % 如果‘L’型树非空,则将该表项添加到列表 LIS 的尾端等待扫描                    LIS=[LIS;LIS(ls,:)];                    % 表项类型更改为‘L’型                    LisFlag=[LisFlag,'L'];                    % 至此,该表项的‘D’型LIS扫描结束,在LIS中删除该项及其类型符                    LIS(ls,:)=[];                    LisFlag(ls)=[];                else                    % 如果‘L’型树为空集                    % 则该表项的‘D’型LIS扫描结束,在LIS中删除该项及其类型符                    LIS(ls,:)=[];                    LisFlag(ls)=[];                end            else                % 如果该表项的‘D’型子孙树不重要,就输入‘0’到 Sn                Sn=[Sn,0];                % 将指针指向下一个 LIS 表项                ls=ls+1;            end            % 更新当前 LIS 的表长,转入下一表项的扫描            rlis=size(LIS,1);        case 'L'            % 对‘L’类表项,不需判断孩子的重要性            % 读入该表项的坐标值            rP=LIS(ls,1);            cP=LIS(ls,2);            % 生成‘L’型子孙树            chL=coef_DOL(rP,cP,'L');            % 判断该子孙树是否重要            isImt=SnOut(chL,N);            if isImt                % 如果该子孙树重要,就输入‘1’到 Sn                Sn=[Sn,1];                % 生成该表项的孩子树                chO=coef_DOL(rP,cP,'O');                % 将该‘L’类表项从 LIS 中删除                LIS(ls,:)=[];                LisFlag(ls)=[];                % 将表项的四个孩子添加到 LIS 的结尾,标记为‘D’类表项                LIS=[LIS;chO(1:4,:)];                LisFlag(end+1:end+4)='D';            else                % 如果该子孙树是不重要的,就输入‘0’到 Sn                Sn=[Sn,0];                % 将指针指向下一个 LIS 表项                ls=ls+1;            end            % 更新当前 LIS 的表长,转入下一表项的扫描            rlis=size(LIS,1);    endend% 对 LIS 的扫描结束,将本级阈值的指数减1,准备进入下一级编码N=N-1;    LIS队列扫描程序中调用的子程序有: COEF_DOL() :根据子孙树的类型'type'来计算点(r,c)的子孙列表; SNOUT() :根据本级阈值指数 N 判断坐标集 coefSet 是否重要; (1)子孙树生成程序function chList=coef_DOL(r,c,type)% 函数 COEF_DOL() 根据子孙树的类型'type'来计算点(r,c)的子孙列表% 输入参数:r,c —— 小波系数的坐标值%                     type —— 子孙树的类型%                     'D':点(r,c)的所有子孙(包括孩子)%                     'O':点(r,c)的所有孩子%                     'L':点(r,c)的所有非直系子孙,L(r,c)=D(r,c)-O(r,c)% 输出参数:chList —— 点(r,c)的'type'型子孙列表global Mat rMat cMat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用[Dch,Och]=childMat(r,c);% 函数 CHILDMAT() 返回点(r,c)的'D'型和'O'型子孙列表Lch=setdiff(Dch,Och,'rows');% 根据关系式 L(r,c)=D(r,c)-O(r,c)求出'L'型子孙列表% Matlab函数 SETDIFF(A,B)计算具有相同列数的两个矩阵A、B中,A有而B无的元素集合% 根据输入参数'type'选择输出参数switch type    case 'D'        chList=Dch;    case 'O'        chList=Och;    case 'L'        chList=Lch;endfunction [trAll,trChl]=childMat(trRows,trCols)% 函数 CHILDMAT() 根据输入的坐标值trRows、trCols 输出其全体子孙 trAll,% 其中包括孩子树 trChl;另外,根据算法原理,还要判断子孙树是否全为零,% 若为全零,则trAll、trChl均为空表global Mat rMat cMat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用trAll=treeMat(trRows,trCols);% 调用函数 treeMat() 生成该点的子孙树坐标队列trZero=1;% 用变量 trZero 来标记该点是否具有非零子孙rA=size(trAll,1);% 如果子孙树 trAll 中有系数值不为零,则 trZero=0,表示该点具有非零子孙for r=1:rA    if Mat(trAll(r,1),trAll(r,2))~=0        trZero=0;        break;    endendif trZero    trAll=[];    trChl=[];else    trChl=trAll(1:4,:);    % 函数 treeMat() 输出的全体子孙树 trAll 头四位元素就组成相应的孩子树end    上面调用的函数treeMat() 与EZW算法中使用的程序是一样的,这里就不写出来了,详细代码请参见《嵌入式小波零树(EZW)算法的过程详解和Matlab代码(1)构建扫描次序表》。(2)系数集重要性判别程序function [isImt,Sign]=SnOut(coefSet,N)% 函数 SNOUT() 根据本级阈值指数 N 判断坐标集 coefSet 是否重要 isImt ,对单元素% 的系数集输出该元素的正负符号 Sign 。global Mat% Mat是输入的小波分解系数矩阵,作为全局变量,在编码的相关程序中使用rSet=size(coefSet,1);% 读取坐标集中各元素的系数值for r=1:rSet    cMat(r)=Mat(coefSet(r,1),coefSet(r,2));end% 根据系数最大值判断该坐标集是否重要if max(abs(cMat))>=2^N    isImt=1;else    isImt=0;end% 对单个元素的坐标集,判断该元素的正负符号if cMat(1)>=0    Sign=1;else    Sign=0;end
阅读(48) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~