主要内容在m文件里,大家直接看文件一步一步运行也可以看懂,我非常讨厌那些收集了资源然后故意拿来卖钱的,开源才是王道,大家随意使用,代码直接在matlab里面就可以运行,当然如果你要用别的图片做请自己更改一下相关参数,如果我的博文对你有用,记得点赞收藏!!!!!!
费尽千辛万苦终于把这个实验做出来了,感觉这个难度已经超过一半的大作业了。
由于本人比较丑,所以就不放自己照片了,使用matlab自带的woman图像,它的原图是这样的。
然后我们对其进行二维小波分解,如果说想用比较简单的分解,那么就直接用dwt2函数就可以做到,他会返回低频信息,垂直,水平,对角四个方向的信息,是四个矩阵。
所以可以
[cA1,cH1,cV1,cD1] = dwt2(X,‘db4’);
A0 = idwt2(cA1,cH1,cV1,cD1,‘db4’);
就能得到小波变换和逆变换,当然这个变换只是一级的,如果还需要更高级别,就需要对里面的cA1进行进一步的dwt2,这是比较麻烦的,对于多级小波变换,可以采用wavedec2,能够返回矩阵的N级小波变换。
[c,s]=wavedec2(X,2,‘haar’);
其中c是分解信息,s是分解后各个小波的尺寸大小。
同时我们可以分别使用detcoef2,appcoef2
[H1,V1,D1] = detcoef2(‘all’,c,s,1);
A1 = appcoef2(c,s,‘haar’,1);
获得各个级别分解的水平、垂直、对角方向信息和二维表达的图像的逼近系数。
而我们如果需要进一步获取二维表达的小波图像数据,则需要将不同级别的数据进行拼接才能得到
PCH3=[A3 H3;V3 D3];
PCH2=[PCH3 H2;V2 D2];
PCH1=[PCH2 H1;V1 D1];
这样我们得到的图就为
第一步我们需要建立小波树结构,我们知道分解的最低频段上,每个点又三个孩子,(r,c)有(r,c+W)、(r+H,c)和(r+H,c+W),其中W、H分别是最低频子带的宽和高;
然后除了最低频以外的高频子带,都有四个孩子,即tp=[2r-1,2c-1;2r-1,2c;2r,2c-1;2r,2c];
据此我们可以写出小波树函数,对于输入其中的任意一点,返回该点的子孙列表,次函数的关键在于那些边界点,即运行终止的节点。第一是如果在最低频段的点,则其孩子只有三个,如果是中间频段的点,则有四个,如果是最高频段的点,则没有孩子。同时,对于中间层的,还必须调用此函数进行递归,以获得其所有孩子列表。
具体代码请查看文件中treeMat函数。
如下图,表示了一个8*8的小波函数,进行两层分解的父子关系对应图
在能够取得孩子数据位置点后,同时将其位置加进来,就可以得到某个点的子孙数据位置及值大小,具体查看函数childMat
下面构建扫描的次序表,课本中介绍的EZW扫描方式为Morton式,特点是从最左上角点开始,每四个点构成一个“Z”形扫描单元,这种扫描可以在无论进行几级分解情况下都能得到正确的扫描顺序,这是一个递归函数,需要扫描到4*4的最小矩阵单元才会停止。其中具体操作看morton函数,mat2list函数,listorder函数。mat2list函数负责将整个矩阵转化为所有矩阵数值按扫描顺序排列的列表。listorder函数负责返回整个矩阵的扫描顺序点的坐标。其中注意事项已经全部写在代码注释中。
接下来定义主扫描函数,首先关注其标记符号,如果被表标为“O”则表明是重要元素,这次扫描可以跳过;然后将数据值绝对值与输入的阈值进行比较,按照正负分为“P”或“N”,然后存入主扫描表scancode,并且将这些重要数据的位置和值存入重要数据列表imptvalue,将符号P或N存入重要数符号列表imptflag中。如果是不重要的系数,则首先检查flagMat(r,c),若是符号“X”,则表示这个点是不重要的,作跳过处理不再扫描。
辅扫描是对输出符号为P和N的系数进行量化,并将量化符号存入辅扫描表quantiflag中。在主扫描中,将输出符号为P和N的系数的符号信息和数值分别储存在列表imptflag和imptvalue中。
量化器的构造比较简单,不过关键的问题是要确定每一级扫描中量化器的数目。首先,量化区间的最大区间值应该是初始阈值的2 倍,最小值是当前的阈值,故第d 级扫描时,总的量化区间为[ T(d), 2T(1) );而量化间隔为T(d),故第d级扫描的量化器数目为:Q = [2T(1) — T(d)] / T(d) 。
确定量化器数目后,就要确定每个量化器中“0”“1”对应的量化值。根据算法原理,第q 个量化器中,相应于符号“0”的量化值为:T(d)(q+0.25),相应于符号“1”的量化值为:T(d)(q+0.75)。至此,量化器构造完成。
首先要确定这个重要系数属于量化器。根据总量化区间与量化间隔的关系,只要将重要系数除以量化间隔,所得的商就是该重要系数所在的量化器编号。
将重要系数减去量化器的起始值,所得的值与量化间隔的二分之一值相比较,小于的话,则量化符号为“0”,大于则量化符号为“1”。然后选择量化重构值,存入重构列表recvalue 中。
对于逆量化器,一个关键点在于,找到当前量化等级对应的量化区间,由于我们是从原始第一次扫描编码开始操作的,所以结果一定是由粗到精。具体代码较为繁杂,已经已经在matlab代码中有详细标注。
实验结果
对小波分解图像进行第一级编码
第一次主扫描过后,得到结果为:
重要值有440个,
扫描的编码输出为
最后输出的整个图的标签为
同样进过一次量化器之后得到的结果为
其中第一列为原始值,第二列为量化的指标,第三列为量化结果,4、5列为该点在原始图像中位置。
%记住了matlab格式化输出是sprintf('asdfasdf%.5f',变量名)
% load('women_l3.mat')
load woman
global row col dim
row=256; col=256; dim=3;% dim 是小波分解级数
figure;imagesc(X),colormap(gray)
% codeDim=3;
% MaxDecIm=max(max(abs(PCH1)));
% T=zeros(1,codeDim);
% T(1)=2^floor(log2(MaxDecIm));%求出初始阈值
% bitch=treeMat(1,1);
% son=childMat(PCH1,3,3);
% of=listorder(256,256,1,1);
% ezw(X,3,5,5);
%图像是X,然后将要小波进行3级分解,并且进行五级编码,五级解码
%在此处决定分解级别,编码级别,以及解码级别
[Im,imDim,codeDim,DecodeDim]=deal(X,3,10,8);
% ----- Wavedec -----%
DecIm=mywavedec2(Im,imDim);
figure;imagesc(DecIm),colormap(gray)
% ----- Select threshold -----%
MaxDecIm=max(max(abs(DecIm)));
T=zeros(1,codeDim);
T(1)=2^floor(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,QuantiFlagList,LenSubQFL);
% ----- Waverec -----%
% DecIm(1:row/8,1:col/8);%取出分解到最低的那一级低频信号
% DecodeMat(1:row/8,1:col/8);%
RecIm=mywaverec2(DecodeMat,imDim);
%这个是仅仅用其中解码后最低频那部分还原的结果
figure;imagesc(RecIm),colormap(gray)
%%
%编解码主程序
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^floor(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,QuantiFlagList,LenSubQFL);
% ----- Waverec -----%
DecIm(1:row/8,1:col/8);
DecodeMat(1:row/8,1:col/8);
% RecIm=mywaverec2(DecodeMat,imDim);
end
%%
function [CodeList,LenSubCL,QuantiFlagList,LenSubQFL]=...
ezwcode(Mat,threshold,codedim)
global row col
scanlist=morton(Mat);
flaglist(1:row,1:col)='Z';%首先把所有行列都标注为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,imptvalue,imptflag,threshold(d));
sprintf('第%.0d次主扫描',d)
% sprintf('imptvalue'),imptvalue
% sprintf('imptflag'),imptflag
% sprintf('scancode'),scancode
% sprintf('scanflag'),scanflag
% sprintf('flaglist'),flaglist
[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
end
function DecodeMat=ezwdecode(Mat,T1,decodeDim,CodeList,LenSubCL,QuantiFlagList,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;
[antiQuantiMat,rIlist,quantiflagOld]=antiquantifier(T1,level,rIlist,quantiflag,quantiflagOld);
[DecodeMat,recvalue,qrNum]=updateRecvalue(DecodeMat,recvalue,qrNum,quantiflag,antiQuantiMat,rIlist);
[DecodeMat,flagMat,recvalue]=decoding(DecodeMat,flagMat,recvalue,antiQuantiMat,quantiflag,rIlist,scanorder,scancode,scNum,qrNum);
% if level<decodeDim
% button = questdlg('Need the nest decodeprocessing ?','Decode Level','Yes','No','Yes');
% if button(1)=='N'
% break;
% end
% end
end
end
%%
%构建小波树结构,构建扫描次序表
%函数输入矩阵内任意位置(r,c),给出该点子孙列表
function cP=treeMat(r,c)
global row col dim
HLL=row/2^dim;
WLL=col/2^dim;
if (r<=HLL)&&(c<=WLL)
tp1=[r,c+WLL;r+HLL,c;r+HLL,c+WLL];
cP=[tp1;treeMat(r,c+WLL);treeMat(r+HLL,c);treeMat(r+HLL,c+WLL)];
elseif (r>row/2)||(c>col/2)
cP=[];
else
tp=[2*r-1,2*c-1;2*r-1,2*c;2*r,2*c-1;2*r,2*c];
tm1=[];tm2=[];tm3=[];tm4=[];
if (tp(4,1)<=row/2)&&(tp(4,2)<=col/2)
t1=treeMat(tp(1,1),tp(1,2));
tm1=[tm1;t1];
t2=treeMat(tp(2,1),tp(2,2));
tm2=[tm2;t2];
t3=treeMat(tp(3,1),tp(3,2));
tm3=[tm3;t3];
t4=treeMat(tp(4,1),tp(4,2));
tm4=[tm4;t4];
end
cP=[tp;tm1;tm2;tm3;tm4];
end
end
%%
%进一步构建返回子孙 数据 列表的函数
function chMat=childMat(Mat,chRows,chCols)
chPoint=treeMat(chRows,chCols);
chMat=[];
[mRows,~]=size(chPoint);%行数等于子孙点数,列没有用
for iRows=1:mRows
chMat=[chMat;chPoint(iRows,1),chPoint(iRows,2),Mat(chPoint(iRows ...
,1),chPoint(iRows,2))];
%上面分号一下的分别为 行位置,列位置,数据值,这是依托于treeMat写的
end
end
%%
%构建morton扫描次序列表
function scanlist=morton(Mat)
global row col
matlist=mat2list(Mat);
scanorder=listorder(row,col,1,1);
scanlist=[];
for i=1:row*col
%里面分别是序号,坐标,值
scanlist=[scanlist;i scanorder(i,:) matlist(i)];
end
end
%按照morton 扫描次序转换成数据列表matlist
function mls=mat2list(Mat) % 该函数为递归函数,把一个矩阵按照扫描顺序变列表
[r,c]=size(Mat);
if (r==2)&&(c==2)%如果只剩4个元素了就直接排序
mls=[Mat(1,1);Mat(1,2);Mat(2,1);Mat(2,2)];
else%否则分成四块,四块分别化成列表在叠加
M1=Mat(1:r/2,1:c/2);
M2=Mat(1:r/2,c/2+1:c);
M3=Mat(r/2+1:r,1:c/2);
M4=Mat(r/2+1:r,c/2+1:c);
lt1=mat2list(M1);
lt2=mat2list(M2);
lt3=mat2list(M3);
lt4=mat2list(M4);
mls=[lt1;lt2;lt3;lt4];
end
end
%按照扫描次序组成的矩阵各点位置的(r,c)列表,
%前两个参数为矩阵总的行列数,后两个为开始的位置
function lsorder=listorder(mr,mc,pr,pc) % 前两个为总行列数,后两个为所求点
lso=[pr,pc;pr,pc+mc/2;pr+mr/2,pc;pr+mr/2,pc+mc/2];
mr=mr/2;mc=mc/2;
lm1=[];lm2=[];lm3=[];lm4=[];
%这里可以理解为首先求出每个大块将要进行扫描的四个角点,然后再
%将整个矩阵分为4块,再对每一块分别求其将要扫描的4个角点
%如果达到了输入长宽都为2,那么就成为了最小矩阵,扫描顺序就是一个最小Z
%也就不用进入下面的if语句,直接lso接上就行
if (mr>1)&&(mc>1)
ls1=listorder(mr,mc,lso(1,1),lso(1,2));
lm1=[lm1;ls1];
ls2=listorder(mr,mc,lso(2,1),lso(2,2));
lm2=[lm2;ls2];
ls3=listorder(mr,mc,lso(3,1),lso(3,2));
lm3=[lm3;ls3];
ls4=listorder(mr,mc,lso(4,1),lso(4,2));
lm4=[lm4;ls4];
end
%其实这个lso我感觉是个累赘,他就是提供每次函数listorder的四个头部点
lsorder=[lso;lm1;lm2;lm3;lm4];
len=length(lsorder);
lsorder=lsorder(len-mr*mc*4+1:len,1:2);
end
%%
%主扫描函数
%输入:小波矩阵,扫描列表,标签列表,重要值,重要值标签,扫描阈值
%输出:重要值(含有绝对值,以及其位置),重要值标签,本次扫描的标签
%提供给下次扫描的标签
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'
%如果遇到标记为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
%如果是X表明不重要,跳过
if flaglist(scanlist(i,2),scanlist(i,3))=='X'
continue;
elseif i>row*col/4
%如果是在最低子带,那低于阈值就可以判断为Z
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
%如果不是重要点,则将子孙中所有点标为不重要X
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;
%扫描结束更新一遍标签,所有标为PN的,下次不需要再主扫描所以标为O
%所有标签为不重要的T,X的下次还可能大于阈值,所以标为可能存在重要子孙系数
%的Z,最后将本次主扫描得到的标签和提供给下次主扫描的标签都返回
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
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
end
%%
%辅扫描,构造量化器,返回一个列表,长度为根据阈值分区的长度,
%其中具体值为不同分区01对应的数值
%输入:原始阈值,量化等级
%输出:量化区间矩阵,当前量化阈值
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
end
%%
%辅扫描
%输入:重要值[重要值绝对值,坐标],量化等级,原始阈值
%输出:量化列表[重要值绝对值,量化标签,量化值,坐标],量化标签,量化值
%量化区间矩阵
%我就你妈奇怪了为什么要重复接收这么多参数,服了
function [quantilist,quantiflag,recvalue,quantifierMat]=...
assistscan(imptvalue,dim,T1)
quantilist=[];%量化结果列表
quantiflag=[];%量化标志列表
recvalue=[];
[quantifierMat,threshold]=quantifier(T1,dim);%给出目标级数的量化器
[imRow,~]=size(imptvalue);
for j=1:imRow
rI=floor(imptvalue(j)/threshold);%先整除阈值,去掉区间影响
flag01=imptvalue(j)-rI*threshold;
if flag01<threshold/2
%小于半阈值标志为0,然后重新量化出来就行
quantiflag=[quantiflag;0];
recvalue=[recvalue;quantifierMat(rI,1)];
else
%大于阈值标志为1,也是重新量化出来
quantiflag=[quantiflag;1];
recvalue=[recvalue;quantifierMat(rI,2)];
end
end
%返回量化列表,中间两个是量化标志和量化值
quantilist=[imptvalue(:,1),quantiflag,recvalue,imptvalue(:,2),imptvalue(:,3)];
end
%%
%逆量化器
%所谓量化器编号列表就是前面提到的量化矩阵,会随着量化等级精度不断提高
%比如说63,对于一级量化T1=32,就是量化器[40,56]的第一行
%对于第二级,T=16,就是[~,~;~,~;~,60]的第三行
%其规律就是上一行量化结果*2+1,这就是下面rIlist公式的来源
%输入:原始阈值,量化等级,量化器编号列表,量化标签,上一级量化值
%输出:逆量化矩阵,新量化器编号列表,旧量化标签
function [antiQuantiMat,rIlist,quantiflagOld]=antiquantifier(T1, ...
level,rIlist,quantiflag,quantiflagOld)
antiQuantiMat=[];
maxInterValue=2*T1;
threshold=T1/2^(level-1);
%这是区间内能整除阈值的次数,相当于决定在第几个量化区间
%下面antiQuantiMat就是逆量化时候0 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;
end
%%
%更新重要系数列表recvalue 的值
%这个recvalue第一次是从decoding里面来的
%输入:解码矩阵(这个矩阵一开始是输入的原始矩阵),重构值
%重构的序数,重构的标志列表,重新量化矩阵,量化器编号列表
%输出:重构矩阵,重构值列表,重构序号
function [DecodeMat,recvalue,qrNum]=updateRecvalue( ...
DecodeMat,recvalue,qrNum,quantiflag,antiQuantiMat,rIlist)
if ~isempty(recvalue)
[rvRow,~]=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
end
%%
%解码
%对于标为XO的不作处理,然后其他的根据解码级别赋值,这个就是
%将上面的操作运用到矩阵中输出一个矩阵
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
end
%%
%自己的二维小波变换,全都使用haar小波,可以用了
function PCH=mywavedec2(im,imDim)
HVD={[]};
[~,~,c]=size(im);
if c~=1
im=rgb2gray(im);
else
end
[C,S]=wavedec2(im,imDim,'haar');
ADim=appcoef2(C,S,'haar',imDim);
for i=1:imDim
[H,V,D]=detcoef2('all',C,S,i);
HVD{i}= {H,V,D};
end
PCH=[];
for i=1:imDim
if i==1
PCH=[ADim HVD{imDim+1-i}{1};HVD{imDim+1-i}{2} HVD{imDim+1-i}{3}];
else
PCH=[PCH HVD{imDim+1-i}{1};HVD{imDim+1-i}{2} HVD{imDim+1-i}{3}];
end
end
end
%%
%将编码解码为图像的函数
function y=mywaverec2(x,dim)
%函数MYWAVEREC2()对输入的分解系数矩阵x进行dim层重构,得到重构矩阵y
%输入参数:x——分解系数矩阵;
% dim——重构层数;
%输出参数:y——重构矩阵。
%绘制分解图像
xd=uint8(x);
%将输入矩阵的数据格式转换为适合显示图像的uint8格式
[m,n]=size(x); %求出输入矩阵的行列数
for i=1:dim
%对转换矩阵xd进行分界线处理
m=m-mod(m,2);
n=n-mod(n,2);
xd(m/2,1:n)=255;
xd(1:m,n/2)=255;
m=m/2;n=n/2;
end
%重构图像
xr=double(x);
%将输入矩阵的数据格式转换回适合数值处理的double格式
[row,col]=size(xr); %求出转换矩阵xr的行列数
for i=dim:-1:1 %重构次序是从内层往外层进行,所以先抽取矩阵xr的最内层分解矩阵进行重构
tmp=xr(1:floor(row/2^(i-1)),1:floor(col/2^(i-1)));
%重构的内层矩阵的行列数均为矩阵xr的2^(i-1)
[rt1,ct1]=size(tmp);
%读取待重构矩阵tmp的行列数
rt=rt1-mod(rt1,2);ct=ct1-mod(ct1,2);%这一步只是为了保证输出为2的幂
%将待重构矩阵tmp分解为四个部分
rLL=tmp(1:rt/2,1:ct/2);
rHL=tmp(1:rt/2,ct/2+1:ct);
rLH=tmp(rt/2+1:rt,1:ct/2);
rHH=tmp(rt/2+1:rt,ct/2+1:ct);
tmp(1:rt,1:ct)=idwt2(rLL,rHL,rLH,rHH,'haar');
%将重构结果返回到矩阵tmp
xr(1:rt1,1:ct1)=tmp; %把矩阵tmp的数据返回到矩阵xr的相应区域,准备下一个外层的重构
end
y=uint8(xr);
end
%%
%这是个网上找的呆逼函数,明明有现成2维的小波逆变换函数不用
%非要自己用一维来变,如果用来理解二维变换有一定教育意义,对实验无意义
function cM=myidwt2(cA,cH,cV,cD)
% 此函数实现了二维离散小波反变换,即重构。它是利用MATLAB工具箱所提供的一维离散小波反变
% 换函数idwt()对传递进来的近似分量cA、水平细节分量cH、垂直细节分量cV和对角细节分量cD进
% 行相应的小波类型重构处理,其中参数wavename是小波类型。它借助于使用了指定的小波基函数
% 'wavename'的idwt()首先对四个分量矩阵进行列反变换,而后行反变换。重构出中间过程图像矩
% 阵cM和原始图像矩阵mypic_RGB。
cA1=[];cD1=[];
% 进行逐列列重构变换,得到过程矩阵cA1、cD1,再对它们列数扩展合成为中间图阵cM
cA=cA';cH=cH';cV=cV';cD=cD';
x=size(cA);
for i=1:x(1)
temp=idwt(cA(i,:),cV(i,:),'haar');
cA1=[cA1;temp];
end
x=size(cH);
for i=1:x(1)
temp=idwt(cH(i,:),cD(i,:),'haar');
cD1=[cD1;temp];
end
cA1=cA1';
cD1=cD1';
cM=[cA1,cD1];
% 对上述得到的分量cA1、cD1作为过程细节分量进行逐行行重构变换,得到图像矩阵mypic_RGB
x=size(cA1);
for i=1:x(1)
temp=idwt(cA1(i,:),cD1(i,:),wavename);
end
end