三维阵列中求极值的矢量化函数(MATLAB)

三维阵列中求极值的矢量化函数(MATLAB),matlab,max,vectorization,minimum,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

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

以下是我将如何将其矢量化:

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)

矩阵有多大?矢量化(我不知道目前如何)需要为max的每次调用创建一个单独的行。这会将数据放大27倍。这是可行的还是会超出内存?看看是否有帮助。@Daniel在我的特殊情况下,这不会是一个问题。事实上,for循环实现的工作速度足够快。我问的更多是出于好奇。所以让我们假设27倍的内存增长不是问题。@Divakar:我看不出和这个问题有什么联系。很好。对于具有五个极值的30x30x30测试矩阵,您的代码比我的代码运行速度快80%。