沿2D阵列中的函数求和

时间:2013-12-30 16:37:35

标签: python arrays performance numpy sum

是否可以在2D数组上放置线性函数,并将2D数组中与函数一致的所有元素相加?因此,例如,我将有一个二维阵列形状说(400,500)。现在在某处,我会重叠一个线性函数,它从2D数组的底部向顶部延伸。我现在只想对与线性线重叠的2D数组的元素求和。

是否有一种快速的方法只能将2D数组的元素与线性线重合?我已经能够通过在for循环中使用for循环来实现。但是,这已经有一段时间了。特别是如果我想开始将这个技巧应用于更大的数组。

1 个答案:

答案 0 :(得分:0)

这在某种程度上取决于你如何完全定义该行,以及哪些数组位置计为" on"这条线。但一种简单的方法是使用布尔掩码。您可以使用numpy.mgrid非常轻松地沿着线定义蒙版:

>>> grid = numpy.mgrid[0:5,0:5]
>>> grid
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]],

       [[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]]])

正如您所看到的,这是一个x和y值的网格,然后您可以将它们与等式相关联:

>>> grid[0] == 2 * grid[1]
array([[ True, False, False, False, False],
       [False, False, False, False, False],
       [False,  True, False, False, False],
       [False, False, False, False, False],
       [False, False,  True, False, False]], dtype=bool)
>>> grid[0] == grid[1]
array([[ True, False, False, False, False],
       [False,  True, False, False, False],
       [False, False,  True, False, False],
       [False, False, False,  True, False],
       [False, False, False, False,  True]], dtype=bool)
>>> grid[0] == grid[1] / 2
array([[ True,  True, False, False, False],
       [False, False,  True,  True, False],
       [False, False, False, False,  True],
       [False, False, False, False, False],
       [False, False, False, False, False]], dtype=bool)

请注意,您可能需要仔细考虑为什么grid[0] == grid[1] / 2会给出"连续"虽然grid[0] == 2 * grid[1]没有,但确切地指出了你想要的行为。 (使用稍微复杂的等式,您可以指定允许您创建不同厚度线的公差值。)

然后你可以用结果掩码做一笔总和:

>>> a = numpy.arange(25).reshape(5, 5)
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
>>> a[grid[0] == grid[1] / 2]
array([ 0,  1,  7,  8, 14])
>>> a[grid[0] == grid[1] / 2].sum()
30

这比嵌套for循环快得多,因为numpy非常快。但它仍然执行相同数量的操作。

另一种方法可能是直接从y值计算x值。这样做的好处是它不需要做很多操作,因此对于非常大的数组来说会更快:

>>> x = numpy.arange(5)
>>> y = x * 2
>>> valid_indices = (x < 5) & (y < 5)
>>> a[x[valid_indices], y[valid_indices]]
array([ 0,  7, 14])

然后只使用.sum()。要显示现在的行:

>>> a[x[valid_indices], y[valid_indices]] = -1
>>> a
array([[-1,  1,  2,  3,  4],
       [ 5,  6, -1,  8,  9],
       [10, 11, 12, 13, -1],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

再次,正如您所看到的那样,线条中存在差距;如果你想要消除这些差距,你必须稍微改变一下#&#34;拉伸&#34; x或y值。这是一个使用简单斜率截距规范的功能。你仍然需要为0和无限斜率添加特殊套管,但这会做很多必要的工作,并且在我测试它的所有情况下产生一个漂亮,流畅的线:

def linear_index(slope, intercept, x_range, y_range):
    if numpy.abs(slope) < 1:
        intercept = intercept / slope
        slope = 1 / slope
        y, x = linear_index(slope, intercept, y_range, x_range)
        return x, y

    x_min, x_max = x_range
    y_min, y_max = y_range
    x = numpy.linspace(x_min, x_max - 1, (x_max - x_min - 1) * slope + 1)
    y = x * slope + intercept
    print x, y
    valid_indices = (y >= y_min) & (y < y_max)
    return x[valid_indices].astype(int), y[valid_indices].astype(int)

如果对Hough Transform有充分的了解,那么将(r, theta)对转换为斜率截距形式应该没有问题。不过,如果你需要更粗的线,这可能不是最好的方法。