【问题标题】:For loop to split matrix to equal sized sub-matricesFor循环将矩阵拆分为大小相等的子矩阵
【发布时间】:2013-12-02 19:30:28
【问题描述】:

给定一个大小为 400x400 的方阵,我将如何使用 for 循环将其拆分为 20x20 的组成子矩阵?我什至想不出从哪里开始!

我想我想要类似的东西:

[x,y] = size(matrix)

for i = 1:20:x
    for j = 1:20:y

但我不确定我将如何进行。想法?

【问题讨论】:

  • 虽然你已经得到了答案,只是出于好奇,如果你要将矩阵拆分为20x20 子矩阵,是什么让你写了数字30
  • mat2cell 适合将矩阵分解为子矩阵。 KlausCPH 的回答就是一个很好的例子。另请参阅here
  • @Parag 搞错了哈哈!

标签: matlab loops octave


【解决方案1】:

嗯,我知道发帖人明确要求 for 循环,而 Jeff Mather 的回答正是提供了这一点。

但我仍然很好奇是否可以在没有循环的情况下将矩阵分解为给定大小的图块(子矩阵)。如果其他人也很好奇,这就是我想出的:

T = permute(reshape(permute(reshape(A, size(A, 1), n, []), [2 1 3]), n, m, []), [2 1 3])

将二维数组A 转换为三维数组T,其中每个二维切片T(:, :, i) 是大小为m x n 的图块之一。第三个索引以标准 Matlab 线性化顺序枚举瓦片,瓦片行在前。

变种

T = permute(reshape(A, size(A, 1), n, []), [2 1 3]);
T = permute(reshape(T, n, m, [], size(T, 3)), [2 1 3 4]);

使T 成为一个四维数组,其中T(:, :, i, j) 给出了具有平铺索引i, j 的二维切片。

想出这些表达式有点像解决一个滑动难题。 ;-)

【讨论】:

  • 如果您有图像处理工具箱,您可以使用blockproc 将函数句柄迭代地应用于图像/矩阵的子部分。例如:blockproc(M, [20 20], @myAwesomeFunction)
  • 当然。但这其中的乐趣在哪里? ;-)
  • +1 我很好奇!事实上,我尝试了几分钟,然后退出了:-)
  • 惊人的工作。 +1 我将您的答案扩展到 3D 矩阵。退房!
  • @carandraug。你称我的回答是“可怕的”,这是一个相当强烈的词,而你隐含地称我为“大师”,这仍然不好。说真的,这里有什么大不了的? Luis Mendo 和可能大多数其他支持者都意识到,这是一种极端矢量化的练习,(对我和其他人来说)很有趣。
【解决方案2】:

很抱歉,我的答案也没有使用 for 循环,但这也可以解决问题:

cellOf20x20matrices = mat2cell(matrix, ones(1,20)*20, ones(1,20)*20)

然后您可以访问各个单元格,例如:

cellOf20x20matrices{i,j}(a,b)

其中 i,j 是要获取的子矩阵(如果需要,a,b 是该矩阵的索引)

问候

