簡體   English   中英

從3D numpy像素陣列中刪除空的“行”和“列”

[英]Remove empty 'rows' and 'columns' from 3D numpy pixel array

我本質上想使用numpy裁剪圖像-我有一個3維的numpy.ndarray對象,即:

[ [0,0,0,0], [255,255,255,255], ....]
  [0,0,0,0], [255,255,255,255], ....] ]

我想刪除空白,在上下文中,空白是[0,0,0,0]整個行或整個列。

在這個例子中,讓每個像素只是一個數字,我試圖做到這一點:

鑒於此:*編輯:選擇了一個稍微復雜一些的示例進行說明

[ [0,0,0,0,0,0] [0,0,1,1,1,0] [0,1,1,0,1,0] [0,0,0,1,1,0] [0,0,0,0,0,0]]

我正在嘗試創建這個:

[ [0,1,1,1], [1,1,0,1], [0,0,1,1] ]

我可以使用循環來強行執行此操作,但是從直覺上來說,我覺得numpy可以做到這一點。

通常,您需要研究scipy.ndimage.labelscipy.ndimage.find_objects以提取滿足條件的連續區域的邊界框。

但是,在這種情況下,您可以使用“ plain” numpy相當容易地做到這一點。

我將假設您在這里有一個nrows x ncols x nbands數組。 nbands x nrows x ncols的另一種約定也很常見,因此請看一下數組的形狀。

考慮到這一點,您可能會執行以下操作:

mask = im == 0
all_white = mask.sum(axis=2) == 0
rows = np.flatnonzero((~all_white).sum(axis=1))
cols = np.flatnonzero((~all_white).sum(axis=0))

crop = im[rows.min():rows.max()+1, cols.min():cols.max()+1, :]

對於您的2D示例,它看起來像:

import numpy as np

im = np.array([[0,0,0,0,0,0],
               [0,0,1,1,1,0],
               [0,1,1,0,1,0],
               [0,0,0,1,1,0],
               [0,0,0,0,0,0]])

mask = im == 0
rows = np.flatnonzero((~mask).sum(axis=1))
cols = np.flatnonzero((~mask).sum(axis=0))

crop = im[rows.min():rows.max()+1, cols.min():cols.max()+1]
print crop

讓我們分解一下2D示例。

In [1]: import numpy as np

In [2]: im = np.array([[0,0,0,0,0,0],
   ...:                [0,0,1,1,1,0],
   ...:                [0,1,1,0,1,0],
   ...:                [0,0,0,1,1,0],
   ...:                [0,0,0,0,0,0]])

好的,現在讓我們創建一個滿足條件的布爾數組:

In [3]: mask = im == 0

In [4]: mask
Out[4]:
array([[ True,  True,  True,  True,  True,  True],
       [ True,  True, False, False, False,  True],
       [ True, False, False,  True, False,  True],
       [ True,  True,  True, False, False,  True],
       [ True,  True,  True,  True,  True,  True]], dtype=bool)

另外,請注意~運算符在布爾數組上的功能為logical_not

In [5]: ~mask
Out[5]:
array([[False, False, False, False, False, False],
       [False, False,  True,  True,  True, False],
       [False,  True,  True, False,  True, False],
       [False, False, False,  True,  True, False],
       [False, False, False, False, False, False]], dtype=bool)

考慮到這一點,要查找所有元素均為假的行,我們可以跨列求和:

In [6]: (~mask).sum(axis=1)
Out[6]: array([0, 3, 3, 2, 0])

如果沒有元素為True,我們將得到0。

同樣,要查找所有元素均為假的列,我們可以對行進行求和:

In [7]: (~mask).sum(axis=0)
Out[7]: array([0, 1, 2, 2, 3, 0])

現在,我們需要做的就是找到第一個和最后一個不為零的內容。 np.flatnonzero比起來更輕松的nonzero ,在這種情況下:

In [8]: np.flatnonzero((~mask).sum(axis=1))
Out[8]: array([1, 2, 3])

In [9]: np.flatnonzero((~mask).sum(axis=0))
Out[9]: array([1, 2, 3, 4])

然后,您可以根據最小/最大非零元素輕松切出區域:

In [10]: rows = np.flatnonzero((~mask).sum(axis=1))

In [11]: cols = np.flatnonzero((~mask).sum(axis=0))

In [12]: im[rows.min():rows.max()+1, cols.min():cols.max()+1]
Out[12]:
array([[0, 1, 1, 1],
       [1, 1, 0, 1],
       [0, 0, 1, 1]])

您可以使用np.nonzero函數找到零值,然后從原始數組中切出非零元素,並np.nonzeronp.nonzero

import numpy as np
n = np.array([ [0,0,0,0,0,0],
   [0,0,1,1,1,0],
   [0,0,1,1,1,0],
   [0,0,1,1,1,0],
   [0,0,0,0,0,0]])

elems = n[n.nonzero()]

In [415]: elems
Out[415]: array([1, 1, 1, 1, 1, 1, 1, 1, 1])

In [416]: elems.reshape(3,3)
Out[416]: 
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

針對任意維度實現此目標的一種方法是:

import numpy as np

def trim(arr, mask):
    bounding_box = tuple(
        slice(np.min(indexes), np.max(indexes) + 1)
        for indexes in np.where(mask))
    return arr[bounding_box]

FlyingCircus中提供了一種稍微更靈活的解決方案(您可以在其中指示要作用於哪個軸)( 免責聲明 :我是軟件包的主要作者)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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