EZW嵌入式零树编码,matlab全实现(小波分析)

主要内容在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 矩阵的第23 列储存的是对应于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



你可能感兴趣的:(小波分析,matlab,预编码算法,图像处理,视频编解码)