Desarrollo de la Solución

Armado del ambiente

A continuación se describe el ambiente utilizado para desarrollar.
Para desarrollar en Android, el ambiente utilizado fue el propuesto por la documentación que se presenta en este tutorial. Para armar el proyecto ChessTrack como una aplicación para Android se utilizaron los tutoriales que presenta Opencv4Android en su documentación. Debido a que el emulador para Android es sumamente lento en lo que respecta a su ejecución, y debuggear sobre un dispositivo es una tarea engorrosa, se decidió realizar las pruebas de conceptos en Matlab con OpenCV, valiéndose del kit de funciones mex de opencv para matlab obtenidas de mexopencv. Una vez validadas las funcionalidades se realizaron pruebas sobre dispositivos con Android. También se hicieron algunas pruebas conceptuales en C/C++ utilizando la librería OpenCV dado que es más cómodo migrar luego el código programado al lenguaje Java.

A modo de versionar el trabajo realizado, desde el desarrollo de la actividad para Android, las pruebas de conceptos y el contenido y análisis de las mismas, se generó un repositorio con soporte institucional.





Pruebas desde matlab y desde C/C++

A continuación se describen las pruebas desarrolladas en matlab y C/C++.
Sobre Matlab y código en C++ se armaron pruebas de concepto de las ideas que iban surgiendo para varios aspectos del procesamiento.

Para la detección del tablero se pensó en una detección de esquinas

Detección de esquinas con la función corners desde matlab:

   

Detección de esquinas con la función corners desde C++ con OpenCV:

   

Nos decidimos por utilizar la función findChessboardCorners que se utiliza para calibrar con tableros de ajedrez y retorna cuando encuentra un tablero interno de determinado tamaño, en este caso 7x7:

Más Pruebas desde matlab y desde C/C++

Para la detección de la mano se utilizó la estructura de OpenCV BackgroundSubtractorMOG obteniendo luego la cantidad de píxeles que se diferencian del fondo, y seteando un umbral para determinar cuando hay una mano sobre el tablero y descartar esos frames, un ejemplo en C++ ejecutado sobre un video que realizamos:

A la izquierda se visualiza un video con la máscara, y a la derecha el video etiquetado con los estados: ESTABLE y MANO para diferenciar cuando descartar frames

             

A continuación se muestran los tableros obtenidos en la transición de estado MANO a estado ESTABLE.



Descripción general de módulos

En esta sección se describen brevemente los módulos y sus actividades principales.

  • Modulo

    Activity

    Este módulo es la actividad Android que se encarga de recibir los eventos de la aplicación, en esta primera versión se cuenta con un menú con opciones de conexión y de calibración, mantiene una máquina de estados para modelar si se está en estado Calibrando o Jugando.

    Cuando se selecciona del menú la conexión se ingresan los datos necesarios (a saber ip y puerto del servidor) y luego es el módulo Manager el encargado de mantener la misma.

    Es en este módulo donde se reciben los frames de la cámara, y es el encargado de pasarlos al Manager a partir de que se selecciona la opción calibrar.

  • Modulo

    Manager

    Este módulo se encarga de manejar los estados de la aplicación. Comienza a tomar partido desde el evento calibrar, y es quien se comunica con el resto de los módulos que procesan los frames y también con el módulo que se comunica con el servidor para enviar las partidas.

    Luego de la calibración válida este módulo se encuentra en el estado Armando Tablero, y cuando le notifican que está pronto el tablero para iniciar la partida, se pasa a estado Jugando.

    Mantiene una bandera para saber si se debe enviar información al servidor, o no se ha seleccionado salida alguna.


  • Modulo de

    Adquisición

    En este módulo se emplean técnicas para el acondicionamiento de la imagen. Se cuenta con la clase Adquisición que dentro posee una lista de clases que implementan la interface ImgProcInterface. Dicha interfaz solo posee el método procesarImagen, que es llamado por el módulo Adquisición para cada una de las clases que se agregaron a la lista.

    La idea detrás de este módulo es que el frame adquirido pase por una serie de acondicionamientos, cada uno siendo una clase que implementa la interface ImgProcInterface y agregándose a la lista en Adquisición. Se ejecutarán en el orden en que son agregadas.

  • Modulo de

    Calibración

    Este módulo es el encargado de calibrar el sistema antes de empezar la partida. Se encarga de localizar el tablero, obteniendo las esquinas internas y calculando la arista promedio del tablero interno.

    Para la localización de las esquinas se utiliza como ya se mencionó la función de OpenCV findChessboardCorners.

    Para que los usuarios sepan si pueden comenzar a armar el tablero se emite un beep, en caso de que no se hayan encontrado las esquinas se emiten dos beep y se deberá ajustar el dispositivo para lograr que la cámara visualice la totalidad del tablero.



  • Modulo

    Oclusión

    Se encarga de detectar si la imagen obtenida se encuentra estable para ser procesada o si por el contrario un jugador está realizando un movimiento, por lo cual no debe procesarse el tablero.

    Para la detección de la oclusión, es decir, que hay una mano realizando una movida, se utiliza la estructura BackgroundSubtractorMOG.

    Internamente este módulo mantiene estados. Oclusión: es cuando hay un jugador realizando una jugada; Transición: al cual se pasa inmediatamente se ha dejado de visualizar la mano; Enviar Tablero: donde se valida que es un tablero limpio para detectar fichas. La existencia del estado Transición se realiza para asegurar un tablero completamente libre de sombras.

  • Modulo

    Modelador

    Este módulo es el encargado de a partir de una imagen obtener información de cada escaque reconociendo si existe una ficha o no en el mismo.

    Para la detección de piezas se utiliza una detección utilizando sobel sobre la región céntrica del escaque, y se aplica un umbral para determinar la existencia de una pieza.

    La detección de piezas es empleada durante el armado, para saber si se ha llegado a la configuración inicial del tablero, y también se utiliza para detectar las piezas en un tablero válido (sin oclusión).





  • Modulo

    Lógica

    Este módulo contiene la lógica de las reglas de Ajedrez y se encarga de procesar las matrices de Modelador para saber qué fichas se movieron y a donde y generar algún tipo salida para que sea procesada por el modulo Comunicacion. Actualmente se encarga de validar los tableros para saber cuando se hizo un movimiento de piezas.

  • Modulo

    Comunicación

    En este módulo debería de estar implementado todas las posibles salidas que se quiere obtener de la partida, quizás a partir de una interfaz que recibe el movimiento y se implementa un tipo de salida (persistencia en archivo, enviar a un servidor, texto a voz,etc). Por temas de tiempo en este módulo sólo se implementó una clase que se encarga de enviar la matriz de las fichas a un servidor conocido.

