矢量化函数在三维数组中找到极值(MATLAB)

时间:2016-02-16 18:02:39

标签: matlab max vectorization minimum

我在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));

1 个答案:

答案 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)的线性索引。