我在Matlab中有一个3D矩阵A
。我想使用3x3x3移动窗口在此矩阵中找到局部极值(最小值和最大值)。也就是说,我希望所有索引i,j,k
都满足
tmp = A(i-1:i+1,j-1:j+1,k-1:k+1)
A(i,j,k) == min(tmp(:)) || A(i,j,k) == max(tmp(:))
我有一个使用嵌套for循环的脚本(见下文),使用上面的标准找到极值。我只是想知道是否有办法对操作进行矢量化。
我还应该提到边界是周期性的;例如,在{i,j,k} = {1,1,1}
点,评估应为
tmp = A([end,1,2],[end,1,2],[end,1,2])
A(1,1,1) == min(tmp(:)) || A(1,1,1) == max(tmp(:))
上述脚本如下:
s = size(A);
% Make outer boundaries equal
A1 = [A(end,:,:); A; A(1,:,:)];
A1 = [A1(:,end,:), A1, A1(:,1,:)];
A2 = NaN(s + [2 2 2]);
A2(:,:,1) = A1(:,:,end);
A2(:,:,2:end-1) = A1;
A2(:,:,end) = A1(:,:,1);
% Create arrays to record extrema
minvals = false(s); maxvals = minvals;
for i = 2:s(1)+1
for j = 2:s(2)+1
for k = 2:s(3)+1
tmp = A2(i-1:i+1,j-1:j+1,k-1:k+1);
a = A2(i,j,k);
if a == min(tmp(:))
minvals(i-1,j-1,k-1) = true;
end
if a == max(tmp(:))
maxvals(i-1,j-1,k-1) = true;
end
end
end
end
[MINidc.i, MINidc.j, MINidc.k] = ind2sub(s,find(minvals));
[MAXidc.i, MAXidc.j, MAXidc.k] = ind2sub(s,find(maxvals));
答案 0 :(得分:1)
这就是我对此进行矢量化的方法:
s=size(A);
s2=cumprod(s);
%For all indices 1:numel(a) build up a table with the neibours among 1. dimension
x=bsxfun(@plus,(1:numel(A)).',cat(2,-1,0,1));
%and second dimension
x=bsxfun(@plus,x,cat(3,-s2(1),0,s2(1)))
%and third dimension
x=bsxfun(@plus,x,cat(4,-s2(2),0,s2(2)));
%reshape to have one row for each element
x=reshape(x,[],27);
%wrap around borders
x=mod(x-1,numel(A))+1;
%use index matrix to get a matrix of values
B=A(x);
%the 14th element is the center of a 27 element cube.
local_maxima=max(B,[],2)==B(:,14);
local_minima=min(B,[],2)==B(:,14);
[MINidc.i, MINidc.j, MINidc.k] = ind2sub(s,find(local_minima));
[MAXidc.i, MAXidc.j, MAXidc.k] = ind2sub(s,find(local_maxima));
我们的想法是首先建立一个矩阵,其中包含作为元素邻居的所有索引。如果您打算理解代码,请将(1:numel(A)).'
替换为创建多维数据集A(2,2,2)
的元素A(1:3,1:3,1:3)
的线性索引。