Tengamos una imagen (escala de grises o incluso binaria) como se muestra en la siguiente figura en el lado izquierdo, el objetivo es generar una lista de puntos, es decir, coordenadas en forma de (x, y) para cada paquete del píxeles oscuros en la imagen.
¿Cuáles son las herramientas de procesamiento de imágenes adecuadas para hacer esto y dónde están disponibles?
Actualizaciones:
1)
Aquí puede encontrar más detalles sobre el problema. (Tenga en cuenta la variación en el tamaño de los paquetes)
Puedo sugerir que se detecten paquetes para calcular el límite del casco convexo para cada uno y luego encontrar el centroide representativo {ver esto para más detalles} .
2)
Aquí está el resultado producido por la aplicación de la Transformación de Distancia (sugerido por "Libor"). Tenga en cuenta mis anotaciones en la figura. ¡El método no funciona como era prometedor!
3) ¡
La erosión elimina los paquetes pequeños!
from __future__ import division
from scipy import zeros, ndimage as dsp
from pylab import subplot,plot,matshow,show
img = zeros((30,30))
img[10:14,10:14] = 1
img[16:17,16:17] = 1
img[19:23,19] = 1
img[19,19:23] = 1
subplot(221)
matshow(img,0)
subplot(222)
y = dsp.binary_erosion(img,[[1,1],[1,1]])
matshow(y,0)
subplot(223)
y = dsp.binary_erosion(img,[[0,1,0],[1,1,1],[0,1,0]])
matshow(y,0)
subplot(224)
y = dsp.binary_erosion(img,[[1,1,1],[1,1,1],[1,1,1]])
matshow(y,0)
show()
4)
Bueno, aquí hay una implementación de Python (es decir, el lenguaje del amor :)) de la idea de etiquetado (también propuesta por "Jean-Yves" a continuación):
subplot(221)
l,n = dsp.label(img)
sl = dsp.find_objects(l)
for s in sl:
x = (s[1].start+s[1].stop-1)/2
y = (s[0].start+s[0].stop-1)/2
plot(x,y,'wo')
y el resultado:
Tenga en cuenta que, aunque se realiza en Python tan rápido debido al rendimiento de Scipy, el procedimiento en segundo plano en label
función debería ser una iteración agotadora. Esto puede considerarse como una compensación. Así que por un tiempo sigo ansioso por buscar algoritmos más eficientes. Y también tenga en cuenta que en el código dado anteriormente encontré el centro de la geometría de manera tan simple, mientras que para formas complejas o asimétricas esto puede hacer que el posicionamiento sea sesgado. Es decir, es un trabajo en progreso;).
5)
Aquí hay un caso complejo (una imagen real) capturado desde aquí en el que se aplicó la propuesta de etiquetado y verá los resultados. Tenga en cuenta que solo tomó 0.015 s para todo el procedimiento, incluido el etiquetado y la búsqueda de los objetos. Chicos astutos , creo que hicieron un muy buen trabajo. ¡Guauu! {haga clic derecho en la imagen, haga clic en ver imagen para resolución completa}
fuente
Respuestas:
Solo una sugerencia ingenua: ¿sabes sobre el etiquetado de componentes ?
La técnica consiste en encontrar trozos de píxeles "en contacto" y asignarles una etiqueta, por ejemplo , un número entero. Luego puede interrogar cada grieta por separado, buscando el píxel que comparte la misma etiqueta.
En MATLAB, aquí está la función que lo hace trivialmente: bwlabel
fuente
También puede ejecutar una transformación de distancia en la imagen, luego detectar máximos locales (buscando píxeles con el valor más alto / más bajo de todos los píxeles en un parche de 3x3 píxeles; puede ser mayor dependiendo de la distancia mínima esperada entre los blobs originales).
Tenga en cuenta que para detectar características de tamaño de 1 a 3 píxeles, debe duplicar su frecuencia de muestreo (aumentar la imagen de origen o realizar una transformación / erosión de distancia con precisión de subpíxel).
ACTUALIZAR:
Los enfoques de transformación de distancia y erosión suponen que las características que está detectando son convexas. Algo con forma de U, por ejemplo, puede disparar en su detector varias veces.
Un método más elaborado para dicha segmentación se basa en conjuntos de niveles y contornos activos . Comienza con una gran curva cerrada que se adapta iterativamente a sus características. Este método se ha utilizado en mi universidad para contar células y detectar cromosomas en imágenes de microscopio.
fuente
Una opción sería aplicar erosión morfológica repetida a la imagen hasta que esté completamente erosionada. En ese punto, cada uno de los blobs que se muestran arriba se reduciría a un solo píxel; podría tomar las ubicaciones de esos píxeles como la lista de puntos que está buscando.
fuente
Me temo que, sea cual sea la forma en que elija hacer esto, no será sencillo porque para asignar los objetivos a los grupos, tendrá que pasar por la imagen (al menos una vez).
Supongo que obtener los puntos es el problema más fácil de los dos (probablemente ya esté aplicando alguna forma de umbral, por ejemplo).
Para recuperar los grupos en los que se agrupan los puntos y hacerlo rápido, puede crear una estructura de cuatro árboles que contenga "cadenas de píxeles conectados" que se encuentren alrededor del área de la celda de cuatro árboles.
De esta manera, podría recorrer la imagen y, una vez que se encuentre con un píxel que es un objetivo, "empujarlo" en su estructura de árbol cuádruple.
Esta operación "push" comenzaría un proceso iterativo que devolvería la celda (en otras palabras, el área específica de la imagen) donde se encuentra el píxel en particular. Luego, puede iterar a través de todas las cadenas de píxeles que están asignadas a esa celda e intentar para "empujar" (nuevamente) el píxel a la cadena de píxeles. Una cadena de píxeles acepta un nuevo píxel si está al menos 1 píxel cerca de cualquiera de sus píxeles ya asignados. Si ninguna cadena de píxeles "acepta" el nuevo píxel, cree una nueva cadena de píxeles en esta celda y asígnele el nuevo píxel.
El quad-tree aquí es una forma de limitar su búsqueda de la cadena de píxeles más cercana y sería necesario si su imagen es grande y los objetivos numerosos para que las operaciones de empuje de la cadena de píxeles se realicen rápidamente. Si sabe que no va a tratar con una gran cantidad de objetivos, incluso podría saltarse el árbol cuádruple y mantener una simple "lista de cadenas de píxeles". Cada vez que te encuentras con un "objetivo", puedes recorrer las listas e intentar "empujar" el píxel sobre ellas. Si ninguna lista "admite" el píxel, cree una nueva lista y asígnele el píxel.
De cualquier forma que elija hacerlo, al final de este proceso tendrá un conjunto de "cadenas de píxeles" conectadas (sus grupos) que luego puede pasar a otra parte de su programa que se encargará de estimar sus ubicación. Puede ser casco convexo, ajuste de modelo (por ejemplo, elipsoide u otro) o simplemente la media / mediana de las coordenadas x, y.
Espero que esto ayude.
fuente