martes, 5 de marzo de 2013

Laboratorio 5: Detección de Círculos (Radios Desconocidos)

Link al repositorio: https://github.com/synnick/viscomp


Ésta semana se trabajo con la detección de círculos con radios comunes (que suele ser la forma más común utilizada en visión computacional. Para laboratorio, se pidió realizar una detección de círculos con diferentes tamaños, es decir radios diferentes.

El principio es el mismo que anteriormente. Antes teníamos una matriz bidimensional con pares de coordenadas $(x_{c}, y_{c})$ a los cuales se realizaba un histograma para saber cuantos pixeles votan por cada par. Ahora, esta matriz será tridimensional, teniendo una matriz como la mencionada para cada diferente radio que estemos probando. 

Esto podemos imaginarlo como buscar partes de un cono en la imagen, partiendo desde la punta que sería un círculo con radio pequeño, y aumentando el radio progresivamente hasta un cierto punto.

Para cada radio diferente, existiría una matriz con los puntos  $(x_{c}, y_{c})$. Entonces deberíamos de quedarnos en cada iteración de cada radio, con los centros que tengan una mayor cantidad de votos, procurando además que los pixeles que no sean bordes (los bordes se localizan previamente con gradientes) no puedan votar.

Probando lo anterior, agregando simplemente al programa de radios comunes, funciona de la siguiente manera:

Los 3 círculos se detectan correctamente pero además de ellos aparece demasiado ruido, detectando círculos de múltiples radios dentro y fuera de los círculos originales. Lo siguiente sería eliminar los círculos con radio al cual no pertenece.

Para realizar esto, podemos trazar dos líneas a través del centro, marcando dos diámetros perpendiculares vertical y horizontal. Estas líneas serían de tamaño aproximado al diámetro del círculo actual (2 veces el radio para el cual se están buscando círculos) agregando un pequeño umbral en caso de que el círculo se detecte un poco movido.

Haciendo esto, se puede verificar que ambos diámetros horizontales y verticales estén en contacto con el círculo 2 veces, es decir, determinaríamos si dicho punto es un círculo de un radio determinado sí:


Para poder aplicar éste método ES NECESARIO contar con una buena detección de bordes, debido a que se van a utilizar valores de los bordes para poder determinar si el círculo es válido o no. Una buena detección de bordes para la imagen anterior sería:

                                           Usando

Con estos bordes, verificamos que trazando "líneas" imaginarias de tamaño r + umbral (umbral siendo una cantidad de tolerancia de separación que puede haber entre el radio y el borde) dichas líneas hagan contacto con los bordes. Cambiando los umbrales es posible disminuir la cantidad de ruido, eliminando círculos que no pertenecen a ningún borde encontrado:

Umbral 30                                        Umbral 20                                                           Umbral 5


(Nota: El avance en los radios se hace en pasos de 5 en 5 para acelerar el proceso)

La detección correcta depende de dos cosas entonces, el paso (cambio) en el radio y el umbral.

Si el paso es de 1 en 1 y $umbral >= 2$, es probable que se detecten diferentes círculos de diferentes radios alrededor de un centro. Por eso sería necesario ajustar los valores dependiendo de la aplicación para la cual se use.

Ahora ya tenemos listo el detector de círculos de diferentes radios.

Igual que en la detección de círculos con radios conocidos, se nos pidió hacer lo siguiente:
  • Marcar los círculos con tonos de amarillo fuerte.
    • Marcar cada círculo de un tono de amarillo diferente.
  • Marcar el centro del círculo con un punto verde.
  • Agregar una etiqueta con el ID del círculo.
  • Imprimir un listado con ID's y diámetros de cada círculo (como porcentaje de la diagonal máxima de la imagen)
La forma de realizar todos los puntos excepto el último están explicadas en el post de detección de círculos con radios conocidos.

Para obtener la diagonal máxima de la imagen, simplemente se puede obtener la distancia desde una esquina, a su contraria usando la fórmula:

$D = \sqrt{ {(x_2 - x_1)}^2 + {(y_2 - y_1)}^2 }$

Con la fórmula obtenemos la distancia desde un punto hasta otro, siendo en nuestro caso en términos de pixeles y siendo los puntos dos esquinas contrarias, por ejemplo la esquina inferior izquierda y la esquina superior derecha.

Ejemplos:




Código

El código siguiente, no funciona para todas las imágenes con círculos pero se comporta correctamente en pruebas hechas en cualquier editor de imágenes con círculos exactos.
Para pruebas rápidas lo mejor es editar el rango del último for con los radios aproximados que sabemos que se tiene, si se colocan rangos puede tardar demasiado, aunque lo peor que puede pasar es detectar múltiples círculos de radios similares en donde hay uno.




1 comentario: