Logo USM                                  

                                    Reconocimiento Facial                                        

Diseño y Programación Orientados a Objetos  - ELO  329
Autores: Critian Carrasco G.                                                                                                                                              cristian.carrascog AT alumnos DOT usm DOT cl                  
                   Luis Fuentes W.                                                                                                                                                        
luis.fuentesw AT alumnos DOT usm DOT cl
                   Felipe López P.                                                                                                                                                           felipe.lopezp AT alumnos DOT usm DOT cl

Profesor: Agustín González.

Introducción Descripción del Problema
Análisis del problema
Diseño de la solución
Implementación
Descarga


      Introducción

        Este sitio web resume el problema y solución del proyecto final Reconocimiento Facial, llevado a cabo en el Ramo Diseño y Programación orientados a Objetos. En las diversas secciones
        de la página se describe y analiza el problema. Posteriormente se diseña la solución y se muestra cómo fue implementada. Finalmente, el código fuente se encuentra disponible para su descarga
        en la sección del mismo nombre.


      Problema a resolver

          El problema que nos propusimo resolver es la detección de rostros utilizando una cámara web. Para esto necesitamos solo una cámara web de gama media.
          Este problema tiene múltiples aplicaciones en diversas áreas. Las más importantes son dos:
               Como se sabe los delicuentes que comenten hurtos y robos en las calles, llamados comúnmente lanzas, casi siempre son los mismos. Existe un círculo vicioso en el cual al ser detenidos, por
               diversas razones no debatibles aquí, vuelven a la calle en un par de días o a lo más meses, y nuevamente vuelven a delinquir. Por lo tanto, al ser detenidos se le podría ingresar a la base de
               datos del sistema para posteriormente realizarles un seguimiento con las cámaras públicas que se encuentran en gran parte del país. Así, se podría saber de forma automática si un lanza
               merodea las calles para realizar un delito o solo transita para ir a algún lugar. Esto facilitaría además, las posibles detenciones, ya que el sistema identificaría automáticamente dónde se
               encuentra el ladrón en ese instante.               En lugar de que el personal marque tarjeta o firme algún tipo de libro al llegar y/o irse de la empresa, se podría implementar un sistema en el cual cuando las personas ingresen por la puerta                           principal inmediatamente el sistema las reconozca y las ingrese a la base de datos previamente confiigurada. Un sistema similar se podría implementar en la universidad para llevar un control
              acabado de las personas que ingresan y transitan por la universidad. También se podría llevar un registro en las salas para evitar pasar lista en los certamenes o en los ramosen los cuales la
              asistencia es necesaria, como podrían ser los laboratorios.           
                        

      Análisis del problema

              Para resolver el problema se necesita una cámara web de gama media, con resolución 800 x 600 pixeles, con la cual se va a capturar el video. Luego, con el video disponible se van a
              capturar múltiples fotos por segundo. Con estas fotos el sistema detecta en primer lugar si en la foto se encuentra algún rostro, y si así es lo recorta y normaliza la foto para que ésta 
              pueda ser ingresada al algoritmo de reconcimiento LDA. Una foto normalizada quiere decir que debe estar en blanco y negro, todas deben tener el mismo tamañan, 100 x 100 pixeles,
              y otras características que no valen la pena mencionar en este apartado. Finalmente, la foto normalizada se ingresa al algoritmo de reconocimiento el cual nos dice a qué usuario se
              identificó.       
        
              A continuación se muestran los dos casos de usos más importantes del programa:
               
              Caso de Uso 1:
              Nombre: Registrar una persona.
              Propósito: Ingresar a una persona a la base de datos.
              Actor: Usuario.
              Pre-condición: El programa está corriendo.
              Evento: El usuario presiona el botón ingresar datos.
              Post-condición: La persona queda registrada en la base de datos del programa.
              Tipo: Manual.

Casos de uso

            Caso de Uso 2:
              Nombre: Reconocimiento facial.
              Propósito: El programa detecte a la persona que se encuentre delante de la cámara.
              Actor: Usuario.
              Pre-condición: El programa está corriendo.
              Evento: El usuario selecciona la pestaña Reconocimiento.
              Post-condición: El programa detecta a la persona mostrando nombre y rut.
              Tipo: Manual.
