lunes, 6 de mayo de 2013

Separación por color II

El siguiente paso en el desarrollo de nuestra aplicación ha sido el estudio y la transformación de las componentes RGB del color obtenido de la cámara a otros espacios de color (HSV, XYZ, YCrCb, Luv, YUV, etc.) para ver si en estos las variaciones de alguna de las coordenadas era determinista para poder diferenciar entre los dos tipos de color en los que se ha enfocado nuestro estudio: oro y cobre.

Los resultados obtenidos eran mejores en unos espacios de color que en otros, pero ninguno ha sido concluyente. A continuación se pasa a explicar brevemente las características principales de los espacios de color más relevantes dentro de todos los utilizados:

HSV


Un color representado en este espacio queda determinado por tres componentes: 
  • H: Hue (Matiz): Representa cada color mediante un ángulo.
  • S: Saturation (Saturación): Representa distancia al eje de brillo negro-blanco.
  • V: Value (Valor): Representa la altura en el eje blanco-negro.
El problema de este espacio con respecto a nuestra aplicación es que los colores oro y cobre están bastante juntos en la circunferencia, aún así podrían ser mucho mas estables y diferenciables que los valores de las componentes RGB. Después de tomar valores de varias monedas, observamos que tampoco cumplía los objetivos.

CIE XYZ


La matriz de transformación del espacio de color RGB a XYZ depende del punto blanco considerado. En nuestro caso se ha tomado como referencia el punto blanco D65, por lo que el respectivo cambio se realiza mediante la siguiente operación:


Este espacio de color se ha utilizado como transformación intermedia del espacio RGB a otros creados por  la Comision Internacional de la Iluminación (CIE), como el que se explica a continuación.

CIE Luv


Las tres componentes que se representan en este espacio de color son las siguientes:
  • L*: Luminosidad del color. Valores altos indican una mayor cercanía al blanco y valores en torno a 0 se corresponden con el color negro.
  • u*: Uniformidad del color.
  • v*: Brillo: Representa la altura en el eje blanco-negro.
Al contrario que los espacios anteriormente descritos, la transformación en este caso no es lineal. Las ecuaciones que definen dicha transformación son las siguientes:


\begin{align}
L^* &= \begin{cases}
  \left(\frac{29}{3}\right)^3 Y / Y_n,&   Y / Y_n \le \left(\frac{6}{29}\right)^3 \\
  116 \left( Y / Y_n \right)^{1/3} - 16,&  Y / Y_n  >   \left(\frac{6}{29}\right)^3      
\end{cases}\\
u^* &= 13 L^*\cdot (u^\prime - u_n^\prime) \\
v^* &= 13 L^*\cdot (v^\prime - v_n^\prime)
\end{align}

donde un y vn se corresponden con las coordenadas del llamado "Punto blanco" y Yn es su luminancia. En este caso se ha tomado como punto blanco: un = 0.2009vn = 0.4610. Además:


La peculiaridad de este espacio de color (y lo que le hace interesante para nuestra aplicación) es que provoca una percepción del color más lineal, es decir, se busca que un cambio de la misma cantidad en un valor de color provoque un cambio de la misma importancia visual.

En este caso, se utilizó la componente u* para intentar diferenciar los colores sin obtener tampoco unos resultados adecuados ya que, aunque obteniendo unos mejores resultados, la separación entre ellos no era lo suficientemente grande como para establecer un umbral determinado.



viernes, 3 de mayo de 2013

Separación por color I

Como se comentó en entradas anteriores, las relaciones de radios entre monedas del mismo color son únicas  y, teóricamente, deterministas. Pero antes de poder desarrollar los algoritmos necesarios para hacer este tipo de diferenciación, es necesario separar dentro de una imagen las monedas de color oro y las de color cobre.

En primer lugar es necesario obtener los colores del centro de las monedas, para obtener unos mejores resultados (colores mas fiables), se ha hecho la media de un cuadrado de 16 píxeles de área. Aunque puede parecer casi trivial en realidad no lo es tanto, el procedimiento a seguir es:
  • Crear un cuadrado con centro el de la elipse; en Opencv los cuadrados se definen a partir del vértice superior izquierdo, por lo que será necesario comprobar que al situar su centro este no se encuentre fuera de la esquina superior izquierda de la pantalla: posiciones inferiores a (1, 1), ya que se obtendría un error de NullPointerException.
  • Lo mismo ocurre al definir la medida de los lados, pero en este caso hay que tener en cuenta el número de filas y de columnas que forman la imagen para que la zona a la que se va a acceder quede totalmente incluida en el área de la pantalla.
  • Finalmente, se obtiene una submatriz de la matriz original (imagen al completo) y se hace la media de las componentes RGB de todos los píxeles.
