lunes, 18 de febrero de 2013

[VC] Tarea 2: Detección de formas

Para esta entrada el objetivo fue programar las rutinas necesarias para la detección de formas en una imagen.
Con lo que hicimos en la tarea 1, detección de bordes utilizando máscaras de Prewitt y aplicación de umbrales para un mejor resultado:


ahora vamos a detectar los objetos que quedan encerrados dentro de los contornos resaltados en color blanco, para ello probaremos con las siguientes imágenes:


Imágenes originales

Para comenzar necesitamos binarizar las imágenes con la técnica de convolución que ya vimos.
Después de aplicar máscaras y umbrales tendremos algo como ésto:

Imágenes binarizadas

Ahora a detectar los objetos, es un procedimiento sencillo y complejo a la vez:

  • Creamos una matriz de pixeles visitados del mismo tamaño que la imagen (alto x ancho)
  • Creamos una lista para guardar la información de los objetos que encontremos y un contador que servirá para poner un ID a cada objeto.
  • Ahora comenzamos a recorrer todos los pixeles de la imagen.
  • Verificamos cada pixel en el que nos posicionamos en la matriz de pixeles visitados, si no esta marcado como visitado (visitado[x][y] = False) y el color del pixel es negro entonces marcamos ese pixel como el origen de nuestra búsqueda (los pixeles negros pertenecen a objetos, los blancos a bordes).
  • Generamos un color aleatorio
  • Aplicamos búsqueda en anchura BFS en el pixel que marcamos como origen para pintar con el color generado los pixeles que nos lance la búsqueda en anchura.
  • BFS nos regresará la lista de pixeles que fueron visitados, dichos pixeles nos sirven para calcular también la masa del objeto y buscar su centro. Además nos regresa la lista de pixeles pintados de la imágen.
  • Calculamos sus propiedades: 
    • tamaño del objeto a partir del largo de la lista de pixeles visitados
    • su porcentaje con una regla de tres simple utilizando el tamaño del objeto y a cantidad total de pixeles en la imágen.
  • Tomamos las coordenadas de la lista de pixeles visitados y realizamos 2 sumas, en una sumamos los valores de las coordenadas x y en la otra suma los valores de las coordenadas y, después dividimos la sumatoria entre la cantidad de valores sumados. Este par de resultados son las coordenadas del centro de masa del objeto.
  • Tomamos las propiedades y armamos un objeto en forma de diccionario, ahí empaquetamos toda la información.
  • Por cada objeto creado incrementamos el contador de los IDs
  • Repetimos hasta que todos los pixeles hayan sido visitados.
  • Después, de la lista de objetos tomamos aquel de mayor tamaño, supondremos que el objeto de mayor tamaño es el fondo de la imágen por ahora. Pintamos los pixeles que pertenecen a ese objeto de color gris.
  • Ahora solo nos queda recorrer la lista de objetos obteniendo las propiedades de cada uno, mas precisamente, las coordenadas de su centro. En esas coordenadas dibujamos un punto negro y colocamos una etiqueta con el ID del objeto al que pertenece.
  • Mientras en terminal imprimimos sus propiedades para que podamos relacionarlas.


La rutina BFS esta basada en el algoritmo visto en clase.

Los objetos identificados se colorean y se ven así:

Objetos identificados con centro de masa

Podemos ver el centro de masa marcado con un punto negro.


Por último los etiquetamos.

Objetos identificados con centro de masa

Mientras en la terminal vemos la información recolectada de cada objeto, su tamaño en pixeles y porcentaje.



Y así termina la entrada, en el repositorio encuentran la implementación completa en código, la carpeta marcada como Tarea 2.

Código:

Clasificación de objetos parte 1, que hace el trabajo en la interfaz gráfica

Clasificación de objetos parte 2, encargada de la parte lógica

Interfaz


La interfaz permanece sin cambios, al menú Machine vision se agregaron las opciones:

  • Convex hull: Envoltura de objetos, aún sin funcionalidad
  • Object Detection: Detección de un objeto individual
  • Object Classification: Detección de todos los objetos en una imágen

Como agregado hice una rutina llamada objectDetection cuyo objetivo es detectar una sola figura dada las coordenadas de origen.
Coloque un listener en el canvas para guardar las coordenadas donde se da clic, después la rutina toma esas coordenadas como inicio para detectar ese objeto utilizando BFS. No etiqueta ni marca centros de masa, pero es una buena práctica para simular el rellenado de figuras que vemos en programas de dibujo. Las coordenadas seleccionadas se muestran en terminal, la figura se rellena de color azul sólido



Citar el blog de Emmanuel García donde me apoye para optimizar el algoritmo de búsqueda de centros de masa.


1 comentario: