2012-03-13 13 views
12

Il mio obiettivo è tracciare disegni che contengono molte forme separate e suddividere queste forme in singole immagini. È nero su bianco. Sono abbastanza nuovo per NumPy, OpenCV & co - ma qui è il mio pensiero attuale:Riconoscimento forme con numpy/scipy (forse spartiacque)

  • scansione per pixel neri
  • pixel nero trovati -> spartiacque
  • trovare confine spartiacque (come percorso poligono)
  • continuare la ricerca, ma ignorano i punti all'interno dei confini già trovati

io non sono molto bravo a questo genere di cose, c'è un modo migliore?

ho cercato di trovare il riquadro rettangolare dei risultati di bacino (questo è più o meno un collage di esempi):

from numpy import * 
import numpy as np 
from scipy import ndimage 

np.set_printoptions(threshold=np.nan) 

a = np.zeros((512, 512)).astype(np.uint8) #unsigned integer type needed by watershed 
y, x = np.ogrid[0:512, 0:512] 
m1 = ((y-200)**2 + (x-100)**2 < 30**2) 
m2 = ((y-350)**2 + (x-400)**2 < 20**2) 
m3 = ((y-260)**2 + (x-200)**2 < 20**2) 
a[m1+m2+m3]=1 

markers = np.zeros_like(a).astype(int16) 
markers[0, 0] = 1 
markers[200, 100] = 2 
markers[350, 400] = 3 
markers[260, 200] = 4 

res = ndimage.watershed_ift(a.astype(uint8), markers) 
unique(res) 

B = argwhere(res.astype(uint8)) 
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1 
tr = a[ystart:ystop, xstart:xstop] 

print tr 

qualche modo, quando si utilizza l'array originale (a) quindi argwhere sembra funzionare, ma dopo lo spartiacque (res), restituisce di nuovo l'array completo.

Il prossimo passo potrebbe essere trovare il percorso del poligono attorno alla forma, ma per il momento il riquadro di selezione sarebbe ottimo!

Si prega di aiuto!

risposta

14

@Hooked ha già risposto la maggior parte della tua domanda, ma ero nel bel mezzo della stesura di questo quando ha risposto, quindi mi post it in le speranze che sia ancora utile ...

Stai provando a saltare attraverso alcuni troppi cerchi. Non hai bisogno di watershed_ift.

È possibile utilizzare scipy.ndimage.label per differenziare gli oggetti separati in un array booleano e scipy.ndimage.find_objects per trovare il riquadro di delimitazione di ciascun oggetto.

Rompiamo le cose un po '.

import numpy as np 
from scipy import ndimage 
import matplotlib.pyplot as plt 

def draw_circle(grid, x0, y0, radius): 
    ny, nx = grid.shape 
    y, x = np.ogrid[:ny, :nx] 
    dist = np.hypot(x - x0, y - y0) 
    grid[dist < radius] = True 
    return grid 

# Generate 3 circles... 
a = np.zeros((512, 512), dtype=np.bool) 
draw_circle(a, 100, 200, 30) 
draw_circle(a, 400, 350, 20) 
draw_circle(a, 200, 260, 20) 

# Label the objects in the array. 
labels, numobjects = ndimage.label(a) 

# Now find their bounding boxes (This will be a tuple of slice objects) 
# You can use each one to directly index your data. 
# E.g. a[slices[0]] gives you the original data within the bounding box of the 
# first object. 
slices = ndimage.find_objects(labels) 

#-- Plotting... ------------------------------------- 
fig, ax = plt.subplots() 
ax.imshow(a) 
ax.set_title('Original Data') 

fig, ax = plt.subplots() 
ax.imshow(labels) 
ax.set_title('Labeled objects') 

fig, axes = plt.subplots(ncols=numobjects) 
for ax, sli in zip(axes.flat, slices): 
    ax.imshow(labels[sli], vmin=0, vmax=numobjects) 
    tpl = 'BBox:\nymin:{0.start}, ymax:{0.stop}\nxmin:{1.start}, xmax:{1.stop}' 
    ax.set_title(tpl.format(*sli)) 
fig.suptitle('Individual Objects') 

plt.show() 

enter image description here enter image description here enter image description here

Speriamo che lo rende un po 'più chiaro come trovare i rettangoli di selezione degli oggetti.

+0

Grazie a tutti e due per le vostre risposte, penso che sia così. Solo una domanda da novizio per principianti se posso: non posso semplicemente salvare l'area dei reces di delimitazione, perché altre forme faranno 'sbirciare'. Quindi il mio piano è di moltiplicare l'area dell'immagine per l'array di etichette invertite (quindi tutto al di fuori della forma corrente diventa nero) e quindi salvare l'area dell'immagine con ndimage. Potresti indicarmi la giusta direzione su come farlo?Lo so, non appena avrò il tempo scriverò attentamente! – user978250

+1

Penso che vogliate 'label == num' dove' num' è il numero dell'oggetto in 'label' (l'array etichettato). Operazioni come questa sono vettorizzate su array numpy, quindi è letteralmente la dichiarazione di cui sopra. Otterrai un array booleano di 'True' all'interno di" object "e' False' all'esterno. –

5

Utilizzare la libreria ndimage da scipy. La funzione label inserisce un tag univoco su ciascun blocco di pixel che si trova all'interno di una soglia. Questo identifica i cluster unici (forme). A partire con la tua definizione di a:

from scipy import ndimage 

image_threshold = .5 
label_array, n_features = ndimage.label(a>image_threshold) 

# Plot the resulting shapes 
import pylab as plt 
plt.subplot(121) 
plt.imshow(a) 
plt.subplot(122) 
plt.imshow(label_array) 
plt.show() 

enter image description here