2011-01-26 13 views
16

Mam do czynienia z tablicami utworzonymi za pomocą numpy.array(), i muszę narysować punkty na płótnie symulującym obraz. Ponieważ istnieje dużo zerowych wartości wokół środkowej części tablicy, która zawiera znaczące dane, chciałbym "przyciąć" tablicę, usuwając kolumny, które zawierają tylko zera i wiersze, które zawierają tylko zera.Czy istnieje funkcja "ramki ograniczającej" (wycinek o wartościach niezerowych) dla ndarray w NumPy?

Chciałbym więc poznać jakąś natywną funkcję numpy, a nawet fragment kodu służący do "przycinania" lub znajdowania "obwiedni" do wycinania tylko części tablicy zawierającej dane.

(., Ponieważ jest to koncepcyjne pytanie, nie umieścić dowolny kod, przepraszam, czy powinienem, jestem bardzo świeże do opublikowania na SO)

Dzięki za czytanie

+0

http://stackoverflow.com/questions/31400769/bounding-box-of-numpy-array zobacz funkcję bbox2 ... DUŻO szybciej, jeśli jest wiele wierszy/kolumn całkowicie wypełnionych zerami i tylko niewielka ilość dane w klastrze. – Benjamin

Odpowiedz

6

Poniższy kod, z this answer biegnie najszybciej w moich testów:

def bbox2(img): 
    rows = np.any(img, axis=1) 
    cols = np.any(img, axis=0) 
    ymin, ymax = np.where(rows)[0][[0, -1]] 
    xmin, xmax = np.where(cols)[0][[0, -1]] 
    return img[ymin:ymax+1, xmin:xmax+1] 

Zaakceptowanych odpowiedź za pomocą argwhere działało, ale biegł wolniej. Domyślam się, to dlatego, że argwhere przydziela gigantyczną tablicę wyjściową indeksów. Testowałem na dużej matrycy 2D (obraz 1024 x 1024, z mniej więcej niezerowym regionem 50x100).

+0

Znalazłem tę odpowiedź bardziej pythonic! Dzięki! – heltonbiker

+0

Uwaga: ten kod może generować błąd w przypadku krawędzi całkowicie czarnego obrazu. Musisz sprawdzić, czy żadne z dwóch wywołań 'np.where()' nie zwraca pustej tablicy. – Delgan

0

coś takiego:

empty_cols = sp.all(array == 0, axis=0) 
empty_rows = sp.all(array == 0, axis=1) 

Powstałe tablice będą tablicami 1-bajtowymi. Zapętlaj je z obu końców, aby znaleźć "obwiednię".

+1

należy unikać pętli nad niewidocznymi tablicami – Paul

+0

Pętla to tylko 1D, więc zamów n, nie n^2. Nie tak wielka sprawa. – kiyo

+1

Masz rację co do kolejności i nie potrzebujesz nawet pętli na całej szerokości tablicy, ale pętla pytona zawiera wszystkie dodatkowe kroki, takie jak sprawdzanie typu. W tym przykładzie 1D: http://www.scipy.org/Getting_Started#head-9aed725bd569d40f625240b2b6ec710550ff14b9 Pętla Pythona działa 25 razy wolniej, aby wykonać to samo zadanie! Nie znając rozmiaru ani ilości obrazów ani zastosowania algorytmu (wizji komputerowej?), Nie mogę powiedzieć, jak duża jest tego rodzaju przyspieszanie. – Paul

20

ten powinien zrobić:

from numpy import array, argwhere 

A = array([[0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 1, 0, 0, 0, 0], 
      [0, 0, 1, 1, 0, 0, 0], 
      [0, 0, 0, 0, 1, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0]]) 

B = argwhere(A) 
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1 
Atrim = A[ystart:ystop, xstart:xstop] 
+1

Nice! Po prostu na notatce czytelności, możesz zrobić '(ystart, xstart), (ystop, xstop) = B.min (0), B.max (0) + 1', a następnie po prostu indeksować' A' z 'Atrim = a [ystart: ystop, xstart: xstop] '. Oczywiście jest to całkowicie równoważne, ale uważam, że w każdym razie jest bardziej czytelny. –

+0

Gotowe. Dzięki, Joe. – Paul

+0

Ten był świetny, użyty przykład jest dokładnie typową tablicą, której będę używał (tylko większy). Nie znałem funkcji w tym miejscu, odtworzę teraz moją pracę domową. Dzięki! – heltonbiker