Una vez se tienen los colores, hay que pensar en un método para distinguir el oro del cobre. Para ello se puede aprovechar el siguiente hecho: el color amarillo es la suma a partes iguales de los colores primarios rojo y verde; y el color cobre tendrá mucha más componente roja. Por lo tanto, para las monedas de oro la relación R/G ~ 1 y para las de cobre R/G > 1.

Una vez implementado, nos dimos cuenta de que en la práctica no se obtienen unos resultados concluyentes, ya que las relaciones que obteníamos eran muy parecidas entre ellas y no había manera de separar las monedas. Después de intentar numerosas relaciones basándonos en la misma idea, se probó utilizando la siguiente fórmula: relación = exp(R / 0.4*G). De esta manera, las variaciones en el exponente se verán reflejadas en una variación aún mayor en la relación.

Aun obteniendo unos mejores resultados, tampoco se obtuvieron unos resultados concluyentes, ya que el umbral de separación entre los colores dependería mucho de la luminosidad del ambiente, por no mencionar los posibles reflejos y sombras de las monedas. Llegados a este punto, se pensó una manera de hacer el color independiente de la luminosidad, es decir, normalizar cada componente dividiendo por el sumatorio de las otras tres y volviendo a multiplicar por 255 para volver a tener valores dentro del intervalo original [0, 255] y poder aplicar la relación explicada anteriormente. Tampoco se obtuvieron buenos resultados.


Figura 1: Espacio de color RGB





martes, 30 de abril de 2013

Problema de dobles contornos

Hay un hecho que había pasado desapercibido hasta el momento, y es la detección de contornos dobles, es decir, para una misma moneda se pintan dos elipses muy parecidas entre ellas. Esto se debe a que a veces se detecta la sombra de la moneda como un contorno y el borde de la moneda en sí como otro. 

Figura 1: Problema de elipses dobles

Para solventar dicho problema, se ha diseñado un algoritmo recursivo que calcula la distancia euclídea entre los centros de todas las monedas presentes en la imagen y, si esta distancia es menor que su radio, la elipse con mayor eje menor se elimina. De esta manera, se elimina el problema de las sombras en algunos casos además del ya comentado.

Figura 2: Problema solucionado

Justificación de la elección final

A continuación se presentan un conjunto de gráficos comparativos entre los distintos métodos probados anteriormente. Para la recogida de los datos utilizados en los gráficos se han utilizado un número total de 10 monedas variadas en tamaño y color, repitiendo cada prueba 50 veces. Por lo que los resultados representados se corresponden a la media de todas las medidas.

Figura 1: Limitaciones.

El porcentaje de las limitaciones que suponen la utilización de un método u otro se han calculado en base a las siguientes condiciones: Si el método necesita de un fondo con un determinado color, se le añade un 50%; Si para el correcto funcionamiento las monedas han de estar en una determinada posición, se añade  otro 50%.

Las limitaciones que presenta la transformada de Hough se deben a que las monedas necesitan estar distribuidas de tal forma que no formen una circunferencia entre ellas (se detectaría una falsa elipse).

Figura 2: Tiempo de ejecución.

El tiempo de ejecución se ha medido en base a lo siguiente: el inicio del contador coincide con el momento en que se recibe un frame de la cámara del dispositivo. Este se detiene cuando la aplicación dibuja en pantalla las elipses correspondientes a las monedas detectadas.

Figura 3: Precisión.

La precisión es el porcentaje de monedas acertadas durante la prueba, se puede observar que ningún método es perfecto, ya que siempre hay algún frame en el que no todas son detectadas.

Conclusiones:

El primer factor eliminatorio es la precisión, ya que para nuestro proyecto no es aceptable un porcentaje de detección inferior al 70%, este hecho descarta cuatro de los métodos analizados.

La decisión final entre los métodos restantes se tomó en base a las limitaciones que presentaban, ya que el método Canny no presentaba ninguna de las anteriormente comentadas además de no suponer una diferencia demasiado grande en cuanto a precisión respecto al Otsu. Además, el tiempo de ejecución tampoco es un factor decisivo (como se ha comentado en entradas anteriores).




domingo, 28 de abril de 2013

Detección por contornos: Solución final


Como se comentó en entradas anteriores, nuestro objetivo era detectar las siluetas de las monedas combinando el reconocimiento por color y el procesado Canny. Sin embargo, y tras varias pruebas, hemos realizado un algoritmo de detección basado únicamente en el procesado Canny y otros procedimientos que se detallarán más adelante. De este modo, se evitan las complicaciones asociadas al color (brillos, sombras y zonas de colores similares que provocan detecciones falsas).

Tras el pre-procesado de la imagen, se le aplica el algoritmo Canny para obtener una imagen binaria con los contornos definidos, que se almacenan en una lista de puntos. La imagen en este momento tiene el siguiente aspecto:

Figura 1: Contornos detectados.

Como se puede observar en la imagen, aparecen muchos contornos que no tienen que ver con las monedas en sí, por lo que se hace imprescindible aplicar una serie de condiciones a todos los contornos de la imagen para que puedan pasar a formar parte de la lista de contornos definitivos. Dichas condiciones se detallan a continuación:

- Si el contorno está formado por un número reducido de puntos, se elimina de la lista. Con esta condición se quitaran de la imagen todos los contornos pequeños.

- Se dibuja una elipse que contenga a los puntos, si el eje mayor o el menor son mayores que un número grande de puntos, se elimina el contorno asociado a la elipse. Esta condición permite eliminar elipses que se salgan del plano de la cámara, ya que no serán monedas sino detecciones falsas debido a los contornos.

- Si la relación axial (eje mayor/eje menor) de la elipse es menor o mayor que unos determinados umbrales, se elimina. Esto se debe a que normalmente las monedas tendrán una relación axial cercana a la unidad que se correspondería con una circunferencia, y por mucho que se incline la cámara dicha relación no superará nunca los umbrales mencionados.

- Finalmente, se dibuja el contorno (en blanco) sobre una imagen con fondo azul y la elipse asociada al mismo (en blanco) sobre una imagen con fondo negro. Se comparan las dos imágenes con el operador lógico AND, que devolverá una matriz con los puntos que coinciden entre la elipse y su contorno. Si el número de puntos coincidentes es menor que un umbral, es porque en realidad no se trataba de una moneda, sino una falsa detección.

La imagen resultante es la que se muestra a continuación: 

Figura 2: Imagen resultante RGB


Notas:

• Los números y umbrales comentados anteriormente se han calculado a partir de numerosas pruebas experimentales. 

• El algoritmo Canny, requiere dos umbrales (superior e inferior), que se fueron modificando mediante dos "seekbar" introducidas en la aplicación con este propósito y a través de las cuales se pudo concretar cuáles eran sus valores óptimos. En las siguientes imágenes se muestran tres ejemplos con distintos umbrales:

Figura 3: Imagen con demasiados contornos

Figura 4: Imagen con los umbrales seleccionados

Figura 5: El contorno de una moneda se pierde

Hay que tener en cuenta que las condiciones anteriores se aplican sobre cada contorno de la imagen, por lo que cuantos más contornos aparezcan en ella, mayor será el tiempo necesario para procesar la imagen. Por lo tanto, se tuvo que hacer también un balance entre tiempo de procesado y precisión del detector para identificar el valor de los umbrales.

Para ilustrar este hecho, se han representado en el siguiente gráfico el número de contornos obtenidos de una imagen con tres monedas sobre fondo blanco frente al tiempo de ejecución (se ha desarrollado así para mantener lo más constantes posibles el resto de las variables que influyen en la detección de los contornos y, por lo tanto, en el tiempo de ejecución).

Figura 6: Comparativa de tiempos

Se puede ver que el tiempo de ejecución aumenta exponencialmente con el número de contornos detectados en la imagen, por lo que se hace necesario elegir unos umbrales que generen el mínimo número de contornos posible sin perder los contornos necesarios para identificar a las monedas.

Detección por contornos: Pruebas intermedias


Alguna de las principales tareas que estamos llevando a cabo para nuestro proyecto están siendo la investigación y numerosas pruebas en el campo de la visión artificial, por lo que en esta entrada nos dedicaremos a enumerar los distintos métodos empleados para intentar realizar una detección correcta de las siluetas de las monedas antes de llegar a la solución final:


1) Detección sobre una imagen en blanco y negro:

Este método trata de transformar una imagen en escala de grises a blanco y negro, la idea era mantener con color negro únicamente las monedas y el resto de la imagen en blanco para así poder calcular los contornos con mayor facilidad.

Para su implementación es necesario establecer un umbral, se analizará la imagen pixel por pixel y en función de su color (si supera o no el umbral definido) se sobrescribirá cada pixel con un valor binario (blanco o negro). En este caso, el fondo sobre el que se encuentren las monedas es de vital importancia para su correcta detección. Se decidió colocarlas sobre un fondo blanco y establecer un umbral bastante alto, de esta manera el fondo se quedaría como está (blanco) y la moneda pasaría a ser mayormente negra (descartando los brillos que, obviamente aparecerían blancos).

