多级树集合分裂(SPIHT)算法的过程详解与Matlab实现(6)解码过程——主程序

时间:2021-01-16 04:37:40

 
    现在我们讨论SPIHT算法的解码过程。SPIHT的编码输出包括:初始阈值T,排序扫描位流SnList,精细扫描位流 RnList,初始有序表(LSP、LIP、LIS、LisFlag),这些参数就作为SPIHT解码的输入,另外还有解码级数decodeDim。

    前面我们提到,任何排序算法的执行路径都是使用分支点的比较结果进行定义的。如果解码器和编码器使用相同的排序算法,则对于编码器输入的系数比较结果,解码器通过执行相同的路径就可获得排序信息。所以,只需将编码器数学表述中的“输出”改为“输入”,解码器即可恢复数据的排序信息;在恢复数据排序信息的同时,解码器还要负责图像的重构,对于确认恢复的重要系数,通过排序扫描和精细扫描两个步骤更新系数的量化值,逐步提高逼近精度和重构图像的质量。

1、首先给出解码主程序

function DecodeMat=spihtdecoding(T,SnList,RnList,ini_LSP,ini_LIP,ini_LIS,ini_LisFlag,decodeDim)
% 函数 SPIHTDECODING() 是SPIHT算法的解码主程序
% 输入参数: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型两种
%          decodeDim —— 解码级数
% 输出参数:DecodeMat —— 解码后重构的小波系数矩阵
%
% 由SPIHT算法原理的排序特点,解码器的执行程序与编码器的程序路径基本相同,只需把编码器程序中的
% 输出信息改为输入,稍作修改即可得到解码器的程序代码

global rMat cMat
% rMat、cMat是Mat的行、列数,作为全局变量,在编码、解码的相关程序中使用

%-------------------------------------------%
% ----- Decoding Input Initialization ----- %
%-------------------------------------------%
N=log2(T);
% 获取初始阈值的指数-N
DecodeMat=2^(N-decodeDim)*rand(rMat,cMat);
% 初始化重构矩阵为一个随机矩阵,其元素最大值小于*解码阈值的二分之一
% 这样就可以保证未被扫描赋值的区域有一定的灰度,避免重构图像出现色块
LSP=ini_LSP;
LIP=ini_LIP;
LIS=ini_LIS;
LisFlag=ini_LisFlag;
% 将输入的各项列表存入相应的解码工作列表

%---------------------------%
% ----- Decoding Loop ----- %
%---------------------------%
for d=1:decodeDim
    %-------------------------------------%
    % ----- Decoding Initialization ----- %
    %-------------------------------------%
    [Sn,SnList]=getflow(SnList);
    [Rn,RnList]=getflow(RnList);
% 用 GETFLOW() 函数读取本级解码所需的位流信息
    LSP_Old=LSP;
% 列表LSP_Old用于存储上级解码产生的重要系数列表LSP,作为本级精细解码的输入

    %--------------------------%
    % ----- Sorting Pass ----- %
    %--------------------------%
        % ----- LIP Scan ----- %
        %----------------------%
    [DecodeMat,Sn,LSP,LIP]=lip_decode(DecodeMat,Sn,N,LSP,LIP);
        %----------------------%
        % ----- LIS Scan ----- %
        %----------------------%
    [LSP,LIP,LIS,LisFlag,DecodeMat,N]=lis_decode(DecodeMat,N,Sn,LSP,LIP,LIS,LisFlag);
    %-----------------------------%
    % ----- Refinement Pass ----- %
    %-----------------------------%
    DecodeMat=decRefine(DecodeMat,Rn,N+1,LSP_Old);
end

可以看出,解码程序和编码程序几乎是一样的,执行路径也相同。只不过解码器要对输入的扫描位流SnList、RnList进行分段读取,只读入本级解码所需的位流,下面给出位流信息读取程序:


(1)位流信息读取程序

function [flow,bitflow]=getflow(bitflow)
% 函数 GETFLOW() 用于截取本级解码所需的位流信息
% 输入参数:bitflow —— 初始为编码器的输入位流,在解码过程中为上一级解码截取后剩余的编码位流
% 输出参数:flow —— 本级解码所需的位流(排序位流Sn、精细位流Rn)
%                 bitflow —— 本级解码截取后剩余的编码位流

flow=[];
i=1;
while bitflow(i)~=7
    flow(i)=bitflow(i);
    i=i+1;
end
% 数字‘7’作为位流区别符,区分不同编码级的位流
bitflow(1:i)=[];
% 将对应于本级解码位流的 bitflow 数据清空
% bitflow 被完全清空后返回一个空表值
if isempty(bitflow)
    bitflow=[];
end