Casos de usos

             Pruebas

                  Caso de uso 1: Registrar una persona

                  En este caso el usuario selecciono la pestaña "Registro Rostros", posteriormente ingreso su nombre y Rut de forma correcta, luego presiono 5 veces el botón "Tomar nueva foto", obteniendo                           imágenes donde el sistema detecto automáticamente el rostro dentro de la imagen y las desplego en el lado derecho de la pantalla. De estas 5 imágenes el usuario selecciono 3 (marcadas en                           rojo) y presiono "Ingresar Datos", y el sistema quedo nuevamente entrenado incluyendo a la nueva persona.

                  Caso de uso 2: Reconocimiento facial


                 El usuario seleccionó la pestaña "Reconocimiento" donde inmediatamente el programa detecto un rostro en la imagen y lo reconoció, desplegando en el lado derecho, en forma de botón, la                              imagen a la que asocio el rostro detectado. Al presionar el botón, se despliega el siguiente menú:

                Donde se desplego el nombre, el RUT y un registro de la hora y la fecha en las cuales se ha detectado el rostro. Hay que notar que mientras tanto, el programa sigue buscando y                                             reconociendo rostros en la imagen de la cámara.

                Dificultades:

                Las principales dificultades en el desarrollo del programa fueron:

                - Obtención de la imagen desde la cámara web: Ya que java no tiene un modo nativo para acceder a los periféricos del sistema, ni de procesar el video para desplegarlo, se requirió de uso de                       bibliotecas externas. En un principio se pensaba usar OpenCV, y JNI para poder acceder a los métodos de OpenCV, ya que este está en C++, pero finalmente, se utilizo JavaCV que es una                         biblioteca para java que utiliza JNA para hacer lo mismo que se quería lograr con JNI de una forma mucho mas facil.

                - Refresco de la imagen lenta: Como se explica en la sección de diseño de la solución, la imagen en un comienzo se veía con un refresco muy lento, llegando a 1 fps (frames per second). Esto                         se solucionó haciendo que cada acción se realizara en hebras diferentes, con lo que la imagen se pudo desplegar en paralelo mientras se hacían los cálculos correspondiente a la detección y                             reconocimiento.

                - Métodos de clasificación:  Inicialmente el programa tenía contemplado usar 2 métodos de clasificación para obtener a quien correspondía el rostro detectado, por distancia euclidiana y por                         redes neuronales, pero para lograr un mejor desempeño en redes neuronales que por distancia, se requería un tiempo demasiado largo de entrenamiento, por lo que el registro de rostros era                         demasiado lento e impracticable. Finalmente se decidió, no incluir las redes neuronales en el programa principal, pero que de todas formas esta quede implementada en el código.

                Bugs conocidos:

                - Detección falsa de rostros: Debido a que el método de detección de rostro busca patrones dentro de la imagen de entrada, es posible que en ciertas ocasiones detecte como rostros cosas                         que no lo son, como manchas y relieves en la muralla de fondo.

                - Reconocimiento equivocado: Considerando que lo detectado era efectivamente un rostro, existe una posibilidad de que el programa se equivoque en reconocer a la persona y lo asocie a                             otra imagen existente en el entrenamiento. El método usado tiene una tasa de error de 10 a 20%, por lo que es muy posible que se reconozca mal un rostro, aunque rápidamente el sistema                             debería volver a reconocer el rostro y desplegar el correcto de forma casi instantánea, aunque también puede no ocurrir.

                De forma análoga, si un rostro de una persona que no está en el set de entrenamiento pasa por la cámara, esta será detectada como alguno de las personas que están registradas,                                             produciéndose un error relativamente grave, ya que el programa, en un par de segundos, puede registrar que pasaron todas las personas por ahí, siendo que fue alguien que simplemente no                             estaba registrado.



      Diseño de la solución

            Para implementar el reconocimiento de rostros se uso el método PCA (Principal Component Analysis), el que básicamente consiste en transformar un gran número de variables correlacionadas,                     en este caso los pixeles, a un menor número de variables no relacionadas, reduciendo en una gran parte las dimensiones de las variables a clasificar.

            Para clasificar las proyecciones de las imágenes en el espacio vectorial generado, se implementaron 2 métodos, comparación mediante la mínima distancia euclidiana y clasificación usando redes                     neuronales. Debido a que esta ultima toma mucho tiempo de entrenamiento para llegar a un resultado mejor que el primero, se decidió dejar la distancia euclidiana como método principal de                         clasificación, sin embargo, se puede cambiar fácilmente a red neuronal cambiando un parámetro en  el código fuente, específicamente en el constructor de PCA.

            Para mayor información sobre el método, este está explicado con detalle en este paper, sin considerar el punto 3, que corresponde a otro método no implementado.

            Por otro lado, debido a que se necesito capturar imágenes desde una cámara para que el sistema sea manipulado en tiempo real y que se detectaran los rostros dentro de la, se requirió el uso de                     bibliotecas como OpenCV y JavaCV. Al hacer estos calculos de forma secuencial, el tiempo desde que terminaba de reconocer un rostro y mostrar nuevamente la imagen era demasiado alto,                         perdiendo la fluidez y el tiempo real deseado, por lo que se utilizaron diferentes hebras o hilos para realizar las diferentes acciones que el programa debe realizar al mismo tiempo, estas son                             mostrar la imagen de la cámara, capturar la imagen, detectar un rostro y reconocer el rostro.

            Finalmente el diagrama de clases quedó de la siguiente forma:

Diagrama de Clases

                Mientras que las  tarjetas CRC de las 2 clases principales son:
Tarjeta CRC

Tarjeta CRC



      Implementación

               Para implementar el código realizado son necesarias tres bibliotecas especiales.
                 
OpenCV (Open Source Computer Vision) es una biblioteca para funciones de computación visual en tiempo real. Con esta biblioteca se realizaron las funciones básicas con la cámara web, como tomar fotos, normalizar cada fotos, y otras funciones. Sin embargo, esta biblioteca es para C++, por lo cual se necesita javacv.

Esta biblioteca se utiliza como interfaz de OpenCV con Java, ya que como se explicó anteriormente, OpenCV está escrito para utilizarlo en C++.

    Biblioteca para cálculo técnicos y científicos enfocados a la ingeniería. Con esta biblioteca se realizaron                   fácilmente los cálculos con matrices, tales como multiplicaciones, transpuestas, etc.

              En el siguiente link se encuentra la documentación del código, realizada con Javadoc.
                     
             
         
              Para generar el Javadoc del código, se debe esrcibir en consola:  $javadoc -d doc *.java
                                     

      Descarga  

            El proyecto se puede descargar desde el siguiente link:

            -Proyecto.rar

            Instalable: Windows 95/98/NT/XP/2008

            Se puede bajar e instalar una versión instalable pre compilada de OpenCV, para la ejecución de este se requiere además tener instalado Microsoft Visual C++ 2008 SP1 Redistributable Package                 (o alguna versión de Visual Studio 2008).

            Código fuente: Windows 95/98/NT/XP/2008 o Unix based OS

            De forma alternativa, se puede obtener descargar el código fuente, en c++, y realizar la compilación. Las instrucciones de instalación se encuentran en 

             http://opencv.willowgarage.com/wiki/InstallGuide.

            En ambos casos se requiere que el System PATH esté configurado para incluir a los binarios de OpenCV (por ejemplo C:\OpenCV2.1\bin).

            - JavaCV

            La biblioteca requerida se puede descargar desde el siguiente link, este enlace incluye la JNA 3.2.5 requerido para el funcionamiento de JavaCV. Tras descargar, descomprimir en algún directorio               deseado.

            - Colt

            La biblioteca requerida se puede descargar en alguno de los siguentes formatos: Zip, tar.gz. Al igual que JavaCV, descomprimir en algún directorio deseado.

            Compilación y Ejecución:

            Para la compilación y ejecución del programa, se requiere especificar el classpath de tanto de JavaCV como de los 2 archivos .jar de Colt. En el caso de que ambas bibliotecas hayan sido                             descomprimidas en el mismo directorio que el código fuente, tal como estas venían en el archivo comprimido, la compilación seria de la siguiente forma:

            javac -classpath .; javacv.jar; colt\lib\colt.jar; colt\lib\concurrent.jar tabDemo.java

            Y de forma análoga, la ejecución:

            java -classpath .; javacv.jar; colt\lib\colt.jar; colt\lib\concurrent.jar tabDemo



         

            Cualquier pregunta o consulta no duden en mandar un mail : )