图像的四叉分解

来源:互联网 发布:meego软件搬运 编辑:程序博客网 时间:2024/04/30 09:01
原文地址:图像的四叉分解作者:uleen

一个简单的示例(来自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 21];   %分块全是2的整数次幂,注①
  numblocks =length(find(S==dim));   %有numblocks个尺寸为dim的分块,注③
  if (numblocks >0)       
    values =repmat(uint8(1),[dim dim numblocks]);%产生一个dim x dim xnumblocks的三维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的linearindexing(线性索引)。含义:MATLAB中矩阵在内存中是以按列的

方式存取的,故对于矩阵A=[2 6 9; 4 2 8; 3 51],使用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 eachdim-by-dim block in the quadtree decomposition of I

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

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

dim blocks in the quadtreedecomposition.
明确的说明了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 21];   
  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,[])
结果如下:
 [转载]图像的四叉分解

0 0
原创粉丝点击