嵌入式小波零树(EZW)算法的过程详解和 Matlab 代码(3)解码过程 收藏
1、初始化
(1)全局初始化:包括获取扫描次序列表 scanorder,初始化符号矩阵 flagMat,创建以下几
个空表:重要系数重构列表 recvalue,量化器编号列表 rIlist,上一次解码用到的辅扫描表 qu
antiflagOld。
(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,quantifl
ag,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,qrN
um,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 列储存的是对应于 DecodeMa
t 中的行、列号(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,an
tiQuantiMat,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
嵌入式小波零树(EZW)算法的过程详解和 Matlab 代码(4)运行示例 收藏
最后,我们以一幅 64*64 的 Lena 局部图像来演示 EZW 算法的编解码效果。
首先给出相关的编解码主程序。
function y=ezw(Im,imDim,codeDim,DecodeDim)
global row col
[row,col]=size(Im);
% ----- Wavedec -----%
DecIm=mywavedec2(Im,imDim);
% ----- Select threshold -----%
MaxDecIm=max(max(abs(DecIm)));
T=zeros(1,codeDim);
T(1)=2^flor(log2(MaxDecIm));
for i=2:codeDim
T(i)=T(i-1)/2;
end
% ----- EZW coding -----%
[CodeList,LenSubCL,QuantiFlagList,LenSubQFL]=ezwcode(DecIm,T,codeDim);
% ----- EZW decoding -----%
DecodeMat=ezwdecode(DecIm,T(1),DecodeDim,CodeList,LenSubCL,QuantiFlagLis
t,LenSubQFL);
% ----- Waverec -----%
DecIm(1:row/8,1:col/8)
DecodeMat(1:row/8,1:col/8)
RecIm=mywaverec2(DecodeMat,imDim);
function [CodeList,LenSubCL,QuantiFlagList,LenSubQFL]=ezwcode(Mat,threshold,
codedim)
global row col
scanlist=morton(Mat);
flaglist(1:row,1:col)='Z';
imptvalue=[];
imptflag=[];
% ----- Intializing EZW coding output variables -----%
CodeList=[];
LenSubCL=[];
QuantiFlagList=[];
LenSubQFL=[];
% ----- Coding loop -----%
for d=1:codedim
[imptvalue,imptflag,scancode,scanflag,flaglist]=mainscan(Mat,scanlist,flaglist,i
mptvalue,imptflag,threshold(d));
[quantilist,quantiflag,recvalue,quantifierMat]=assistscan(imptvalue,d,threshold
(1));
% Produce code dataflow
CodeList=[CodeList,scancode];
LenSubCL=[LenSubCL,length(scancode)];
QuantiFlagList=[QuantiFlagList,quantiflag'];
LenSubQFL=[LenSubQFL,length(quantiflag)];
end
function DecodeMat=ezwdecode(Mat,T1,decodeDim,CodeList,LenSubCL,QuantiFla
gList,LenSubQFL)
global row col
recvalue=[];
rIlist=[];
quantiflagOld=[];
scanorder=listorder(row,col,1,1);
flagMat(1:row,1:col)='Z';
for level=1:decodeDim
scancode=CodeList(1:LenSubCL(level));
CodeList=CodeList(LenSubCL(level)+1:end);
quantiflag=QuantiFlagList(1:LenSubQFL(level));
QuantiFlagList=QuantiFlagList(LenSubQFL(level)+1:end);
DecodeMat=Mat;
qrNum=1;
scNum=1;