首先根据实际需要确定扫描次数D=codeDim,然后进行D次主扫描和辅扫描。
1、初始化
首先获取扫描次序表scanlist,表中每行的数字依次是该元素的(1)扫描序号、(2)对应于数据矩阵中位置的行号r、(3)对应于数据矩阵中位置的列号c、(4)值Mat(r,c),即
scanlist (i) = [ i, r, c, Mat(r,c) ]
编码扫描的对象就是次序表scanlist,而非数据矩阵Mat。然后构建初始符号矩阵flagMat,其中每个元素均为字符“Z”。
2、主扫描
在第d次(1<= d <=codeDim)扫描中,输入阈值为T(d),首先依次对次序表的每一行scanlist(i)按照如下步骤扫描:
(1) 如果上一次扫描得到的flagMat中,处于位置(r,c)的符号为“O”,则表示相应的Mat(r,c)是重要的,不需要通过本次扫描再次编码,故作跳过处理。
(2) 将scanlist(i,4)(即Mat(r,c))的绝对值与阈值T(d) 比较,如果是重要的系数,则令flagMat(r,c)的值为P或N,并存入主扫描表scancode中,并将Mat(r,c)的值以及相应的行、列数(r,c)存入重要数列表imptvalue中,将符号P或N存入重要数符号列表imptflag中。
(3) 如果是不重要的系数,则首先检查flagMat(r,c),若是符号“X”,则表示这个点是不重要的,作跳过处理不再扫描。
(4) 如果点(r,c)处于第一分解级,即r>row/2或c>col/2,没有子孙系数,且其系数是不重要的,则该点flagMat的符号为Z,存入主扫描表scancode中。
(5) 如果点(r,c)满足r<row/2且c<col/2,则检查其子孙系数中是否有重要系数。有,则flagMat(r,c)的值为字符Z,存入主扫描表scancode中;否则flagMat(r,c)的值为T,存入主扫描表scancode中,并令其所有子孙系数相应的flagMat(r’,c’)值为字符X,不再作下一次扫描。
至此,扫描结束。然后,将扫描后得到的符号矩阵flagMat转存到scanflag中,再将flagMat中的字符P、N都置换为O,字符X和T都置换为Z,使得flagMat的元素只有字符O、Z两种,作为输出到下一次扫描中使用。
function [imptvalue,imptflag,scancode,scanflag,flaglist]=mainscan(Mat,scanlist,flaglist,imptvalue,imptflag,threshold)
global row col
scancode=[];
for i=1:row*col
if flaglist(scanlist(i,2),scanlist(i,3))=='O'
continue;
elseif abs(scanlist(i,4))>=threshold
if scanlist(i,4)>=0
flaglist(scanlist(i,2),scanlist(i,3))='P';
scancode=[scancode 'P'];
imptvalue=[imptvalue;abs(scanlist(i,4)),scanlist(i,2),scanlist(i,3)];
imptflag=[imptflag 'P'];
else
flaglist(scanlist(i,2),scanlist(i,3))='N';
scancode=[scancode 'N'];
imptvalue=[imptvalue;abs(scanlist(i,4)),scanlist(i,2),scanlist(i,3)];
imptflag=[imptflag 'N'];
end
else
if flaglist(scanlist(i,2),scanlist(i,3))=='X'
continue;
elseif i>row*col/4
scancode=[scancode 'Z'];
else
[chImt,chMat]=childImportant(Mat,scanlist(i,2),scanlist(i,3),threshold,flaglist);
if chImt
flaglist(scanlist(i,2),scanlist(i,3))='Z';
scancode=[scancode 'Z'];
else
flaglist(scanlist(i,2),scanlist(i,3))='T';
scancode=[scancode 'T'];
[rowch,colch]=size(chMat);
for r=1:rowch
if flaglist(chMat(r,1),chMat(r,2))~='O'
flaglist(chMat(r,1),chMat(r,2))='X';
end
end
end
end
end
end
scanflag=flaglist;
for r=1:row
for c=1:col
switch flaglist(r,c)
case {'P','N'}
flaglist(r,c)='O';
case {'X','T'}
flaglist(r,c)='Z';
end
end
end
function [chImt,chMat]=childImportant(Mat,chRows,chCols,threshold,flaglist)
global row col
chMat=childMat(Mat,chRows,chCols);
if max(abs(chMat(:,3)))>=threshold
chImt=1;
else
chImt=0;
end
3、辅扫描
辅扫描是对输出符号为P和N的系数进行量化,并将量化符号存入辅扫描表quantiflag中。在主扫描中,将输出符号为P和N的系数的符号信息和数值分别储存在列表imptflag和imptvalue中。辅扫描的具体过程是:
(1)构造量化器
量化器的构造比较简单,不过关键的问题是要确定每一级扫描中量化器的数目。首先,量化区间的最大区间值应该是初始阈值的2倍,最小值是当前的阈值,故第d级扫描时,总的量化区间为[ T(d), 2*T(1) );而量化间隔为T(d),故第d级扫描的量化器数目为:Q = [2*T(1) — T(d)] / T(d) 。
确定量化器数目后,就要确定每个量化器中“0”“1”对应的量化值。根据算法原理,第q个量化器中,相应于符号“0”的量化值为:T(d)*(q+0.25),相应于符号“1”的量化值为:T(d)*(q+0.75)。至此,量化器构造完成。
function [quantifierMat,threshold]=quantifier(T1,level)
quantifierMat=[];
maxInterValue=2*T1;
threshold=T1/2^(level-1);
intervalNum=maxInterValue/threshold-1;
for i=1:intervalNum
quantifierMat=[quantifierMat;threshold*(i+0.25) threshold*(i+0.75)];
end
(2)辅扫描过程
首先要确定这个重要系数属于量化器。根据总量化区间与量化间隔的关系,只要将重要系数除以量化间隔,所得的商就是该重要系数所在的量化器编号。即:
rI=flor(imptvalue(j) /threshold);
将重要系数减去量化器的起始值,所得的值与量化间隔的二分之一值相比较,
小于的话,则量化符号为“0”,大于则量化符号为“1”。然后选择量化重构值,存入重构列表recvalue中。
function [quantilist,quantiflag,recvalue,quantifierMat]=assistscan(imptvalue,dim,T1)
quantilist=[];
quantiflag=[];
recvalue=[];
[quantifierMat,threshold]=quantifier(T1,dim);
[imRow,imCol]=size(imptvalue);
for j=1:imRow
rI=flor(imptvalue(j)/threshold);
flag01=imptvalue(j)-rI*threshold;
if flag01<threshold/2
quantiflag=[quantiflag;0];
recvalue=[recvalue;quantifierMat(rI,1)];
else
quantiflag=[quantiflag;1];
recvalue=[recvalue;quantifierMat(rI,2)];
end
end
quantilist=[imptvalue(:,1),quantiflag,recvalue,imptvalue(:,2),imptvalue(:,3)];
4、编码输出
每级扫描完成后,把主扫描输出的主扫描表scanlist存入列表Codelist中,并用一个辅助列表LenSubCL记录这一级主扫描表的表长(在信号传输应用中不一定用得上);把辅扫描输出的量化符号列表quantiflag存入列表QuantiFlagList中,并用一个辅助列表LenSubQFL记录辅扫描表的表长。
以下是经过3次扫描后的编码输出
code_level = 1
scancode = ZPPPTTTTTTTTTTTT
quantiflag = 011
code_level = 2
scancode = PZTTTZNTTTTTTTZTNTTTZNTTTZZZNZNZZZZNZZZZZ
quantiflag = 1111000110
code_level = 3
scancode = NPTTNNZTNTTTNTPNPTTNZNZTTZZTTZZTTNTTTZZZZNZZZPPNZZNZPZPZZZZZZZNZ
NZZZNNPZZZZPZZPPZZPZZZNZZZZZZZ
quantiflag = 101101001001100110001010100101011000110