Octave:从矩阵中获取多个子矩阵

4

我有一个大矩阵,想要从中收集一些子矩阵。如果我的矩阵是NxN,子矩阵的大小是MxM,我想要收集I=(N - M + 1)^2个子矩阵。换句话说,我想要为原始矩阵中可以在左上角的每个元素都得到一个MxM的子矩阵。

这是我现有的代码:

for y = 1:I
    for x = 1:I
        index = (y - 1) * I + x;
        block_set(index) = big_mat(x:x+M-1, y:y+M-1)
    endfor
 endfor

如果 a) 输出不正确,或者 b) 暗示着 big_mat(x:x+M-1, y:y+M-1) 表达式中有一些可以让我得到所需结果而不需要两个 for 循环的东西。非常感谢您的帮助。


2
似乎你在使用Octave,但也许这个MATLAB问题可以帮你得到一些想法:http://stackoverflow.com/questions/2678857/general-method-for-making-sub-arrays-around-a-particular-element。 - gnovice
3个回答

5

您的代码似乎有一些问题。如果我要使用双重循环,我会这样做:

M = someNumber;
N = size(big_mat,1); %# I assume big_mat is square here

%# you need different variables for maxCornerCoord and nSubMatrices (your I)
%# otherwise, you are going to index outside the image in the loops!
maxCornerCoord = N-M+1;
nSubMatrices = maxCornerCoord^2;

%# if you want a vector of submatrices, you have to use a cell array...
block_set = cell(nSubMatrices,1); 
%# ...or a M-by-M-by-nSubMatrices array...
block_set = zeros(M,M,nSubMatrices);
%# ...or a nSubMatrices-by-M^2 array
block_set = zeros(nSubMatrices,M^2);

for y = 1:maxCornerCoord
    for x = 1:maxCornerCoord
        index = (y - 1) * maxCornerCoord + x; 
        %# use this line if block_set is a cell array
        block_set{index} = big_mat(x:x+M-1, y:y+M-1);
        %# use this line if block_set is a M-by-M-by-nSubMatrices array
        block_set(:,:,index) = big_mat(x:x+M-1, y:y+M-1);
        %# use this line if block_set is a nSubMatrices-by-M^2 array
        block_set(index,:) = reshape(big_mat(x:x+M-1, y:y+M-1),1,M^2);
    endfor
 endfor

编辑

我刚刚看到Octave有一个实现了im2col的版本。因此,您可以将双重循环改写为

%# block_set is a M^2-by-nSubMatrices array
block_set = im2col(big_mat,[M,M],'sliding');

%# if you want, you can reshape the result to a M-by-M-by-nSubMatrices array
block_set = reshape(block_set,M,M,[]);

这可能更快,并且节省大量数字树。

谢谢;有没有一种方法可以避免双重循环? 我假设如果有这样的方法,其性能比循环版本要好得多... - fbrereto
@fbereto:事实证明,你可以将其写成一行代码。请查看我的编辑。 - Jonas
@Jonas:哦,看来你已经考虑到了IM2COL,我想我没有看到你的编辑...考虑添加permute/reshape将其转换为所需的形状:block_set = reshape(permute(im2col(big_mat,[M M],'sliding'),[1 3 2]),2,2,[]); - Amro
顺便提一下,该函数文档的正确链接为:http://octave.sourceforge.net/image/function/im2col.html - Amro
@Amro:感谢您的建议!我认为不需要调用permute,这与Octave有关吗? - Jonas

1
用 Mathematica: 这段代码生成一个矩阵,其中每个元素都是 MxM 的矩阵,并且原始矩阵中的每个元素位于这样一个矩阵的左上角。
矩阵右侧和底部的元素会使用 x 进行填充。
Partition[big_mat, {M, M}, {1, 1}, {1, 1}, x]

例子: alt text http://img130.imageshack.us/img130/6203/partitionf.png

如果省略x参数,则会自动定期进行采样。


0
关于您的输出错误,可能是由于赋值操作引起的。您正在尝试将矩阵分配给向量位置。请尝试使用:
block_set(:,:,index) = big_mat(x:x+M-1, y:y+M-1)

改为使用。


@Ofri:谢谢你的提示。如果我确实想要一个矩阵向量呢? - fbrereto
技术上讲,这是你使用这段代码所得到的结果。它是一个矩阵向量,但索引以获取不同的矩阵是第三个索引。第一个和第二个索引是矩阵内部的索引。另一种可能性是使用单元数组,但我认为在这种情况下,三维矩阵更好。 - Ofri Raviv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接