2012-03-13 11 views
12

Mi objetivo es rastrear dibujos que tienen muchas formas separadas en ellos y dividir estas formas en imágenes individuales. Es negro sobre blanco. Soy bastante nuevo en numpy, OpenCV & co - pero aquí está mi pensamiento actual:Reconocimiento de formas con numpy/scipy (quizás watershed)

  • exploración de píxeles negros
  • píxel negro encontrados ->
  • de cuencas
  • encuentran límite de la cuenca (como la ruta polígono)
  • continuar la búsqueda, pero ignoran los puntos dentro de los límites que ya se encuentran

no soy muy bueno en este tipo de cosas, hay una manera mejor?

Primero trató de encontrar la caja de contorno rectangular de los resultados de las cuencas hidrográficas (esto es más o menos un collage de ejemplos):

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 

De alguna manera, cuando se utiliza la matriz original (a) entonces parece que argwhere funciona, pero después de la cuenca hidrográfica (res) simplemente emite la matriz completa nuevamente.

El siguiente paso podría ser encontrar la ruta del polígono alrededor de la forma, ¡pero el cuadro delimitador sería genial por ahora!

Por favor ayuda!

Respuesta

14

@Hooked ya ha respondido a la mayoría de su pregunta, pero yo estaba en el medio de escribir esto cuando contestó, así que voy a publicar en las esperanzas de que todavía sea útil ...

Estás tratando de pasar por algunos aros demasiados. No necesita watershed_ift.

Utiliza scipy.ndimage.label para diferenciar objetos separados en una matriz booleana y scipy.ndimage.find_objects para encontrar el cuadro delimitador de cada objeto.

Analicemos un poco las cosas.

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

suerte que hace que sea un poco más claro cómo encontrar los cuadros delimitadores de los objetos.

+0

Gracias a ambos por sus respuestas, creo que esto es todo. Solo una nueva pregunta numpy si puedo: no puedo simplemente guardar el área de las rectas de delimitación, porque otras formas estarán 'asomándose'. Así que mi plan es multiplicar el área de la imagen por el conjunto de etiquetas invertidas (para que todo lo que esté fuera de la forma actual se vuelva negro) y luego guardar el área de la imagen con ndimage. ¿Podría señalarme en la dirección correcta cómo hacer esto?Lo sé, tan pronto como tenga el tiempo lo haré con cuidado. – user978250

+1

Creo que solo quieres 'label == num' donde' num' es el número del objeto en 'label' (la matriz etiquetada). Operaciones como esta están vectorizadas en matrices numpy, por lo que es literalmente la declaración anterior. Obtendrá una matriz booleana de 'Verdadero' dentro del 'objeto' y 'Falso' afuera. –

5

Utilice la biblioteca ndimage desde scipy. La función label coloca una etiqueta única en cada bloque de píxeles que están dentro de un umbral. Esto identifica los clusters únicos (formas). A partir de su definición de 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