Técnicas empleadas

A continuación se describen las tecnicas empleadas.
Primeramente se emplea, para la calibración, una detección de esquinas usando el metodo XXXchescorners. De esta manera se obtienen las esquinas interiores del tablero de ajedrez. Con las esquinas detectadas se calcula una homografía para enderezar el tablero, recortarlo para solo tener el tablero en la imagen para procesar y colocarlo en una posición conocida. Con este proceso también se obtiene el tamaño de los escaques y de todo el tablero.

Luego de acondicionar la imagen se utiliza un proceso de supresión de fondo para detectar cuando se esta haciendo el movimiento de las fichas, para esto se utiliza los métodos DDDDDDD de la librería OpenCV.

Para la detección de fichas se obtienen de cada frame la sub imagen correspondiente al área central de cada escaque, se le hace un filtro de Sobel para la detección de bordes, a su vez se binariza una imagen a partir de cierto umbral. Luego para eliminar ruido se hace un erode, y un dilate para acrecentar los pixeled donde hay fichas. Si la cantidad de pixeles blancos pasan cierto umbral se puede decir que se encuentra una ficha en el escaque.






Para el envío de la partida a un servidor externo, como ya se comento, solamente se envía un tablero con unos y ceros, los cuales representan el tablero y las fichas. Dicho servidor es dedicado a esta aplicación y se encuentra dentro del repositorio del proyecto. Para usarlo se debe de levantar el mismo en un pc con java, y luego antes de calibrar, configurar la ip y el puerto (actualmente es el 5556) en la aplicación.

Igualmente la aplicación permite una jugabilidad importante (siempre dentro de partidas lentas), luego de calibrar, la misma aplicación detecta cuando esta todo el tablero armado y emite un pitido, de ahi en mas, espera a que se hagan movimientos y detecta cambios de fichas.

Es importante tener en cuenta cómo se debe de armar el tablero, dado que la detección es automática. Se ha de poner una ficha en el medio del tablero (no importa de qué jugador) y colocar el resto de las piezas en su lugar, cuando esten todo pronto para empezar la partida, se coloca la pieza que se encuentra en el medio del tablero en su lugar, y se espera a que el dispositivo emite un pitido, indicando que se puede comenzar a jugar.

Consideraciones sobre la Solución

A continuación se describe el ambiente utilizado para desarrollar.
La solución que se llegó fue más acotada de lo que se planteó en un inicio, dado que se hizo énfasis en el procesamiento de las imágenes y no tanto en el problema, es que actualmente (Julio 2014) la aplicación solo detecta donde hay fichas y luego de cada movimiento de un jugador manda una matriz 8x8 binaria indicando donde hay o no fichas si hubo un movimiento efectivo.

Otra consideración importante para el uso de la aplicación es la iluminación, la misma debe de ser uniforme. Dado que era una de las precondiciones del proyecto, no se tuvo en cuenta en ninguno de los algoritmos de procesamiento de imágenes.

Otro hecho a tener en cuenta para el uso de la aplicación es el tamaño del tablero y la altura donde debe de estar el dispositivo para poder ver todo el tablero.

La calibración no es automática, se debe de decirle a la aplicación que debe de calibrar para detectar el tablero, luego de detectarlo emite un pitido y el dispositivo no puede ser movido de esa posicion, asi como tampoco se permite la re-calibración luego de iniciada la partida. Es importante apreciar que el plano de la cámara debe de ser paralelo al plano del tablero y que éste más una margen de un escaque han de aparecer en la imagen de la aplicación. No importa de què lado van a estar las fichas con respecto al dispositivo, pero si la rotación del tablero con respecto al mismo, lo ideal es que las líneas del tablero sean paralelas a los bordes de la imagen, aunque la aplicación puede soportar una pequeña rotación del mismo con respecto a esta alineación, siempre que se consideren los márgenes antes mencionados.