lunes, 4 de marzo de 2013

Tarea 4: Detección de Círculos (Radios Conocidos)

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

Usando principios similares a la detección de línea, ahora lo que se debe de detectar son círculos. 

Para este post que corresponde a la materia, se utilizarán círculos con el mismo radio, el cuál será conocido. Para medir el radio (en pixeles) se utiliza cualquier herramienta de dibujo como GIMP o Paint.

Recordando anteriormente, para la detección de líneas buscábamos pares $(\rho, \theta)$ para cada pixel a partir de sus gradientes horizontal y vertical, y después se hacía un histograma con las frecuencias y se quedaban los que tenían más "votos".

En el caso de los círculos, buscaremos pares $(x_{c}, y_{c})$ que representan los posibles centros de círculos.

Para calcularlos, igualmente en base a los gradientes horizontal ($g_{x}$) y vertical ($g_{y}$) se hace lo siguiente:
Se calcula la magnitud $g$ usando la fórmula:

$g = \sqrt{gx^{2} + gy^{2}}$

Con esto se calcula:
$\cos \theta = {g_{x}}/{g}$
$\sin \theta = {g_{y}}/{g}$

Teniendo $\cos \theta$ y $\sin \theta$, calculamos $x_{c}$ y $y_{c}$:

$x_{c} = x - r \cos \theta$
$y_{c} = y - r \sin \theta$

Donde $r$ es el radio designado como parámetro.

Calculando estos pares, se hará un histograma de frecuencias para cada par, contando cuantos hay. Después, solo se dejarán los más significativos, que corresponden a posibles centros para muchos puntos.

Teniendo ya los posibles centros localizados, se solicitó localizar lo siguiente:
  • Marcar los contornos de los círculos detectados de color amarillo.
    • Si hay más de un círculo, el tono debe ser diferente para cada uno.
  • El centro del círculo, se marca con un punto de color verde.
  • Al centro de cada círculo se coloca una etiqueta con un ID para cada círculo.
Para marcar los contornos de los círculos, hago uso de ImageDraw de la librería PIL y su función draw.ellipse, ya que teniendo localizados los centros, y teniendo el radio, podemos trazar círculos alrededor de ese punto con un radio determinado. 

Para los diferentes tonos de amarillo, simplemente se obtiene un color $Amarillo = (var, var, 0)$, donde var es un número del 100 al 255, que varía para dar diferentes tonos de amarillo (más cercano a 0 más oscuro, más cercano a 255 más brillante).

Para pintar los centros basta con simplemente pintar cada pixel de centro localizado de color verde, es decir $(0, 255, 0)$.

Y finalmente para colocar el ID, de nuevo se usa ImageDraw para colocar un texto con un número asignado al círculo, usando draw.text en las coordenadas del centro.

Ejemplos


Los círculos se dibujaron en Paint, por lo cual no son perfectos. El radio usado para localizarlos es 40. La cantidad de círculos localizados es la correcta, sin embargo, la localización del centro y el contorno parece ser incorrecta, pero es debido al mismo problema de que no son círculos perfectos.



En este ejemplo se localizan correctamente los círculos y se agregan dos círculos fantasmas más. Gracias a éste ejemplo me di cuenta que cuando los círculos que se buscan están a una distancia R (radio) cercanos, se crea un círculo fantasma entre los círculos reales cercanos (lo cual es el caso del círculo 3, que se forma debido a que tiene puntos alrededor que corresponderían a la circunferencia de los círculos 1 y 5, y lo mismo para el cŕculo 4, con vecinos 2 y 6.


En cambio cuando los círculos están pegados uno al otro, no se localizan círculos fantasmas, aunque aquí aparecen ligeramente alejados de donde se encuentra el centro exactamente, pero la cantidad de círculos es correcta, y la localización es bastante aceptable.

Código


1 comentario:

  1. Faltó lo de imprimir el listado con los tamaños, pero el resto está suficientemente bien para ponerte los 5 puntos completos.

    ResponderEliminar