![](/img/trans.png)
[英]how to modify a 2D numpy array at specific locations without a loop?
[英]How to fill 2D binary Numpy array without using for loop?
假設我有一個 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.]])
我目前正在使用for
循環來執行此操作,是否有任何方法可以在不使用for
循環且僅使用 Numpy 的情況下執行此操作? 謝謝。
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
編輯:
您可以使用 scipy 嗎? 您要填充的區域是否始終具有連續的邊界?
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]])
這是實現 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
我們可以通過將最后一個 for 循環更改為列表理解來進一步加快速度。 它不會將工作委托給底層 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.