【问题标题】:Octave: Multiple submatrices from a matrix八度:来自矩阵的多个子矩阵
【发布时间】:2011-02-12 13:58:39
【问题描述】:

我有一个大矩阵,我想从中收集一组子矩阵。如果我的矩阵是 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 循环,则输出。任何帮助将不胜感激

【问题讨论】:

  • 您似乎在 Octave 中执行此操作,但也许这个 MATLAB 问题会帮助您提供一些想法:*.com/questions/2678857/…

标签: matlab matrix wolfram-mathematica octave submatrix


【解决方案1】:

关于您的输出错误,可能是因为分配。您正在尝试将矩阵分配给向量位置。尝试使用

block_set(:,:,index) = big_mat(x:x+M-1, y:y+M-1)

改为。

【讨论】:

  • @Ofri:感谢您的提示。如果我确实想要一个矩阵向量怎么办?
  • 从技术上讲,这就是您使用这段代码所能得到的。它是一个矩阵向量,但到达不同矩阵的索引是第三个索引。第一个和第二个索引是矩阵内的索引。另一种可能性是使用元胞数组,但我认为在这种情况下使用 3D 矩阵会更好。
【解决方案2】:

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

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,[]);

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

【讨论】:

  • 谢谢;有没有办法在没有双循环的情况下做到这一点?我假设如果有这样的性能会比循环版本好得多......
  • @fbereto:事实证明你可以把它写成 1-liner。查看我的编辑。
  • @Jonas:哦,看来您已经想到了 IM2COL,我想我没有看到您的编辑...考虑添加 permute/reshape 以将其变成所需的形状:block_set = reshape(permute(im2col(big_mat,[M M],'sliding'),[1 3 2]),2,2,[]);
  • 顺便说一句,函数文档的正确链接是:octave.sourceforge.net/image/function/im2col.html
  • @Amro:感谢您的建议!不过,我认为不需要调用 permute - 还是 Octave 有什么特别之处?
【解决方案3】:

使用 Mathematica: 这段代码创建了一个矩阵,其中每个元素都是 MxM 的矩阵,原始矩阵中的每个元素都位于该矩阵的左上角。

右边和底部的矩阵元素用x填充。

Partition[big_mat, {M, M}, {1, 1}, {1, 1}, x]

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

如果您不使用 x 参数,那么它会定期自动采样。

【讨论】: