【问题标题】:Fast way to find locally maximal gradient values in a numpy array?在 numpy 数组中找到局部最大梯度值的快速方法?
【发布时间】:2011-11-18 05:23:09
【问题描述】:

我有一个二维数组,我想检测它的所有局部最大数组索引。也就是说,给定一个索引 (i, j),它的最大梯度是其 8 个相邻值中的任何一个的最大绝对变化:

Index: (i, j)

Neighbors:
(i-1,j+1)  (i,j+1)  (i+1,j+1)
(i-1,j)    [index]    (i+1,j)
(i-1,j-1)  (i,j-1)  (i+1,j-1)

Neighbor angles:
315           0            45
270        [index]         90
225          180          135

MaxGradient(i,j) = Max(|Val(index) - Val(neighbor)|)

如果它的 MaxGradient 至少与其邻居的任何 MaxGradient 一样大,则称该索引为局部最大值

算法的输出应该是一个二维元组数组或一个 3 维数组,其中对于原始数组中的每个索引,输出数组包含一个值,该值指示该索引是否为局部最大值,如果所以,渐变的角度。

我最初的实现只是简单地传递了数组两次,一次是为了计算最大梯度(存储在一个临时数组中),然后一次是临时数组以确定局部最大索引。每次,我都通过 for 循环执行此操作,分别查看每个索引。

在 numpy 中有没有更有效的方法来做到这一点?

【问题讨论】:

  • 在这种情况下,梯度是用词不当,不是吗?你真的在计算差异,如果你想要梯度,“对角线”邻居的计算必须不同于“行和列”邻居
  • 这是一个很好的观点。我想我可能误解了算法。这是AIMA(第三版)书中边缘检测算法的后半部分。

标签: python matrix numpy linear-algebra


【解决方案1】:

考虑这 8 个相关指标:

X1 X2 X3
X4 X  X5
X6 X7 X8

您可以计算每个像素 X 的差异D1=Val(X)-Val(X1)D2=Val(X)-Val(X2)D3=Val(X)-Val(X3)D4=Val(X)-Val(X4)。您不需要计算其他差异,因为它们是前四个差异的镜像。 要计算差异,您可以用一行和一列零填充图像并减去。

【讨论】:

  • 那不只是计算 X1-X 吗?
  • @Wesley,要计算 X-X2,填充一行而不是一列和一行。
  • 所以我基本上会创建 8 个数组(4 个填充 + 4 个结果数组),然后有没有一些快速的方法来获取四个结果数组中的每一个的最大值?
  • 不要循环,只使用numpy.maximum。您可以在新维度中连接数组。
【解决方案2】:

正如 Cyborg 指出的那样,只需计算四个差异即可完成计算(请注意,如果这确实是空间计算,则对角线和对角线计算确实应该有 1/sqrt(2) 的因子均匀网格上的梯度计算)。如果我理解了你的问题,numpy 的实现可能是这样的:

A=np.random.random(100).reshape(10,10)

# Padded copy of A
B=np.empty((12,12))
B[1:-1,1:-1]=A
B[0,1:-1]=A[0,:]   
B[-1,1:-1]=A[-1,:]
B[1:-1,0]=A[:,0]
B[1:-1,-1]=A[:,-1]
B[0,0]=A[1,1]
B[-1,-1]=A[-1,-1]
B[-1,0]=A[-1,0]
B[0,1]=A[0,1]

# Compute 4 absolute differences
D1=np.abs(B[1:,1:-1]-B[:-1,1:-1]) # first dimension
D2=np.abs(B[1:-1,1:]-B[1:-1,:-1]) # second dimension
D3=np.abs(B[1:,1:]-B[:-1,:-1]) # Diagonal
D4=np.abs(B[1:,:-1]-B[:-1,1:]) # Antidiagonal

# Compute maxima in each direction
M1=np.maximum(D1[1:,:],D1[:-1,:])
M2=np.maximum(D2[:,1:],D2[:,:-1])
M3=np.maximum(D3[1:,1:],D3[:-1,:-1])
M4=np.maximum(D4[1:,:-1],D4[:-1,1:])

# Compute local maximum for each entry
M=np.max(np.dstack([M1,M2,M3,M4]),axis=2)

这将使您在 M 中的输入 A 的 4 个方向中的每一个上都有最大差异。类似的想法可用于标记局部最大值,最终形成类似

T=np.where((M==np.max(np.dstack([Ma,Mb,Mc,Md,Me,Mf,Mg,Mh]),axis=2)))

这会给你一个数组,其中包含 M 中局部最大值的坐标

【讨论】:

    猜你喜欢
    • 2016-05-18
    • 2012-05-07
    • 2014-03-18
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    相关资源
    最近更新 更多