快速四叉树构造,matlab中的矩阵分区

时间:2014-10-28 12:54:28

标签: matlab

我有一个矩阵,我想逐步将它分成更小的部分。在第一步中,它本身是一个1 by 1矩阵,在第二步中,它被分为四个子矩阵2 by 2矩阵,在下一步中,它被分为十六个子矩阵,4 by 4矩阵和等等。

我的矩阵是n乘n和2的幂。

我怎样才能按照我所处的步骤快速完成?

这是我编写的代码,但效率不够。

function [A,B] = qtree(X,K,N,l)

L = log2(N);
wx = (size(X,1))/(2^l); 
wk = (size(K,1))/(2^(L-l)); 
for n=1:2^l
    m (n,:) = (n-1)*wx+1:n*wx ; 
end
for n=1:2^(L-l)
    mm (n,:) = (n-1)*wk+1:n*wk ; 
end
% the ordering is like MATLAB, from top to bottom and left to right
k=1;
for i = 1:size(m,1)
    for j= 1:size(m,1)
        A(:,:,k) = X(m(j,:),m(i,:));
        k = k+1;
    end
end
kk=1;
for i = 1:size(mm,1)
    for j= 1:size(mm,1)
        B(:,:,kk) = K(mm(j,:),mm(i,:));
        kk = kk+1;
    end
end

1 个答案:

答案 0 :(得分:0)

我要做的是使用mat2cell来帮助您将矩阵分解为子矩阵,其中每个子矩阵属于一个单元格。在此之后,简单地将它们全部连接成3D数值矩阵,其中i th 切片表示i th 子矩阵。因此,从主标度(原始矩阵)开始,您可以简单地将行和列细分为2的幂,将它们放入单元格中,然后在空间上将所有这些单元格连接成数字3D矩阵。但是,此代码假定您的矩阵维度为2的幂。如果不是,则此方法将不起作用。我的一个建议是填充矩阵,使其均匀地适合2的幂。你可以做的是使用nextpow2来确定行和列的最大兼容能力2,然后创建一个这个增加的大小的矩阵并将矩阵放在里面。但是,如果您的矩阵大小已经是2的幂,那么nextpow2将只返回该数字的精确log2,因此当我们完成时不会有任何零填充。它只是原始矩阵。

我不确定您正在使用哪种输入,但如果大小不是2的幂,这将处理所有通用大小矩阵。


换句话说,如果您的矩阵存储在A中,并指定num_scales作为您要执行这些细分的次数,请尝试以下操作:

[rows, cols] = size(A); %// Get dimensions

%// Determine compatible dimensions for matrix
rows_pad = 2^(nextpow2(rows));
cols_pad = 2^(nextpow2(cols));

%// Create padded matrix
Apad = zeros(rows_pad, cols_pad);
Apad(1:rows, 1:cols) = A;

num_scales = 5; %//Determines number of subdivisions
%// You can also intelligently figure this out by:
%// num_scales = min(log2(rows_pad), log2(cols_pad)) + 1;

for s = 1 : num_scales
    Bcell = mat2cell(A, (rows_pad/(2^(s-1)))*ones(2^(s-1),1), (cols_pad/(2^(s-1)))*ones(2^(s-1),1)).';
    B = cat(3,Bcell{:});

    %// B contains this 3D matrix
    %// Continue your processing...
    %//
end

请注意,您可以通过获取行和列的log2并确定最小值并添加1来智能地确定要分解图像的最大比例数。我已将其添加为注释设置num_scales后。但是,我将此设置为常量,以防您不希望将矩阵一直分解为单个1 x 1元素。

B包含3D矩阵,其中每个切片是i th 子矩阵。请注意,此代码将按行存储块 。这意味着子矩阵从左到右,从上到下。如果您需要列主要订单,只需删除.'语句末尾的转置运算符(Bcell = ...)。

现在,Bcell = ...声明可能会让你失望。让我们慢慢地逐步完成这个陈述。这里又是自我遏制:

Bcell = mat2cell(A, (rows_pad/(2^(s-1)))*ones(2^(s-1),1), (cols_pad/(2^(s-1)))*ones(2^(s-1),1)).';

mat2cell的工作原理是您提供要分区为单元格的矩阵,在我们的示例中为Apad。接下来的两个输入是1D向量,它们告诉您正在分区的每个块的大小。第二个输入适用于行,而第三个输入适用于列。因此,在第一次迭代中,我们只有一个相同大小的单个2D矩阵,因此在1循环中的比例for,我们只需得到相同大小的单元矩阵。 / p>

在下一次迭代中,我们的比例为2,因此等效的调用将是:

Bcell = mat2cell(Apad, [rows_pad/2 rows_pad/2], [cols_pad/2 cols_pad/2]);

该语句基本上创建了4个子矩阵,其中细分发生在行的中间和列的中间。在第三次迭代中,我们的比例为4,因此等效的调用将是:

Bcell = mat2cell(Apad, [rows_pad/4 rows_pad/4 rows_pad/4 rows_pad/4], ...
                [cols_pad/4 cols_pad/4 cols_pad/4 cols_pad/4]);

因此,我们将行和列均分为4个段,在4 x 4网格中提供16个子矩阵。这就是ones语句的目的,这样我们就可以根据需要多次复制这个语句。

最后,我们使用cat将所有这些2D矩阵堆叠到一个3D矩阵中,并指定第三个维度,以便我们堆叠这些矩阵。 B应包含您的最终3D矩阵,您可以从该点开始执行任何处理。


这应该足以让你开始。祝你好运!