[英]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.label
和scipy.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.nonzero
為np.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.