嵌入式小波零树(EZW)算法的过程详解和Matlab代码(3)解码过程

时间:2023-01-31 19:28:28

 
1、初始化
(1)全局初始化:包括获取扫描次序列表scanorder,初始化符号矩阵flagMat,创建以下几个空表:重要系数重构列表recvalue,量化器编号列表rIlist,上一次解码用到的辅扫描表quantiflagOld。
(2)每级扫描的初始化:获取本级解码需要的主扫描表scancode和辅扫描表quantiflag。创建解码矩阵DecodeMat,量化符号列表编号qrNum,主扫描表扫描编号scNum。

2、构造逆量化器
(1)逆量化器包括两个部分,一是量化值部分,与编码程序中的量化器函数代码相同;二是量化器编号列表rIlist的构造,这个是难点和重点,把它构造出来,才能解码出重要系数的数值。
(2)以下是编码过程中经过4次扫描产生的辅扫描表quantiflag和量化器编号列表rIlist:

Q:0  1  1
R:1  1  1
Q:1  1  1 1 0 0 0 1 1 0
R:2  3  3 1 1 1 1 1 1 1
Q:1  0  1 1 0 1 0 0 1 0 0 1 1 0 0 1 1 0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 1 0 0 0 1 1 0
R:5  7  7 3 2 2 2 3 3 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Q:0  1  1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 0 0 1 0 0 1 0 1 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1……
R:11 14 15 7 4 5 4 6 7 4 2 3 3 2 2 3 3 2 2 2 3 2 3 2 3 2 2 3 2 3 2 3 3 2 2 2 3 3 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1……

仔细观察可以发现两者之间存在一种函数关系:
以第一级扫描产生的三个量化符号(0,1,1)为例,其编号列表为(1,1,1),在随后的第2、3、4级分解后,量化符号相继变化为(1,1,1)、(1,0,1)、(0,1,1),编号列表相继变化为(2,3,3)、(5,7,7)、(11,14,15),这里有一个规律:

    (2,3,3)       = 2*(1,1,1)+(0,1,1)
    (5,7,7)       = 2*(2,3,3)+(1,1,1)
    (11,14,15)= 2*(5,7,7)+(1,0,1)

这样,我们就得到如下公式:
       设r表示扫描级数,则有:   rIlist(r) = 2*rIlist(r-1) + quantiflag(r-1)
从而,就可以轻松编写出逆量化器的函数代码:

function [antiQuantiMat,rIlist,quantiflagOld]=antiquantifier(T1,level,rIlist,quantiflag,quantiflagOld)
antiQuantiMat=[];
maxInterValue=2*T1;
threshold=T1/2^(level-1);
intervalNum=maxInterValue/threshold-1;
for i=1:intervalNum
    antiQuantiMat=[antiQuantiMat;threshold*(i+0.25) threshold*(i+0.75)];
end
 
rIlen=length(rIlist);
flaglen=length(quantiflag);
for r=1:rIlen
    rIlist(r)=2*rIlist(r)+quantiflagOld(r);
end
for f=rIlen+1:flaglen
    rIlist(f)=1;
end
quantiflagOld=quantiflag;

3、提高上一级解码的重要系数的重构精度
这里主要是根据逆量化器生成的重构值矩阵antiQuantiMat和逆量化器编号列表rIlist来更新重要系数列表recvalue的值,并将更新数据存入解码矩阵DecodeMat中。这四个矩阵(列表)的每一行(个)元素都是一一对应的关系,更新就很容易实现,代码如下:

function [DecodeMat,recvalue,qrNum]=updateRecvalue(DecodeMat,recvalue,qrNum,quantiflag,antiQuantiMat,rIlist)
if ~isempty(recvalue)
    [rvRow,rvCol]=size(recvalue);
    for i=1:rvRow
        if quantiflag(qrNum)==1
            qValue=antiQuantiMat(rIlist(qrNum),2);
            if recvalue(i)<0
                qValue=-qValue;
            end
            recvalue(i,1)=qValue;
            DecodeMat(recvalue(i,2),recvalue(i,3))=qValue; 
            qrNum=qrNum+1;    % recvalue矩阵的第2、3列储存的是对应于DecodeMat中的行、列号(r,c)
        else
            qValue=antiQuantiMat(rIlist(qrNum),1);
            if recvalue(i)<0
                qValue=-qValue;
            end
            recvalue(i,1)=qValue;
            DecodeMat(recvalue(i,2),recvalue(i,3))=qValue;
            qrNum=qrNum+1;
        end
    end
end

4、解码
解码过程其实与主扫描过程非常类似,按照扫描次序scanorder扫描解码矩阵DecodeMat:
(1)    首先检查对应的flagMat是否为“O”或“X”,是则跳过,扫描下一个元素。
(2)    然后对照主扫描表scancode,作如下操作:
如果为“P”或“N”,则更新flagMat,根据逆量化器重构DecodeMat相应元素的值,并存入重要系数矩阵recvalue中;
如果为“Z”,则DecodeMat相应元素的值置零;
如果为“T”,则更新flagMat,DecodeMat相应元素的值置零,并使该点所有子孙的flagMat置为“X”。
(3)本级解码完毕,保存符号矩阵flagMat到解码符号矩阵Decodeflag中,然后使flagMat中的元素重置为“O”或“Z”,供下一级解码使用。

function [DecodeMat,flagMat,recvalue]=decoding(DecodeMat,flagMat,recvalue,antiQuantiMat,quantiflag,rIlist,scanorder,scancode,scNum,qrNum)
global row col
for r=1:row*col
    if flagMat(scanorder(r,1),scanorder(r,2))=='O'
        continue;
    elseif flagMat(scanorder(r,1),scanorder(r,2))=='X'
        continue;
    else
        if scancode(scNum)=='P'
            flagMat(scanorder(r,1),scanorder(r,2))='P';
            if quantiflag(qrNum)==1
                qValue=antiQuantiMat(rIlist(qrNum),2);
                recvalue=[recvalue;qValue,scanorder(r,1),scanorder(r,2)];
                DecodeMat(scanorder(r,1),scanorder(r,2))=qValue;
                qrNum=qrNum+1;
            else
                qValue=antiQuantiMat(rIlist(qrNum),1);
                recvalue=[recvalue;qValue,scanorder(r,1),scanorder(r,2)];
                DecodeMat(scanorder(r,1),scanorder(r,2))=qValue;
                qrNum=qrNum+1;
            end
            scNum=scNum+1;
        elseif scancode(scNum)=='N'
            flagMat(scanorder(r,1),scanorder(r,2))='N';
            if quantiflag(qrNum)==1
                qValue=-antiQuantiMat(rIlist(qrNum),2);
                recvalue=[recvalue;qValue,scanorder(r,1),scanorder(r,2)];
                DecodeMat(scanorder(r,1),scanorder(r,2))=qValue;
                qrNum=qrNum+1;
            else
                qValue=-antiQuantiMat(rIlist(qrNum),1);
                recvalue=[recvalue;qValue,scanorder(r,1),scanorder(r,2)];
                DecodeMat(scanorder(r,1),scanorder(r,2))=qValue;
                qrNum=qrNum+1;
            end
            scNum=scNum+1;
        elseif scancode(scNum)=='Z'
            DecodeMat(scanorder(r,1),scanorder(r,2))=0;
            scNum=scNum+1;
        elseif scancode(scNum)=='T'
            flagMat(scanorder(r,1),scanorder(r,2))='T';
            DecodeMat(scanorder(r,1),scanorder(r,2))=0;
            chTree=treeMat(scanorder(r,1),scanorder(r,2));
            [rowch,colch]=size(chTree);
            for rc=1:rowch
                if flagMat(chTree(rc,1),chTree(rc,2))~='O'
                    flagMat(chTree(rc,1),chTree(rc,2))='X';
                end
            end
            scNum=scNum+1;
        end
    end
end
Decodeflag=flagMat;
for i=1:row
    for j=1:col
        switch flagMat(i,j)
            case {'P','N'}
                flagMat(i,j)='O';
            case {'T','X'}
                flagMat(i,j)='Z';
        end
    end
end