9

Esta pregunta es un tanto independiente del idioma, pero mi herramienta de elección pasa a ser una matriz numpy.regiones en blanco en la imagen

Lo que estoy haciendo es tomar la diferencia de dos imágenes a través de PIL:

img = ImageChops.difference(img1, img2) 

Y quiero encontrar las regiones rectangulares que contienen cambios de una imagen a otra. Por supuesto está el método construido en .getbbox(), pero si hay dos regiones con cambios devolverá un cuadro de una región a otra, y si solo hay 1 cambio de píxel en cada esquina, devolverá la imagen completa.

Por ejemplo considere el siguiente, donde o es un píxel distinto de cero:

______________________ 
|o   ooo | 
|  oooo ooo | 
|  o    | 
|  o o   | 
|     | 
|  oo  o  | 
| o o  ooo | 
|  oo  ooooo | 
|    ooo | 
|    o  | 
|____________________| 

me gustaría llegar 4x4-tuplas que contienen los cuadros delimitadores de cada región que no sea cero. Para el caso borde de la estructura

oooo 
o 
o o 

, no estoy muy preocupado cómo lo maneja - ya sea con dos secciones por separado o juntos, porque los límites de la forma invertida-L se solapan por completo los límites de la sola pixel

Nunca he hecho algo así de avanzado con el procesamiento de imágenes, así que quería obtener algo de información antes de escribir algo (y si hay métodos preexistentes en los módulos que ya uso, ¡los recibo!) .

Mi versión psuedocode-ish es algo como esto:

for line in image: 
    started = False 
    for pixel in line: 
     if pixel and not started: 
     started = True 
     save start coords 
     elif started and not pixel: 
     started = False 
     save end coords (x - 1 of course) 

Esto me debe dar una lista de coordenadas, pero luego tengo que determinar si las regiones son contiguas. ¿Podría hacer eso con una búsqueda de tipo gráfico? (Hicimos mucho DFS y BFS en Algoritmos el semestre pasado) Por supuesto que creo que podría hacer eso en lugar de/junto con mis ciclos anteriores?

no voy a estar haciendo esto en imágenes "grandes" - que están sacados de una cámara web y el mejor momento tengo hace 640x480. A lo sumo estaría haciendo 720p o 1080p, pero eso es lo suficientemente lejos en el futuro como para que no sea una preocupación real.

Así que mi pregunta (s): ¿Soy yo nos dirigimos por el camino correcto, o estoy muy lejos? Y más importante, ¿hay funciones integradas que me impidan reinventar la rueda? Y finalmente, ¿hay algún buen recurso que debería considerar (tutoriales, documentos, etc.) que ayude aquí?

Gracias!

Respuesta

17

creo scipy's ndimage module tiene todo lo que necesita ...

Aquí está un ejemplo rápido

import numpy as np 
import scipy as sp 
import scipy.ndimage.morphology 

# The array you gave above 
data = np.array( 
     [ 
      [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 
      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 
     ]) 


# Fill holes to make sure we get nice clusters 
filled = sp.ndimage.morphology.binary_fill_holes(data) 

# Now seperate each group of contigous ones into a distinct value 
# This will be an array of values from 1 - num_objects, with zeros 
# outside of any contigous object 
objects, num_objects = sp.ndimage.label(filled) 

# Now return a list of slices around each object 
# (This is effectively the tuple that you wanted) 
object_slices = sp.ndimage.find_objects(objects) 

# Just to illustrate using the object_slices 
for obj_slice in object_slices: 
    print data[obj_slice] 

Este salidas:

[[1]] 
[[1 1 1] 
[1 1 1]] 
[[1 1 1 1] 
[1 0 0 0] 
[1 0 0 1]] 
[[1]] 
[[0 1 1 0] 
[1 0 0 1] 
[0 1 1 0]] 
[[0 0 1 0 0] 
[0 1 1 1 0] 
[1 1 1 1 1] 
[0 1 1 1 0] 
[0 0 1 0 0]] 

Tenga en cuenta que los "object_slices" son básicamente lo que pidió originalmente para, si es necesario los índices del real.

Editar: Sólo quería señalar que a pesar de constar de manejar adecuadamente el caso borde de

[[1 1 1 1] 
[1 0 0 0] 
[1 0 0 1]] 

que en realidad no (lo tanto el extra solitario [[1]]). Esto se puede ver si se imprime la matriz "objetos" y echar un vistazo a los objetos 3 & 4.

[[1 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0] 
[0 0 0 0 0 0 3 3 3 3 0 0 0 2 2 2 0 0 0 0] 
[0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 
[0 0 0 0 0 5 5 0 0 0 0 0 0 0 6 0 0 0 0 0] 
[0 0 0 0 5 5 5 5 0 0 0 0 0 6 6 6 0 0 0 0] 
[0 0 0 0 0 5 5 0 0 0 0 0 6 6 6 6 6 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 0 0 0 0] 
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0]] 

espero que ayude!

[1]

+0

Holy Smokes ¡eso es perfecto! Eso es exactamente lo que quería, y creo que en realidad prefiero manejar el caso extremo de esa manera, de esa manera realmente obtendrá los cuadros para * todos * los píxeles. ¡Ojalá pudiera votar más de una vez! –

+0

@Wayne - ¡Me alegra ayudar! Hay un buen lote de funciones en scipy.ndimage, una vez que aprendes cómo encadenar a los diversos operadores. ¡Buena suerte! –

+0

@JoeKington es uno de los programadores más útiles por ahí – chimpsarehungry

1

Se podría buscar componentes conectados en la imagen y luego determinar los cuadros delimitadores de estos componentes.

+0

Estoy confundido - ¿cómo es esto diferente de lo que dije que estaba haciendo? –

1

Un paquete de agrupación (ie this) debe ser capaz de la mayor parte de la obra (Encontrar píxeles conectados). Encontrar el cuadro delimitador para un clúster es trivial entonces.

+0

¿Cómo ayudaría la agrupación en clúster (especialmente este paquete)? De lo que encuentro leyendo las cadenas de documentos, solo puede encontrar datos que están a una distancia X, y no (parece) almacenar ningún dato X-Y. ¿Me estoy perdiendo de algo? –

Cuestiones relacionadas