【问题标题】:Vectorized function to find extrema in 3D array (MATLAB)用于在 3D 数组中查找极值的矢量化函数(MATLAB)
【发布时间】:2016-05-28 03:56:00
【问题描述】:

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

【问题讨论】:

  • 你的矩阵有多大?向量化这个(我现在不确定如何)需要为每个 max 调用创建一个单独的行。这会将您的数据放大 27 倍。这是可行的还是会超出内存?
  • @Daniel 在我的特殊情况下,这不是问题。事实上,for 循环的实现运行得足够快。我问更多是出于好奇。所以让我们假设内存增加 27 倍不是问题。
  • @Divakar:我看不出与那个问题有关联。

标签: matlab max vectorization minimum


【解决方案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(1:3,1:3,1:3) 的元素A(2,2,2) 的线性索引。

【讨论】:

  • 不错。对于具有五个极值的 30x30x30 测试矩阵,您的代码运行速度比我的快 80%。
猜你喜欢
  • 2015-02-01
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 2015-02-21
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多