【问题标题】:Numpy Average distance from array centerNumpy 到阵列中心的平均距离
【发布时间】:2017-04-10 19:07:58
【问题描述】:

我有一个数组的中心点,

center_point = (array.shape[0]/2.,array.shape[1]/2.)

我有一个二进制图像数组array,它的形状相关像素设置为 0(所有其他像素为 255)。


对于所有设置为零的像素,我需要到数组中心的平均距离,并且我需要对其进行矢量化(它不能在 python 级别解释——速度很慢)。

这就是我所拥有的,现在我被卡住了,因为我找到的其他答案指向 SciPy,但服务器 only 支持 numpy。

centerpoint = array_center_point(shape_array)
distance_shape = np.zeros(size=shape_array.shape,dtype=float)

distance_shape[shape==0] = ...???

avg_distance = np.sum(distance_shape) / len(np.where(shape_array == 0)[0])

如果不多次调用 np.where 并使用 python for 循环遍历形状索引,我无法弄清楚如何做到这一点。一定有办法在 numpy 代码中完成这项工作...??


这是有效的非矢量化版本:

def avg_distance_from_center(shape_array):
    center_point = array_center_point(shape_array)
    distance_shape = np.zeros(shape=shape_array.shape, dtype=float)

    shape_pixels = np.where(shape_array == 0)
    total_distance = 0.
    for i in range(len(shape_pixels[0])):
        i_ind = float(shape_pixels[0][i])
        j_ind = float(shape_pixels[1][i])

        total_distance += ((i_ind - center_point[0])**2.0 + (j_ind - center_point[1])**2.0)**0.5
    avg_distance = total_distance / len(shape_pixels[0])

    return avg_distance

【问题讨论】:

  • 编写一个我们可以尝试矢量化的有效循环实现?
  • @Divakar 好的,会的……等一下
  • 如果你说“只有 numpy”是否包括 cython(构建依赖)?
  • @MSeifert 基本上,如果代码有标题,import numpy as np 它将在服务器上运行。除此之外,我不能说。将在几秒钟内建立循环版本

标签: python arrays performance numpy vectorization


【解决方案1】:

方法 #1: 使用 NumPy broadcasting -

np.sqrt(((np.argwhere(shape_array==0) - center_point)**2).sum(1)).mean()

方法 #2: 使用 np.einsum -

subs = (np.argwhere(a==0) - center_point)
out = np.sqrt(np.einsum('ij,ij->i',subs,subs)).mean()

【讨论】:

  • argwhere 的使用非常巧妙,我希望我能多次投票!但是请注意:我通常提倡np.hypot 而不是sqrtsquare,因为实现可能会更快并且它是overflowunderflow 安全(在这种特殊情况下,它并不重要)。
  • @MSeifert 嗯,我不知道这些替代方案的性能标准,很高兴知道!很高兴看到你指出这些,谢谢!
  • 这很棒,适用于曼哈顿从一个索引到所有其他索引的距离:h_map[h_map==0] = np.abs((np.argwhere(h_map!=0) - np.argwhere(h_map==100)).sum(1))
【解决方案2】:

为了说明,我使用了一个随机数组:

>>> import numpy as np
>>> arr = (np.random.random((5, 5)) > 0.5).astype(int)
>>> arr
array([[0, 0, 0, 1, 0],
       [0, 0, 1, 1, 1],
       [0, 1, 0, 0, 1],
       [1, 0, 0, 1, 0],
       [1, 0, 1, 0, 1]])
>>> center = (2, 2)  # use your center here

为了获得距离,我将使用网格:

>>> grid_x, grid_y = np.mgrid[0:arr.shape[0], 0:arr.shape[1]]
>>> grid_x
array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4]])
>>> grid_y
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])

我们将网格平移到中心坐标:

>>> grid_x = grid_x - center[0]
>>> grid_y = grid_y - center[1]

最后我们使用np.hypot 函数(几乎与np.sqrt(x**2 + y**2) 相同)计算距离,但仅使用arr == 0 所在的点:

>>> distances = np.hypot(grid_x[arr == 0], grid_y[arr == 0])

现在是时候计算距离的平均值了:

>>> np.mean(distances)
2.767080465988093

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 2019-11-21
    • 1970-01-01
    • 2021-08-30
    • 2017-06-15
    • 1970-01-01
    相关资源
    最近更新 更多