图像的四叉分解(zz)

来源:互联网 发布:旅游路线规划软件 编辑:程序博客网 时间:2024/05/16 07:13

一个简单的示例(来自MATLAB help for qtdecomp):
原始矩阵:
I =
                         6
                         8
                         7
                         5
   20   22   20   22             4
   20   22   22   20             8
   20   22   20   20      12   40   12
   20   22   20   20   13   14   15   16
>> S = qtdecomp(I,.05) %执行四叉分解,阈值为0.05,实际上的阈值是ceil(0.05*255)=13,因为I是uint8类的
S =
   (1,1)        4
   (5,1)        4
   (1,5)        4
   (5,5)        2
   (7,5)        2
   (5,7)        2
   (7,7)        1
   (8,7)        1
   (7,8)        1
   (8,8)        1
S是一个稀疏阵,全显示为:
>> disp(full(S));
                                 0
                                 0
                                 0
                                 0
                                 0
                                 0
                                 1
                                 1
过程:

图像的四叉分解

图像的四叉分解


图像的四叉分解

含义:
图像的四叉分解

显示四叉树分解的表示(来自MATLAB help,作了些注释):
I = imread('liftingbody.png');
S = qtdecomp(I,.27);%以阈值ceil(0.27*255)=69对图像I进行四叉分解
blocks = repmat(uint8(0),size(S));%得到一个和I同尺寸的黑色背景blocks

for dim = [512 256 128 64 32 16 8 4 2 1];    %分块全是2的整数次幂,注①
  numblocks = length(find(S==dim));    %有numblocks个尺寸为dim的分块,注③
  if (numblocks > 0)       
    values = repmat(uint8(1),[dim dim numblocks]);%产生一个dim x dim x numblocks的三维1值矩阵(或说

                  numblocks个尺寸为dim x dim的1值block)
    values(2:dim,2:dim,:) = 0;
    blocks = qtsetblk(blocks,S,dim,values);%blocks保存了所有块被替换后的结果。注④
  end
end

blocks(end,1:end) = 1;
blocks(1:end,end) = 1;

imshow(I), figure, imshow(blocks,[])
图像的四叉分解

图像的四叉分解

注:
①如果图像不是2的整数次幂,则函数qtdecomp会运行出错。需要将输入图像增大为一个方形,其维数是可包围图像的2的最小整数次幂。这样以确保分离为1是可能的。如,对于一幅 246x300的图像,需要将其扩展为512x512,

可使用如下方法:
>> I(512,512)=0;%原始图像位于I的左上角,扩展的区域全部为0,是不会影响分解结果的。
②分离结果看起来密密麻麻的,但实际上分离的等级数并不多,如512x512的图像最多才分离9次(512分离为4个

256x256算第一级,256再分离为4个128x128算第二级,……),因为每次细分的尺寸都是呈2的指数次减小,故等级数不多。
③find(S==dim)返回的是S中值为dim的linear indexing(线性索引)。含义:MATLAB中矩阵在内存中是以按列的

方式存取的,故对于矩阵A=[2 6 9; 4 2 8; 3 5 1],使用A(3,2)与A(6)有相同的效果——都是访问元素值5。如

此例中,dim=128时,find(S==dim)返回的是:
>> find(S==128)
ans =
           1
         129
       65537
      131073
      196609
      196865
即共有6个尺寸为128x128的分块,它们的位置分别在1、129、65537、131073、196609 、 196865。
这些数字叫做元素的“linear indices(线性顶点)”,根据这些顶点,可以很容易的推算出元素所在的行列位置

。如对于131073的元素而言,其所在的列位置为col=ceil(131073/512)=257,行位置为row=131073-(col-1)

*512=1,即S(1,257)=S(131073)。find的另一种形式可以直接获得行列位置:[row,col] = find(S==dim);
J = qtsetblk(I, S, dim, vals) replaces each dim-by-dim block in the quadtree decomposition of I

with the corresponding dim-by-dim block in vals. S is the sparse matrix returned by qtdecomp; it

contains the quadtree structure. vals is a dim-by-dim-by-k array, where k is the number of dim-by-

dim blocks in the quadtree decomposition.
明确的说明了qtsetblk的功能:在图像I的四叉树分解S中,用vals定义的块代替dim对应的块。
每个块具有如下特征:
图像的四叉分解

下图给出了S中尺寸为128、64和32的块被values定义的块替换后的效果:
图像的四叉分解

⑤试着做下修改,就可在原图上显示网格:
I = imread('liftingbody.png');
S = qtdecomp(I,.27);

for dim = [512 256 128 64 32 16 8 4 2 1];   
  numblocks = length(find(S==dim));   
  if (numblocks > 0)   
    [values, r, c] = qtgetblk(I, S, dim);%读取S中所有尺寸为dim x dim的block,r和c是所有块的左上角点

位置
    values(1:end,1,:)=0;%直接修改所有block的左、上边界为黑色。
注意values是三维矩阵!!
    values(1,1:end,:)=0;
    I= qtsetblk(I,S,dim,values);%直接用修改后的block去替换S中的现有block
  end
end

I(end,1:end) = 0;
I(1:end,end) = 0;

figure, imshow(I,[])
 
图像的四叉分解