簡體   English   中英

如何在不使用 for 循環的情況下填充二維二進制 Numpy 數組?

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

編輯

  • 僅使用 Numpy
  • 我要填充的區域總是有連續的邊界。

您可以使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM