[英]How to fill 2D binary Numpy array without using for loop?
Suppose I have a Numpy array a
and I want to fill the inner with all 1 like array b
假设我有一个 Numpy 数组
a
并且我想像数组b
一样用所有 1 填充内部
print(a)
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 1., 1., 1., 1., 0., 0., 0.],
[0., 1., 0., 1., 1., 1., 1., 1., 0., 0.],
[0., 1., 0., 0., 1., 0., 0., 0., 1., 0.],
[0., 1., 0., 1., 0., 0., 0., 0., 1., 0.],
[0., 1., 0., 1., 0., 0., 0., 1., 0., 0.],
[0., 1., 0., 1., 0., 0., 0., 1., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
print(b)
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 1., 1., 1., 1., 0., 0., 0.],
[0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
[0., 1., 1., 1., 1., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
[0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],
[0., 0., 1., 1., 1., 1., 1., 1., 0., 0.],
[0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
I'm currently using the for
loop to do this, are there any ways to do this without using the for
loop and only using Numpy?我目前正在使用
for
循环来执行此操作,是否有任何方法可以在不使用for
循环且仅使用 Numpy 的情况下执行此操作? Thanks.谢谢。
b = np.zeros(a.shape)
for i in range(a.shape[0]):
occupied = np.where(a[i] == 1)[0]
if len(occupied) > 0:
for j in range(occupied[0], occupied[-1] + 1):
b[i][j] = 1
Edit :编辑:
Can you use scipy?您可以使用 scipy 吗? Do the areas you want to fill always have contiguous boundaries?
您要填充的区域是否始终具有连续的边界?
In [1]: from scipy import ndimage
In [2]: # x = ... copied from OP
In [3]: ndimage.binary_fill_holes(x).astype(int)
Out[3]:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
This is one way to achieve everything in numpy.这是实现 numpy 中所有内容的一种方法。
def dilation(x):
out = x.copy()
# Get mask of non-zeros and then use it to forward-filled indices
r, c = x.nonzero()
bins = np.bincount(r)
indices = np.cumsum(bins)
col_slices = np.split(c, indices)
row_slices = np.split(r, indices)
for rw, cl in zip(row_slices, col_slices):
if cl.size !=0:
out[rw[0], cl[0]:cl[-1]] = 1
return out
We can acheive further speed up by changing the last for loop to list comprehesion.我们可以通过将最后一个 for 循环更改为列表理解来进一步加快速度。 It doesn't delegate the work to underlying C but the assembly code generated is shorter than normal for loop and hence faster.
它不会将工作委托给底层 C,但生成的汇编代码比正常的 for 循环更短,因此速度更快。
def assign_val(out, rw, cl):
out[rw[0], cl[0]:cl[-1]] = 1
def dilation(x):
out = x.copy()
# Get mask of non-zeros and then use it to forward-filled indices
r, c = x.nonzero()
bins = np.bincount(r)
indices = np.cumsum(bins)
col_slices = np.split(c, indices)
row_slices = np.split(r, indices)
[assign_val(out, rw, cl) for rw, cl in zip(row_slices, col_slices) if cl.size !=0]
return out
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.