【讨论】:

    【解决方案3】:

    你看起来很亲密。仅使用您描述的问题(400×400,分为 20×20 块),这不是你想要的吗?

    [x,y] = size(M);
    
    for i = 1:20:x
      for j = 1:20:y
        tmp = M(i:(i+19), j:(j+19));
        % Do something interesting with "tmp" here.
      end
    end
    

    【讨论】:

    • 谢谢,这很有帮助。并感谢其他所有人的其他答案,但希望在这种特殊情况下使用 for 循环。正在讨论一些非常有趣的想法!
    • @user3058703,如果这个答案符合您的要求,您应该接受它(单击勾勒出的复选标记,使其变为绿色)。
    【解决方案4】:

    尽管这个问题基本上是针对 2D 矩阵的,但受到 A. Donda's answer 的启发,我想将他的答案扩展到 3D 矩阵,以便可以将这种技术用于裁剪真彩色图像 (3D)

    A = imread('peppers.png');       %// size(384x512x3)
    nCol = 4;                        %// number of Col blocks
    nRow = 2;                        %// number of Row blocks
    m = size(A,1)/nRow;              %// Sub-matrix row size (Should be an integer)
    n = size(A,2)/nCol;              %// Sub-matrix column size (Should be an integer)
    
    imshow(A);                       %// show original image
    
    out1 = reshape(permute(A,[2 1 4 3]),size(A,2),m,[],size(A,3));
    out2 = permute(reshape(permute(out1,[2 1 3 4]),m,n,[],size(A,3)),[1 2 4 3]);
    
    figure;
    for i = 1:nCol*nRow
        subplot(nRow,nCol,i); imshow(out2(:,:,:,i));
    end
    

    基本思想是在重塑时使第 3 维不受影响,这样图像就不会失真。为了实现这一点,进行了额外的置换以交换第 3 维和第 4 维。完成该过程后,尺寸将通过重新排列恢复原样。

    结果:

    原图

    子图(分区/子矩阵)


    这种方法的优点是,它也适用于 2D 图像。 这是灰度图像 (​​2D) 的示例。这里使用的示例是 MatLab 内置图像'cameraman.tif'

    【讨论】:

      【解决方案5】:

      对于使用嵌套调用permute 的答案有很多人赞成,我想到了计时并与使用mat2cell 的其他答案进行比较。

      的确,他们不会返回完全相同的东西,但是:

      • 可以轻松地将单元格转换为与其他单元格一样的矩阵(我对此进行了计时,请参阅下文);
      • 当出现此问题时,最好(根据我的经验)将数据放在一个单元格中,因为稍后人们通常希望将原始数据重新组合在一起;

      无论如何,我已经将它们与以下脚本进行了比较。代码在 Octave(版本 3.9.1)中运行,并禁用了 JIT。

      function T = split_by_reshape_permute (A, m, n)
        T = permute (reshape (permute (reshape (A, size (A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
      endfunction
      
      function T = split_by_mat2cell (A, m, n)
        l = size (A) ./ [m n];
        T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1));
      endfunction
      
      function t = time_it (f, varargin)
        t = cputime ();
        for i = 1:100
          f(varargin{:});
        endfor
        t = cputime () - t;
      endfunction
      
      Asizes = [30 50 80 100 300 500 800 1000 3000 5000 8000 10000];
      Tsides = [2 5 10];
      As = arrayfun (@rand, Asizes, "UniformOutput", false);
      
      for d = Tsides
        figure ();
      
        t1 = t2 = [];
        for A = As
          A = A{1};
          s = rows (A) /d;
      
          t1(end+1) = time_it (@split_by_reshape_permute, A, s, s);
          t2(end+1) = time_it (@split_by_mat2cell, A, s, s);
      
        endfor
      
        semilogy (Asizes, [t1(:) t2(:)]);
        title (sprintf ("Splitting in %i", d));
        legend ("reshape-permute", "mat2cell");
        xlabel ("Length of matrix side (all squares)");
        ylabel ("log (CPU time)");
      endfor
      

      注意 Y 轴是对数刻度

      性能

      在性能方面,对于较小的矩阵,使用嵌套置换只会更快,因为相对性能的大变化实际上是非常小的时间变化。请注意,Y 轴采用 对数刻度,因此 100x100 矩阵的两个函数之间的差异为 0.02 秒,而 10000x10000 矩阵的两个函数之间的差异为 100 秒。

      我还测试了以下内容,它将单元格转换为矩阵,以便两个函数的返回值相同:

      function T = split_by_mat2cell (A, m, n)
        l = size (A) ./ [m n];
        T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1), 1);
        T = reshape (cell2mat (T(:)'), [m n numel(T)]);
      endfunction
      

      这确实会减慢速度,但不足以考虑(线条将在 600x600 而不是 400x400 处交叉)。

      可读性

      要理解嵌套置换和重塑的使用要困难得多。使用它很疯狂。它会增加很多维护时间(但是,这是 Matlab 语言,它不应该是优雅和可重用的)。

      未来

      对 permute 的嵌套调用根本无法很好地扩展到 N 维。我想这将需要一个按维度的 for 循环(这对已经非常神秘的代码毫无帮助)。另一方面,利用mat2cell:

      function T = split_by_mat2cell (A, lengths)
        dl = arrayfun (@(l, s) repmat (l, s, 1), lengths, size (A) ./ lengths, "UniformOutput", false);
        T = mat2cell (A, dl{:});
      endfunction
      

      编辑(也在 Matlab 中测试过)

      对建议使用 permute 和 reshape 的答案的投票数量让我非常好奇,因此我决定在 Matlab (R2010b) 中进行测试。结果几乎相同,即它的性能真的很差。所以除非这个操作会被做很多次,在总是很小(小于 300x300)的矩阵中,并且总会有一个 Matlab 大师来解释它的作用,不要使用它。

      【讨论】:

        【解决方案6】:

        如果你想使用 for 循环,你可以这样做:

        [x,y] = size(matrix)
        
        k=1; % counter
        
        for i = 1:20:x
            for j = 1:20:y
        
                subMatrix=Matrix(i:i+19, j:j+19);
        
                subMatrixCell{k}=subMatrix;  % if you want to save all the
                                            % submatrices into a cell array
                k=k+1;
        
            end
        end   
        

        【讨论】:

          猜你喜欢
          • 2013-04-28
          • 1970-01-01
          • 1970-01-01
          • 2015-03-16
          • 1970-01-01
          • 2011-05-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多