Una vez implementado, se hicieron pruebas y aparecieron varios problemas: los contornos que se detectaban incluían las sombras que pudieran tener las monedas, por lo que la medida de los ejes para la identificación por tamaños sería una medida falsa. Además al cambiar a otro ambiente con distinto nivel de luz, el umbral dejaba de ser válido y era necesario ajustarlo manualmente. La idea para evitar este último problema era utilizar de alguna manera un umbral dinámico, el método de Otsu. 


2) Detección mediante el método de Otsu:

Dicho método convierte una imagen en grises a blanco y negro calculando el umbral óptimo en cada momento a partir del histograma de la misma. De esta manera, se obtiene un umbral dinámico válido para cualquier situación de luminosidad. Sin embargo, seguía apareciendo el problema de la detección de sombras con otra complicación añadida, como el método calcula el histograma de la imagen, no puede haber en toda la imagen algún objeto oscuro, ya que esto provocaría un descenso del umbral y por lo tanto los pixeles correspondientes a las monedas se tomarían como blancos y la detección sería errónea.

Para evitar la complicación de las sombras, se optó por cambiar el fondo de la imagen a negro, de manera que las monedas quedarían como superficies blancas y las sombras pasarían a formar parte del fondo. Finalmente, se invertiría el valor de cada pixel de la imagen para volver a la situación anterior (monedas negras y fondo blanco).

Figura 1: Imagen binaria mediante el método Otsu

  Figura 2: Imagen RGB resultante



Esta última modificación hizo que la detección fuera lo suficientemente buena para el clasificador por tamaños, pero estaba limitada a tener un fondo oscuro, por lo que se probaron otros métodos para poder hacer la detección independiente del fondo.


3) La transformada de Hough:

Este método se tuvo que implementar enteramente en C++ incluyendo el código en la carpeta jni del proyecto debido a que las librerías OpenCv para Java no incluían los métodos necesarios para su desarrollo.  

Este método se propuso inicialmente para detectar líneas rectas, pero con el paso del tiempo se ha utilizado para la detección de todo tipo de figuras geométricas siempre que sus ecuaciones se puedan describir con unos cuantos parámetros. En nuestro caso se empezó con la detección de círculos por su mayor simplicidad, pudiendo después extrapolarlo a elipses si los resultados obtenidos eran buenos. Los parámetros a tener en cuenta en este caso son tres: la posición del centro de la circunferencia (valores x e y) y el tamaño del radio, que son los parámetros que se utilizarán para su representación y para hacer la clasificación. 
Con este método evitaríamos además la necesidad de estar obligados a disponer de un fondo de un determinado tono.

Figura 3: Transformada de Hough


Figura 4: Problema de no-detección.


Una vez implementado, se hizo evidente el primer problema,  el método requiere un cálculo computacional demasiado grande como para poder hacerlo a tiempo real en un dispositivo móvil. Aun así esto no supondría un problema, ya que se podrían hacer dos hebras en la aplicación: una en la que solo se mostraran las imágenes captadas y otra que sería la encargada de coger unos cuantos frames del flujo continuo de vídeo y hacer los cálculos sobre ellos, siendo este comportamiento totalmente transparente al usuario.

Tras varias pruebas e intentos de mejora descartamos la implementación del método para elipses, ya que aunque las detecciones que hacía eran muy precisas, un gran número de las monedas presentes en la imagen no eran detectadas y en ocasiones aparecían falsas monedas.

Nota: En todos los métodos anteriores es necesario incluir un pre-procesado de la imagen como por ejemplo un filtro gaussiano para eliminar ruido o una normalización de la escala de grises (de 0 a 255).

jueves, 21 de marzo de 2013

Próximos pasos: Implementación.


Una vez diseñados los algoritmos de detección y reconocimiento, vamos a proceder a su implementación. A pesar de que por separado, hemos probado ya gran parte de las funcionalidades que componen dicho algoritmo, no queremos retrasarnos mucho en la implementación completa, ya que somos conscientes de que por el camino van a aparecer numerosas dificultades que van a complicar nuestro proyecto.

Ya hemos probado la detección de contornos por color, y el procesado Canny, de tal manera que nuestro próximo paso será establecer el pegamento de unión entre los dos procesados. En concreto, nuestro próximo paso es, una vez obtenida la matriz blanco y negro de los contornos tras el procesado Canny, detectar en ella siluetas elípticas, para poder posteriormente analizar los colores en su interior e introducir dichos parámetros dinámicamente en el detector por colores.