2016-01-11 3 views
2

я принципиально хочу, чтобы обрезать изображение с NumPy-У меня есть 3-размерный numpy.ndarray объект, то есть:Удалить пустые «строки» и «столбцы» из 3D Numpy массива пикселей

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

, где я хочу, чтобы удалить пробелы, которые в контексте известны как целые строки или целые столбцы [0,0,0,0].

Позволить каждый пиксель просто номер для этого примера, я пытаюсь сделать это по существу:

Учитывая это: * EDIT: выбрал несколько более сложный пример, чтобы уточнить

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

Я перебирает это с Ио ops, но интуитивно я чувствую, что numpy имеет лучшее средство для этого.

ответ

4

В общем, вы хотите посмотреть в scipy.ndimage.label и scipy.ndimage.find_objects для выделения ограничивающей рамки смежных областей, выполняющей условие.

Однако в этом случае вы можете сделать это довольно легко с помощью «простого» 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]) 

Если ни один элемент не является Истиной, мы получим 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]]) 
0

Вы можете использовать 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]]) 
+0

Это предполагает, что регион является известным прямоугольным форма. –

+0

как насчет столбцов с нулевыми значениями? – keksnicoh

+0

Ну, это * будет * быть прямоугольником, поскольку я только хочу удалить полностью пустые строки/столбцы. – Jonline

Смежные вопросы