这在一定程度上取决于您准确如何定义线,以及哪些数组位置算作“在线”上。但一种简单的方法是使用布尔掩码。你可以很容易地使用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 非常快。但它仍然执行相同数量的操作。
另一种方法可能是直接从x 值计算y 值。这样做的好处是它不必执行太多操作,因此对于非常非常大的数组会更快:
>>> 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]])
再一次,正如您所见,这条线上有空隙;如果你想消除这些差距,你必须通过“拉伸”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) 对转换为斜率截距形式。不过,如果您需要更粗的线,这可能不是最好的方法。