use*_*703 11 matlab loops octave
给定一个说大小的方阵400x400,如何将其拆分为20x20使用for-loop的组成子矩阵?我甚至不知道从哪里开始!
我想我想要的东西:
[x,y] = size(matrix)
for i = 1:20:x
for j = 1:20:y
Run Code Online (Sandbox Code Playgroud)
但我不确定如何继续下去.思考?
A. *_*nda 23
嗯,我知道海报明确要求for循环,而杰夫马瑟的回答恰恰提供了.
但我仍然很好奇是否有可能在没有循环的情况下将矩阵分解为给定大小的瓦片(子矩阵).如果其他人也很好奇,这就是我想出的:
T = permute(reshape(permute(reshape(A, size(A, 1), n, []), [2 1 3]), n, m, []), [2 1 3])
Run Code Online (Sandbox Code Playgroud)
将二维数组A转换为三维数组T,其中每个2d切片T(:, :, i)是大小为mx的切片之一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]);
Run Code Online (Sandbox Code Playgroud)
制作T一个四维数组,T(:, :, i, j)给出带有图块索引的2d切片i, j.
提出这些表达感觉有点像解决滑动拼图.;-)
Kla*_*CPH 14
对不起,我的回答也没有使用for循环,但这也可以解决问题:
cellOf20x20matrices = mat2cell(matrix, ones(1,20)*20, ones(1,20)*20)
Run Code Online (Sandbox Code Playgroud)
然后,您可以访问单个单元格,如:
cellOf20x20matrices{i,j}(a,b)
Run Code Online (Sandbox Code Playgroud)
其中i,j是要获取的子矩阵(如果需要,a,b是索引到该矩阵中)
问候
Jef*_*her 10
你似乎很亲密.只是使用你所描述的问题(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
Run Code Online (Sandbox Code Playgroud)
虽然问题基本上是针对2D矩阵,但受到A. Donda的回答的启发,我想扩展他对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
Run Code Online (Sandbox Code Playgroud)
基本思路是在重塑时不使第3维度受影响,以免图像失真.为实现此目的,进行了额外的置换以交换第3维和第4维.完成该过程后,通过置换来恢复尺寸.
原始图像

子图(分区/子矩阵)

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

对于使用嵌套调用的答案有一些很多的赞成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
Run Code Online (Sandbox Code Playgroud)

性能方面,对于较小的矩阵,使用嵌套的置换只会更快,相对性能的重大变化实际上是非常小的时间变化.请注意,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
Run Code Online (Sandbox Code Playgroud)
这确实减慢了一点但不足以考虑(线将以600x600而不是400x400交叉).
让你的头围绕使用嵌套的置换和重塑是非常困难的.使用它真是太疯狂了.它会增加很多维护时间(但是,嘿,这是Matlab语言,它不应该是优雅和可重用的).
对置换的嵌套调用根本不能很好地扩展到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
Run Code Online (Sandbox Code Playgroud)
对答案表示使用置换和重塑的答案的数量让我非常好奇,我决定在Matlab(R2010b)中进行测试.结果几乎相同,即它的表现非常糟糕.因此,除非这个操作将会进行很多次,总是很小(小于300x300)的矩阵,并且总会有一个Matlab大师来解释它的作用,不要使用它.
| 归档时间: |
|
| 查看次数: |
7998 次 |
| 最近记录: |