título: interfaz persona-ordenador mediante lenguaje
TRANSCRIPT
Título: Interfaz persona-ordenador mediante lenguaje gestual
Volumen: 1
Alumno: Hugo Tomás Benedet Jiménez
Director/Ponente: Joan Climent Vilaró
Departamento: ESAII (Enginyeria de Sistemes, Automàtica i
Informàtica Industrial)
Fecha:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
2
DATOS DEL PROYECTO
Título del Proyecto: Interfaz persona-ordenador mediante lenguaje gestual
Nombre del estudiante: Hugo Tomás Benedet Jiménez
Titulación: Ingeniería Informática
Créditos: 37,5
Director/Ponente: Joan Climent Vilaró
Departamento: ESAII
MIEMBROS DEL TRIBUNAL (nombre y firma)
Presidente: Joan Aranda López
Vocal: Albert Oliveres Llunell
Secretario: Joan Climent Vilaró
CALIFICACIÓN
Calificación numérica:
Calificación descriptiva:
Fecha:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
4
Agradecimientos
En primer lugar me gustaría dar las gracias a Joan Climent Vilaró, director de este proyecto,
por su tutela y supervisión. Su experiencia ha ayudado a cumplir los hitos y objetivos de este
proyecto.
Al equipo de docentes de la Facultad de Informática de Barcelona, quienes durante todo este
largo trayecto, me han proporcionado todos los conocimientos necesarios para afrontar esta
carrera profesional.
También quisiera agradecer el soporte que me ha brindado mi mujer, Maribel, que ha tenido
que sufrir todos mis altibajos y ha aguantado estoicamente las largas jornadas de trabajo que he
realizado estos últimos meses. Sin su ayuda hubiese sido imposible entregar este proyecto.
A mis padres, por haberme aportado tanto la educación necesaria como los medios para estudiar
Ingeniería Informática, esa profesión que siempre ha llamado a mi puerta. A mi difunto tío, por
haberme dado las primeras clases de programación en BASIC. A mis hermanos y cuñados, por
el ánimo que me han dado durante toda la carrera.
Quisiera también hacer especial mención a mis colegas de carrera. A Aarón Montero Montero
y Víctor Sotillo Reinaldos, grandes compañeros y amigos desde el primer día de clase. Como
ya sabéis han sido muchas horas de clases, laboratorios y ejercicios en el bunker, muchas
alegrías y tristezas, pero, para lo bueno y lo no tan bueno, siempre estuvisteis ahí. A Alicia
González López, y Susana Del Moral Arjona, a quienes el destino me llevó a conocer en esta
universidad. Vuestro ejemplo y dedicación me ha empujado a mejorar día a día. A Albert Neira
Yáñez, con quien he tenido la suerte de coincidir, no solo en esta etapa universitaria, sino
también en la laboral. Hemos compartido, desde errores de compilación, a robots que andaban,
y desde pequeños evolutivos a grandes problemas en Producción. Y a Miguel Ángel Marina
Ramírez quien ha sido un gran compañero de universidad, aunque últimamente esté
desaparecido.
A mis amigos, a quienes, durante estos últimos meses, he tenido abandonados para poder llevar
a término este proyecto.
Por último también quisiera dar las gracias a todos aquellos que, a pesar de no haber sido
citados, de un modo u otro, han contribuido a que este proyecto haya llegado a buen puerto.
A todos… ¡Gracias!
Hugo Tomás Benedet Jiménez
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
6
ÍNDICE
1. Introducción ..................................................................................................................... 9
1.1 Motivaciones .......................................................................................................... 11
1.2 Objetivos ................................................................................................................. 12
1.3 Estado del arte ....................................................................................................... 13
1.4 Planificación y coste económico del proyecto ............................................. 17
1.4.1 Planificación del proyecto .............................................................................. 19
1.4.2 Coste del proyecto ............................................................................................ 21
1.4.3 Planificación mediante consultora IT .......................................................... 22
2. Conceptos básicos ...................................................................................................... 26
2.1 Espacio de colores ............................................................................................... 26
2.1.1 Matiz ...................................................................................................................... 26
2.1.2 Saturación ........................................................................................................... 27
2.1.3 Valor ...................................................................................................................... 27
2.1.4 Transformación RGB a HSV ........................................................................... 28
2.2 Algoritmo de Viola & Jones ............................................................................... 29
2.2.1 Imagen Integral .................................................................................................. 29
2.2.2 Extracción de características ........................................................................ 31
2.2.3 AdaBoost ............................................................................................................. 32
2.2.4 Clasificador en cascada .................................................................................. 34
2.3 Imagen binaria y región de interés ................................................................... 35
2.4 Ruido y filtrado ...................................................................................................... 36
2.5 Centro de masas ................................................................................................... 38
2.6 Dynamic Time Warping ....................................................................................... 39
2.6.1 Definición Dynamic Time Warping ............................................................... 40
2.6.2 Complejidad y restricciones .......................................................................... 41
2.6.3 Cálculo de los coeficientes ............................................................................ 43
2.6.4 Complejidad ........................................................................................................ 43
2.6.5 Fast DTW ............................................................................................................. 44
3. Definición de los movimientos a detectar ............................................................. 46
3.1 Inicio y fin de movimiento .................................................................................. 46
3.2 Conjunto de movimientos a detectar .............................................................. 47
3.2.1 Movimiento hacia arriba .................................................................................. 47
3.2.2 Movimiento hacia abajo ................................................................................... 47
3.2.3 Movimiento hacia la derecha ......................................................................... 48
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
7
3.2.4 Movimiento hacia la izquierda ....................................................................... 48
3.2.5 Movimiento circular .......................................................................................... 49
3.2.6 Movimiento de saludo ...................................................................................... 50
4. Implementación ............................................................................................................ 51
4.1 Plataforma de desarrollo ..................................................................................... 51
4.1.1 Entorno de desarrollo ...................................................................................... 51
4.1.2 Librería de visión por computador ............................................................... 51
4.1.2.1 OpenCV ............................................................................................................ 53
4.1.3 Librería de aprendizaje por computador .................................................... 53
4.1.4 Lenguaje de programación ............................................................................. 54
4.1.4.1 Java ................................................................................................................... 54
4.1.4.2 JDK & JVM 1.8 ................................................................................................ 55
4.1.5 Eclipse .................................................................................................................. 56
4.2 Detalles de implementación ............................................................................... 57
4.2.1 Obtención de imágenes ................................................................................... 57
4.2.2 Imagen especular .............................................................................................. 59
4.2.3 Algoritmo de Viola & Jones ............................................................................ 60
4.2.4 Filtrado de imágenes ........................................................................................ 60
4.2.5 Binarización de imágenes ............................................................................... 62
4.2.6 Región de interés .............................................................................................. 63
4.2.7 Dynamic Time Warping .................................................................................... 64
4.2.8 Clasificador ......................................................................................................... 65
5. Diseño de la GUI ........................................................................................................... 66
6. Diagrama de bloques .................................................................................................. 70
7. Patrones de software utilizados ............................................................................... 71
7.1 Patrón Modelo-Vista-Controlador ..................................................................... 71
7.1.1 Interacción entre los componentes .................................................................. 71
7.1.2 Detalles de construcción ..................................................................................... 72
7.2 Patrón Observador ............................................................................................... 74
7.3 Patrón Singleton ................................................................................................... 76
7.4 Arquitectura en 3 capas ...................................................................................... 77
7.5 Patrón Data Access Object ................................................................................ 78
8. Diagrama de Clases ..................................................................................................... 80
8.1 Diagrama de clases detallado MVC ................................................................. 80
8.2 Diagrama de clases detallado Vista ................................................................. 81
8.3 Diagrama de clases detallado Modelo ............................................................ 82
8.4 Diagrama de clases detallado ProcesadorFrame ........................................ 83
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
8
8.5 Diagrama de clases detallado Detector .......................................................... 84
8.6 Diagrama de clases detallado DAO ................................................................. 85
9. Conclusiones ................................................................................................................. 86
10. Líneas de futuro ........................................................................................................ 87
11. Bibliografía ................................................................................................................. 89
Anexo A. Preparación del entorno de trabajo ............................................................. 93
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
9
1. Introducción
En los inicios de la informática, ni los diseñadores ni los desarrolladores prestaban atención a
la problemática de hacer que el hardware y los productos de software fueran amigables para el
usuario final. Esto principalmente se debía a que el acceso a los ordenadores estaba restringido
a unos pocos privilegiados que podían permitirse el elevado coste de los mismos y además, el
acceso a información quedaba acotada a ámbitos profesionales y académicos muy
especializados. Así pues, en aquella época primaba la eficiencia y la funcionalidad por encima
de la usabilidad.
Durante los siguientes años se ha experimentó una increíble evolución de la informática. Por
un lado, gracias al aumento del nivel de integración de los circuitos, no solo se redujo el tamaño
de los ordenadores, sino que se abarataron costes y se aumentaron las prestaciones. Por otro
lado, gracias a la globalización sufrida por Internet, la información se volvió mucho más
accesible para todos los públicos, evitando tener que ir, forzadamente, a las bibliotecas
tradicionales a buscarla.
La combinación de estos factores hizo que muchos más usuarios pudieran acceder a los
ordenadores y al mundo de la informática en general, por lo que factores como la usabilidad,
que en el pasado apenas se tenían en consideración, pasaron a ser factores determinantes, hasta
el punto que hoy en día no se concibe una aplicación de usuario con una interfaz poco amigable.
En estos últimos años, los sensores de bajo coste han comenzado a impactar en la forma en que
la gente interactúa con sus dispositivos. Las pantallas táctiles han impulsado el cambio en los
teléfonos móviles. El uso de la voz y los gestos para activar funciones en dispositivos personales
está empezando a ser una interfaz cotidiana para la mayoría de nosotros.
Empresas del ámbito del entretenimiento invierten millones de euros en investigación y
desarrollo de nuevas formas de controlar sus dispositivos, con el objetivo único de conseguir
una experiencia de usuario única y una mayor inmersión en los videojuegos.
Interfaces como Nintendo Wii Remote (2006), PlayStation Move (2010) o Microsoft Kinect
(2011), representan un paso adelante hacia la implementación de interfaces completamente
naturales, donde el cuerpo se transforma en el propio controlador. Estos dispositivos traducen
gestos y posturas corporales a instrucciones que permiten controlar los videojuegos, en tiempo
real.
Hardware Microsoft Kinect Hardware PlayStation Move Hardware Wii Remote
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
10
Por otro lado, empresas privadas como Leap Motion han
sacado al mercado dispositivos que pueden realizar el
seguimiento interactivo de las manos de un usuario al
identificar la posición de los dedos y del centro de la
palma de la mano.
Algunos fabricantes de televisores inteligentes están
empezando a implementar sistemas que permitan a los
usuarios interactuar con el televisor por medio de gestos,
con el fin de reemplazar el mando a distancia tradicional.
Del mismo modo, los grandes referentes del
automovilismo están invirtiendo muchísimos recursos en sistemas de protección activa, como
sistemas dotados con cámaras que detectan si un conductor está somnoliento o si intenta
conducir ebrio, con el fin de detener el vehículo para evitar posibles accidentes.
Hace tan solo unos años atrás, los escenarios y tecnologías referenciados en párrafos anteriores
solo podían encontrarse en películas de ciencia ficción como Minority Report (2002).
Las oportunidades que nos brindan las interfaces entre personas y computadores son casi
infinitas y pueden llegar a cambiar nuestras vidas tal y como la concebimos hoy en día.
Hardware Leap Motion
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
11
1.1 Motivaciones
La interacción entre personas y ordenadores (Human-Computer Interaction) es un área que,
dada su naturaleza, permite poner en práctica conocimientos de múltiples asignaturas cursadas
en Ingeniería Informática (Visión por Computador, Minería de Datos, Inteligencia Artificial,
Estadística, Matemáticas, Programación…). Estos conocimientos van desde el procesamiento
y filtrado de imágenes para detectar gestos y acciones realizadas por un usuario o la creación
de heurísticas que permitan discriminar entre los diferentes gestos para poder tomar una
decisión o para realizar una acción, a la programación de todos y cada uno de estos algoritmos.
Si además, esta interfaz se comunicara con algún circuito electrónico o robot, permitiría aplicar
conocimientos de otras muchas asignaturas (Periféricos, Robótica, Procesamiento de Señales,
Redes,…) para enviar información a robots humanoides o para implementar nuevas formas de
interactuar con dispositivos electrónicos.
Por otro lado, este proyecto me permite investigar cómo funcionan los dispositivos hardware
de reconocimiento de gestos que existen a día de hoy, y entender conceptos y tecnologías muy
incipientes en el mercado. Así mismo, me permite desarrollar algunos de los métodos y técnicas
adquiridos en la carrera en mayor profundidad.
Por último, el hecho de crear una interfaz de reconocimiento de gestos de propósito general,
mediante webcam, y que pueda ser portada a cualquier tipo de dispositivo (portátil o móvil), es
un reto complicado de abordar pero que, en un futuro, podría llegar a ser útil para mucha gente
que tiene conocimientos limitados de informática o una cierta aversión a interactuar con
ordenadores, robots y máquinas en general.
Todas estas características hacen que este proyecto sea un reto muy interesante y completo, que
pone a prueba los conocimientos adquiridos durante los cuatro años y medio que dura la carrera
y permite satisfacer inquietudes personales, a la vez que aporta un sentido global a los estudios
cursados.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
12
1.2 Objetivos
Este proyecto pretende implementar una
interfaz persona-ordenador capaz de interpretar
lenguaje gestual.
Para desarrollar el proyecto, se va a disponer de
un ordenador conectado a una webcam, la cual,
va a capturar los movimientos de la escena.
Para acotar el alcance del proyecto, se
establecen las siguientes restricciones:
El sistema que se implementará parte de
la premisa de que la escena será una habitación debidamente iluminada.
Los movimientos se capturarán a partir de la mano derecha de una persona, por lo que
en la imagen debe reconocerse una persona de cintura hacia arriba.
Para tomar la región de interés (mano derecha), se va a aplicar un algoritmo de detección de
caras (Viola-Jones). También se aprovechará la detección de la cara para retroalimentar al
sistema con el color de la piel de la persona que aparezca en la escena y mejorar la detección
de la mano.
Para restringir el alcance del proyecto se establece que el sistema tiene que ser capaz de detectar
6 movimientos diferentes. Estos movimientos deben empezar y acabar en la misma posición y
deben tener una pequeña pausa entre ellos para que la aplicación pueda interpretarlos como
movimientos independientes
Por otro lado, se implementará un algoritmo de Dynamic Time Warping (DTW) para
discriminar los movimientos capturados contra un pequeño subconjunto de movimientos
registrados en el sistema.
Este algoritmo se encargará de decidir si el movimiento capturado es interpretable por el sistema
o, por el contrario, debe ser descartado por no tener un nivel de similitud significativo con
alguno de los movimientos registrados en el sistema.
Por último, el sistema tendrá desarrollada una interfaz que, en base a los movimientos
identificados, sea capaz de realizar acciones sobre un ordenador (pulsar teclas, mover el
ratón,…).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
13
1.3 Estado del arte
Antes de iniciar el proyecto se realizó un análisis del estado del arte y de cómo otras personas
habían abordado problemas similares. Tras buscar intensamente a través de Internet, se encontró
información acerca de varios proyectos no comerciales que tratan sobre el reconocimiento de
movimientos.
Un hecho remarcable es que, la mayoría de ellos, utilizaban la librería OpenCV para procesar
las imágenes. Un análisis posterior llevó a la conclusión que esto no era una simple
coincidencia.
La librería OpenCV está bastante estandarizada en el mundo de la Visión por Computador,
aunque hay también muchos desarrolladores e investigadores que utilizan librerías de Matlab
para desarrollar sus proyectos.
Igual que la librería de Visión por Computador está bastante estandarizada, se detectó que en
lo que respecta al lenguaje de programación había una clara diversidad. Muchos desarrolladores
e investigadores utilizan C++ y Python para desarrollar sus proyectos y pruebas, mientras que,
Java es un lenguaje que apenas se utiliza para dichos desarrollos.
A continuación se van a comparar los proyectos más destacados que encontramos durante
nuestro análisis del estado del arte:
Proyectos que reconocen los dedos de la mano
La mayoría de proyectos encontrados ([2], [8], [12], [13], [14], [15], [24], [27]) hacen
referencia a la detección de los dedos de las manos.
Todos ellos realizan una binarización de la imagen que contiene una mano a partir de
un rango de colores. Tras binarizar la imagen, proceden a crear una caja envolvente
sobre la mano y aplican un algoritmo de OpenCV para detectar puntos de convexidad.
A partir de estos puntos de convexidad, con una heurística más o menos compleja,
determinan qué dedos son los que aparecen en la imagen.
La mayoría de proyectos identifica un número reducido de gestos con la mano, aunque
alguno de ellos [10] amplía el rango hasta abarcar el idioma de los sordos.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
14
Otro punto a remarcar sobre este tipo de proyectos es que en ningún momento aparece
una persona de cuerpo entero, sino que en la escena únicamente aparece una mano sobre
un fondo simple.
Esto ayuda mucho a la hora de binarizar la imagen. Por otro lado, asegura que no
aparecerá ruido en la escena que pueda alterar los resultados del programa.
Finalmente destacar que el código fuente que contienen todos estos programas ha podido
ser compilado, aunque se ha tenido que realizar algún cambio debido a que las librerías
de OpenCV no identificaban alguna función porque usaban versiones dispares de
OpenCV.
Un hecho sorprendente es que los proyectos que pudieron ser ejecutados, no
funcionaban según se esperaba.
Otro hecho remarcable que hace destacar al proyecto [14] frente al resto es que la
detección del color de la mano se hace de forma dinámica.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
15
Para ello, genera un patrón como el de la imagen adjunta y obtiene una media de color
para cada uno de los rectángulos. Con esa media de color, aplica hasta 7 binarizaciones
de la misma imagen, las cuales se integran en una única imagen.
Con este enfoque, el autor consigue tener una binarización de la mano mucho más
robusta que se adapta a cambios en la iluminación debido al movimiento de la mano.
Proyectos que utilizan técnicas de minimización de energía
Los proyectos [9] y [11] utilizan una representación de la mano obtenida mediante
técnicas de minimización de energía. Una vez más, los proyectos se centran en detectar
gestos de una mano y no movimientos.
A diferencia de los proyectos anteriores, en este caso se utiliza un modelo de
minimización de energía para representar los dedos de la mano. En función del ángulo
que forman los dedos y de los nodos que tiene el árbol, establecen una heurística para
detectar ciertos símbolos con la mano.
Otro punto remarcable es que en el caso de [11] utiliza un guante de un color
determinado para realizar la binarización de la imagen. Esto permite poder hacer gestos
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
16
en un entorno estándar (habitación) en el que no interviene un fondo uniforme y
controlado.
En el caso de [9] no se puede analizar este punto puesto que se queda en una base teórica.
Proyectos que utilizan hardware específico (Kinect)
Durante la investigación sobre el funcionamiento del proyecto, se observó que existen
bastantes proyectos que utilizan el hardware Kinect para la detección de movimientos.
El uso de Kinect no entra dentro del alcance de este proyecto pero, no obstante, al haber
encontrado bastantes proyectos basados en esta tecnología, se ha considerado
remarcable citar un caso [29], como referencia a todos ellos.
Kinect es un dispositivo que dispone de una cámara RGB que capta la luz visible y los
movimientos de una persona. Así mismo, dispone de un sensor de infrarrojos que se
encarga detectar la profundidad de los objetos y un motor para poder hacer un tracking
de la persona.
Toda esta información se integra hasta que Kinect es capaz de identificar qué partes del
cuerpo están en la escena. A partir de ese pequeño ajuste que realiza Kinect, se genera
un esqueleto con las partes que ha reconocido del cuerpo.
Proyectos que reconocen gestos
Sorprendentemente, ha sido difícil encontrar proyectos que detecten gestos de una
persona a cuerpo completo. Por ello, destaca el proyecto [10].
Este proyecto detecta diferentes posiciones de los brazos basándose en la proporción del
cuerpo. A modo de ejemplo, si un brazo está a la altura de la cabeza, el sistema determina
que el brazo está levantado.
La posición del brazo la obtiene a partir de los histogramas de la imagen (parte gris)
A pesar de no detectar un movimiento fluido, es el único proyecto que se ha encontrado
en el que interviene una persona a cuerpo completo y donde no hay un escenario
controlado.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
17
1.4 Planificación y coste económico del proyecto
En este apartado se realiza una planificación preliminar del proyecto, teniendo en cuenta las
etapas que lo componen, así como las diferentes partes a desarrollar, y estimando el tiempo que
llevaría realizarlas.
Todo proyecto se puede dividir en las siguientes partes:
Toma de requerimientos
En esta parte se definen todos los objetivos del proyecto y se toman todos los requisitos
imprescindibles del mismo. También se definen que herramientas y librerías se
utilizarán y se empieza a hacer una estimación del tiempo que llevará cada fase.
Análisis
En esta fase se empiezan a abordar los diferentes objetivos del proyecto en grandes
bloques. Se empieza a preparar el entorno de trabajo en base a los requisitos técnicos y
se procede a realizar las primeras pruebas con las librerías de trabajo.
También se empiezan a desglosar los diferentes módulos que se deben implementar.
Construcción
Una vez se ha definido el grueso de la aplicación, se inicia la fase de implementación.
Esta fase es, sin lugar a dudas la que más tiempo llevará.
Al ser una fase grande, es importante desglosarla en módulos independientes. Este punto
será clave si el proyecto se realiza por más de una persona, puesto que una correcta
granularidad en las tareas permitirá mayor paralelización.
Para completar esta fase debemos tener finalizados todos los módulos que componen el
programa que se desarrolla en este proyecto.
Pruebas y configuración
En esta etapa se validarán los diferentes módulos que se han construido. Así mismo, se
realizarán los ajustes que sean necesarios para calibrar la aplicación y asegurar que
funciona tal y como se espera.
Podría ser que las pruebas realizadas no sean satisfactorias y se deba modificar algún
módulo del programa.
Documentación
En esta etapa se documentarán todos los detalles de cada una de las fases, por lo que,
esta fase se debe realizar en paralelo a todas las etapas del proyecto.
Es importante documentar todo el proyecto en el momento que se realiza y no dejarlo
para el final, puesto que de lo contrario se pueden olvidar u obviar detalles importantes.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
18
Presentación
Para finalizar la entrega de un proyecto, este se debe presentar, explicando las bondades
del mismo y demostrando que el programa desarrollado cumple las expectativas y los
requisitos que se definieron durante la toma de requisitos.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
19
1.4.1 Planificación del proyecto
A continuación se adjunta un plan de trabajo a alto nivel donde se detalla temporalmente la dedicación para cada una de estas etapas:
Seguidamente se detallan las tareas de cada uno de los bloques:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
21
1.4.2 Coste del proyecto
El desarrollo de un proyecto de final de carrera no se asemeja a la realizad de un proyecto real.
Esto es debido a que únicamente intervienen dos figuras en proyecto, el proyectista y el
profesorado.
Adicionalmente, en la mayoría de casos, el proyectista realiza el proyecto sin percibir ningún
incentivo económico, lo cual hace que los costes del proyecto sean muy inferiores a los que
realmente se derivarían de un proyecto así.
En este caso trabajaremos con la premisa de que los costes derivados del proyecto por horas de
trabajo son las siguientes:
Euros / hora
Proyectista 0 €
Profesorado 45 €
El desarrollo del proyecto actual se centra básicamente en la figura del proyectista. En esta
figura recae la mayor parte del proyecto.
El proyectista es quien se encarga de realizar la toma de requerimientos, analiza el
funcionamiento de las diferentes librerías, codifica y valida el código, y, finalmente presenta el
proyecto.
Según el diagrama de Gantt anterior, podemos estimar que se requiere un esfuerzo de unos 104
días a 8h por día.
Por otro lado tenemos la figura del profesorado. El profesorado tiene la tarea inicial de idear el
proyecto y aterrizarlo en objetivos asumibles por los alumnos. Así mismo, el profesorado
realiza tareas de soporte y seguimiento a los proyectistas y, finalmente, dedica tiempo a la
lectura y evaluación del proyecto.
Según el diagrama de Gantt anterior, podemos estimar que las tareas del profesorado se
desglosan del siguiente modo
8 horas para dar de alta el proyecto
1 hora de tutoría semanal
16 horas de lectura y evaluación del proyecto (3 miembros del tribunal)
Esto sumaría un total de (8h x 1 recurso + 1h x 20 semanas x 1 recurso + 16h x 3 recursos) 76
horas a un coste de 45€/hora. En total 3420€.
En cuanto al software, todo el desarrollo se ha realizado con software libre, por lo que no ha
sido necesario adquirir ninguna licencia adicional.
Por otro lado, el proyecto no requiere adquirir hardware costoso. Un simple portátil con una
webcam integrada es suficiente para desarrollarlo.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
22
En su defecto, cualquier ordenador de los laboratorios de la facultad, dotado de una sencilla
webcam de unos 30€ cumple sobradamente con los requisitos exigidos en este proyecto.
Así pues, el coste del proyecto es mínimo, puesto que, en su mayor parte, los costes vienen
derivados de las horas del profesorado:
Precio / Hora Horas Coste
Proyectista 0 € 832 0 €
Profesorado 45 € 76 3.420 €
Hardware 30 €
Software 0 €
Total 3.450 €
Sumando todos los conceptos extraemos que el coste de realizar este proyecto asciende a unos
3450€.
1.4.3 Planificación mediante consultora IT
Como contrapunto a esta evaluación económica, se realiza un análisis de costes suponiendo que
el proyecto se elabora por medio de una consultora (o PyME) del sector de las tecnologías de
la información.
Para un proyecto de esta envergadura (unas 850 horas), se puede derivar que es necesario un
pequeño equipo de trabajo compuesto por un Jefe de proyecto, un Analista y dos
Programadores.
Precio / Hora
Jefe de Proyecto 50 €
Analista 30 €
Programador 20 €
A continuación se desglosarán todas las tareas realizadas por cada uno de los miembros del
equipo, basándonos en el diagrama de Gantt inicial, con el fin de evaluar el coste detallado de
cada uno de los paquetes de trabajo.
Debe notarse que, al ser un equipo de trabajo, algunas tareas se pueden paralelizar, reduciendo
el tiempo de entrega del proyecto drásticamente:
Seguimiento del proyecto
Jefe de Proyecto: 1h de seguimiento semanal con cliente (14 semanas)
2h de seguimiento semanal con el Analista (14 semanas)
Analista: 2h de seguimiento semanal con el Jefe de Proyecto
Toma de requerimientos:
Analista: 4h al día durante 12 días
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
23
Desarrollo y pruebas del sistema
Analista: 3h de validación de código y arquitectura durante 29 días
Programadores: 8h de desarrollo diario durante 29 días (2 programadores)
Pruebas integradas
Analista: 8h al día durante 2 días
Documentación
Jefe de Proyecto: 10h de validación de la documentación final
Analista: 1h al día para realizar la documentación a lo largo de todo el
proyecto (62 días)
Precio / Hora Horas Coste
Jefe de Proyecto 50 € 52 2.600 €
Analista 30 € 258 7.740 €
Programador 20 € 464 9.280 €
Hardware 30 €
Software 0 €
Total 19.650 €
Tal y como se deriva de la tabla adjunta, los costes derivados de hacer el trabajo mediante una
consultora, son mayores (19650€). No obstante, también se reduce el tiempo de entrega del
proyecto en 30 días hábiles.
Ésta eficiencia en tiempo se deriva, sobretodo, del hecho de poder paralelizar ciertas tareas
(desarrollos, pruebas, documentación) que el proyecto actual no soporta.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
24
A continuación se adjunta un plan de trabajo a alto nivel donde se detalla temporalmente la dedicación para cada una de estas etapas:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
26
2. Conceptos básicos Antes de poner foco al trabajo realizado en este proyecto de final de carrera, se van a introducir
algunos conceptos básicos en los que se ha basado el proyecto. Estos conceptos permitirán
ahondar en cómo funcionan los diferentes algoritmos y entender algunas de las decisiones
tomadas en el transcurso del proyecto.
2.1 Espacio de colores
Las cámaras y videocámaras digitales actuales capturan
imágenes gracias a un sensor CCD o bien a un sensor
CMOS. Este sensor se compone de millones de
semiconductores que toman una carga en función de la
intensidad de luz capturada.
Generalmente, los semiconductores están expuestos a un
filtro de Bayer, el cual hace que los semiconductores se
encarguen de capturar diferentes longitudes de onda (colores).
Los colores que se capturan e interpolan son el rojo, el verde y el azul, por ello habitualmente
la imagen se registra en formato RGB (del inglés rojo, verde, azul).
Para llevar a cabo este proyecto, debemos cambiar de espacio de trabajo. Debemos pasar del
formato RGB al formato HSV.
A diferencia del formato RGB, donde se trabaja con mezclas de los tres colores primarios, el
formato HSV trabaja directamente con los componentes del color.
El modelo HSV (del inglés hue, saturation, value)
utiliza el valor del matiz, de la saturación y del brillo
para obtener un color.
Esta propiedad es muy interesante puesto que en el
proyecto nos permitirá filtrar rangos de colores en
función del matiz y de su saturación, y nos permitirá
obviar el brillo, lo cual simplifica en gran medida la
tarea de filtrado.
2.1.1 Matiz
El matiz se representa angularmente. Sus valores se representan como un grado de ángulo, los
valores que puede tomar van de 0° a 359° y cada uno de ellos corresponde a un color.
A continuación se adjunta una pequeña tabla que permite convertir rápidamente los colores
básicos del espacio de color RGB a HSV:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
27
RGB(255, 0, 0) = 0º Color Rojo
RGB(255, 255, 0) = 60º Color Amarillo
RGB(0, 255, 0) = 120º Color Verde
RGB(0, 255, 255) = 180º Color Cyan
RGB(0, 0, 255) = 240º Color Azul
RGB(255, 0, 255) = 300º Color Magenta
Cuando un color toma por valor 360º estamos diciendo que equivale a 0º (valor de matiz módulo
360º).
2.1.2 Saturación
La saturación viene representada como la distancia al eje de brillo (centro del cono). Los valores
posibles vienen determinados entre 0 y 100. Cuanto menor sea la saturación de un color, más
decolorado estará.
La siguiente tabla muestra un ejemplo de saturación con los colores básicos y colores
secundarios:
Matiz 100% saturado
Matiz 75% saturado
Matiz 50% saturado
Matiz 25% saturado
Matiz 0% saturado
2.1.3 Valor
Representa la altura en el eje central del cono. Este valor permite discernir entre tonos blancos
o negros. Los valores vienen determinados entre 0 y 100.
El valor 0 siempre es negro.
El valor 100 siempre es blanco.
Esto significa que el color blanco se puede obtener con cualquier color y saturación, siempre
que se establezca el valor (de luminosidad) máximo. Asimismo, para el color negro se puede
poner cualquier color y saturación, siempre que se ponga un valor de 0.
Dicho de otro modo, la componente Valor carece de componentes cromáticos.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
28
2.1.4 Transformación RGB a HSV
Sea MAX el valor máximo de los componentes (R, G, B), y MIN el valor mínimo de esos mismos
valores, los componentes del espacio HSV se pueden calcular como:
𝐻 =
{
𝑛𝑜 𝑑𝑒𝑓𝑖𝑛𝑖𝑑𝑜, 𝑠𝑖 𝑀𝐴𝑋 = 𝑀𝐼𝑁
60° 𝐺 − 𝐵
𝑀𝐴𝑋 −𝑀𝐼𝑁+ 0°, 𝑠𝑖 𝑀𝐴𝑋 = 𝑅 𝑦 𝐺 ≥ 𝐵
60° 𝐺 − 𝐵
𝑀𝐴𝑋 −𝑀𝐼𝑁+ 360°, 𝑠𝑖 𝑀𝐴𝑋 = 𝑅 𝑦 𝐺 < 𝐵
60° 𝐺 − 𝐵
𝑀𝐴𝑋 −𝑀𝐼𝑁+ 120°, 𝑠𝑖 𝑀𝐴𝑋 = 𝐺
60° 𝐺 − 𝐵
𝑀𝐴𝑋 −𝑀𝐼𝑁+ 240°, 𝑠𝑖 𝑀𝐴𝑋 = 𝐵
𝑆 = {0, 𝑠𝑖 𝑀𝐴𝑋 = 0
1 − 𝑀𝐼𝑁
𝑀𝐴𝑋, 𝑒𝑛 𝑜𝑡𝑟𝑜 𝑐𝑎𝑠𝑜
𝑉 = 𝑀𝐴𝑋
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
29
2.2 Algoritmo de Viola & Jones
En 2001, los ingenieros Paul Viola (Mitsubishi Electric Research Labs) y Michael Jones
(Compaq CRL) publicaron por primera vez un sistema capaz de detectar rostros con un coste
computacional muy bajo.
Dicho sistema alcanza tasas de detección muy elevadas (99,9%) y una tasa de falsos positivos
bastante baja (33,3%). Por si fuera poco, dichos resultados se obtienen sin necesidad de utilizar
información auxiliar, como puede ser el color de la piel, o la zona candidata a tener un rostro
en la imagen.
Por otro lado, es importante remarcar que el algoritmo no
trabaja directamente con la imagen de entrada, sino con una
representación de la misma, conocida como imagen integral,
que se obtiene mediante unas pocas operaciones por pixel.
Estas transformaciones facilitan mucho la posterior búsqueda
de características en la imagen, puesto que trabajar con dicha
imagen reduce el coste computacional considerablemente.
Para determinar si en una imagen se encuentra un rostro o no,
el algoritmo divide la imagen integral en regiones de tamaño
variable y aplica un conjunto de clasificadores (etapas), cada
uno con un conjunto de características visuales.
Este tipo de clasificación es denominada clasificación en
cascada. En cada etapa se determina si la subregión es un
rostro o no. Si la subregión es aceptada como rostro entonces
es evaluada por la siguiente etapa (más rigurosa) y si no es
discriminada.
La clasificación en cascada garantiza la discriminación rápida de subregiones que no sean un
rostro. Esto significa un ahorro considerable de tiempo, pues no se procesarán innecesariamente
subregiones de la imagen que no contengan un rostro y únicamente se invertirá tiempo en
aquellas subregiones que posiblemente sí lo contengan.
2.2.1 Imagen Integral
La imagen integral es una nueva representación de la imagen introducida por Viola & Jones en
2004 para evitar cálculos redundantes y hacer más eficiente el proceso de extracción de
características.
Dicha imagen, en el punto (x,y) contiene la suma de los píxeles situados a la izquierda y encima:
𝑖𝑖(𝑥, 𝑦) = ∑ 𝑖(𝑥′, 𝑦)
𝑥′≤𝑥,𝑦′≤𝑦
Donde ii(x, y) es la imagen integral e i(x’, y’) es la imagen original.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
30
La imagen integral puede ser calculada eficientemente y
mediante una única pasada gracias a las siguientes
recurrencias:
𝑠(𝑥, 𝑦) = 𝑠(𝑥, 𝑦 − 1) + 𝑖(𝑥, 𝑦)
𝑖𝑖(𝑥, 𝑦) = 𝑖𝑖(𝑥 − 1, 𝑦) + 𝑠(𝑥, 𝑦)
Donde s(x,y) es la suma acumulada de la fila, s(x,-1) = 0,
e ii(-1,y) = 0
A modo de ejemplo, si la matriz de la izquierda fuera una imagen, la matriz de la derecha
representaría su imagen integral:
1 1 1 1 2 3
1 1 1
2 4 6
1 1 1 3 6 9
Otra característica interesante de la imagen integral es que podemos obtener la suma de un
rectángulo a partir de las referencias de sus esquinas:
Así pues, la suma de los píxeles dentro del rectángulo D puede ser calculada a partir de los
puntos 1, 2, 3 y 4.
El punto 1 es la suma de los píxeles del rectángulo A.
El valor del punto 2 acumula la suma de los rectángulos A + B.
De manera análoga, el punto 3 acumula la suma de los rectángulos A + C.
Así pues, la suma del rectángulo D puede ser calculada como la suma en el punto 1 y 4 menos
la suma del punto 2 y 3.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
31
2.2.2 Extracción de características
El algoritmo de Viola & Jones se basa en la extracción de características simples.
El principal motivo para utilizar características simples es que el sistema puede entrenarse para
adquirir un conocimiento que es difícil de aprender utilizando una cantidad de datos finita.
Además, un sistema basado en características funciona mucho más rápido que uno basado en
píxeles.
Las características de cada imagen se extraen al aplicar funciones que permiten la
representación de los objetos de interés de la imagen. En el algoritmo de Viola & Jones, la
extracción de características se realiza aplicando a la imagen las transformadas de Haar.
Dichas transformadas se forman a partir de ventanas que se dividen en regiones del mismo
tamaño y forma. Estas regiones pueden ser adyacentes tanto verticalmente como
horizontalmente.
Los píxeles dentro de los límites de los rectángulos blancos se restan de la suma de los píxeles
dentro de los límites de las regiones grises.
En el caso del algoritmo de Viola & Jones se hace uso de tres tipos de funciones en forma de
rectángulos:
El valor de una transformación con 2
rectángulos se calcula como la
diferencia entre la suma de los píxeles
dentro de las dos regiones rectangulares
(Figura A y B).
El valor de una transformación con 3
rectángulos se calcula como la suma de
los dos rectángulos de fuera y ese valor
se resta de la suma de píxeles obtenida
en el rectángulo del centro (Figura C).
El valor de una transformación con 4 rectángulos se calcula como la diferencia entre
pares diagonales de rectángulos (Figura D).
Otra característica importante es que estas transformaciones pueden ser modificadas tanto en
escala como en orientación.
Al convolucionar las transformaciones de Haar sobre una imagen, permite obtener
características de contornos, puntos y líneas sobre la imagen integral.
Gracias a la imagen integral, estas características pueden extraerse en tiempo constante, tal y
como se mostró en el apartado anterior.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
32
2.2.3 AdaBoost
Llegados a este punto, tenemos gran cantidad de características asociadas a las diferentes
transformaciones de Haar. A pesar de calcular estas características de forma muy eficiente, no
es posible aplicar todas las transformaciones sobre una imagen.
No obstante, podríamos encontrar un pequeño grupo de características que, en conjunto sean
un clasificador muy eficaz. El problema, pues, recae en cómo encontrar el grupo de
características que definen el clasificador.
Para que un clasificador sea efectivo y preciso debe cumplir las siguientes condiciones:
Debe haber sido entrenado con suficientes datos
Debe tener un ratio de errores bajos
Debe ser simple
Para ello, Viola & Jones utilizaron un algoritmo llamado AdaBoost (contracción de Adaptative
Boosting). El término de Boosting fue introducido en 1995 por Schapire y Freund y hace
referencia a un tipo de algoritmos cuya finalidad es encontrar una hipótesis compleja (o fuerte
a partir de hipótesis simples (o débiles).
La principal diferencia de AdaBoost y su predecesor es que éste es adaptativo puesto que
propone entrenar a los clasificadores de forma iterativa, de forma que cada nuevo clasificador
se focalice en los datos que se clasificaron de forma errónea. De esta forma, el algoritmo se
“adapta” para obtener mejores resultados.
La siguiente imagen muestra un ejemplo de cómo el algoritmo de AdaBoost sigue para formar
un clasificador final.
En este caso se tiene una muestra de símbolos “+” (en azul) y símbolos “-” (en rojo).
En el primer intento, el clasificador propone una clasificación tratando de separar los datos pero
realiza errores (deja datos positivos fuera del conjunto), por lo que el peso de estos datos es
incrementado para dar más importancia a resolver bien estos puntos.
En el segundo intento, se observa que se logra discriminar correctamente los datos positivos
que tenían más peso. Por el contrario, podemos observar que el clasificador vuelve a cometer
errores (deja datos negativos dentro del conjunto), por lo que el peso de estos datos también es
incrementado para tenerlos en cuenta en las siguientes iteraciones.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
33
En el tercer intento, se procede del mismo modo para intentar resolver el problema. El
clasificador también comente errores, pero esta vez, a diferencia de las anteriores, se produce
con elementos que los anteriores clasificadores habían conseguido separar correctamente.
Al no haber ningún punto pendiente de clasificar correctamente, se suman todos los
clasificadores creados, formando un clasificador fuerte que, teóricamente, debería ser mejor
que cada clasificador por separado
A continuación se muestra el pseudocódigo del algoritmo de AdaBoost utilizado por Viola &
Jones:
Dadas imágenes de ejemplo (xi, yi),…, (xn, yn), donde yi = {0, 1} para ejemplos negativos
y positivos respectivamente.
Se inicializan los pesos w1,i = 1
2𝑚 , 1
2𝑙 , donde m y l son el número de ejemplos positivos
y negativos respectivamente.
Para t = 1,…,T.
1) Normalizar los pesos: wt,i wt,i
∑ wt,j𝑛𝑗=1
, donde wt,i es una distribución de
probabilidad.
2) Para cada característica j, entrenar un clasificador hj. El error es evaluado
respecto a wt, εj = ∑ 𝑤𝑖|𝑖 ℎ𝑗(𝑥𝑖) − 𝑦𝑖|
3) Escoger un clasificador débil, hj, con el menor εt
4) Actualizar los pesos: 𝑤𝑡+1,𝑖 = 𝑤𝑡,𝑖𝛽𝑡1−𝑒𝑖
Donde 𝑒𝑖= 0 si 𝑥𝑖 se clasifica correctamente.
En caso contrario, 𝑒𝑖= 1 y 𝛽𝑡 =εt
1−εt
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
34
El clasificador fuerte obtenido es:
ℎ(𝑥) = {1 𝑠𝑖 ∑ 𝛼𝑡ℎ𝑡(𝑥) ≥
1
2𝑇𝑡=1 ∑ 𝛼𝑡
𝑇𝑡=1
0 𝑒𝑛 𝑐𝑢𝑎𝑙𝑞𝑢𝑖𝑒𝑟 𝑜𝑡𝑟𝑜 𝑐𝑎𝑠𝑜 donde 𝛼𝑡 = log
1
𝛽𝑡
2.2.4 Clasificador en cascada
Con el fin de poder descartar rápidamente regiones no importantes de una imagen, Viola y Jones
presentan un método para combinar los clasificadores fuertes, el cual llamaron clasificador en
cascada.
El diagrama muestra un ejemplo de un clasificador en cascada. Este clasificador se puede
representar como un árbol de decisión binario.
Para garantizar el rendimiento, el primer clasificador tiene que ser muy simple y efectivo,
puesto que le llegarán todas las ventanas y su objetivo será eliminar el máximo número de
muestras negativas.
Un resultado positivo en el primer clasificador activa el segundo clasificador, el cual será más
complejo que el primero y estará ajustado a alcanzar tasas de detección mayores.
Un resultado positivo en este segundo clasificador activará al siguiente y así sucesivamente.
Los siguientes clasificadores serán más complejos que los primeros puesto que su objetivo es
reducir el número de falsos positivos.
Aquellas muestras que hayan sido identificadas positivamente por todos los clasificadores serán
muestras candidatas a haber detectado una cara.
Para evaluar la eficiencia de este clasificador, Viola & Jones efectuaron una prueba donde se
comparó un clasificador fuerte y un clasificador en cascada. El clasificador fuerte comparaba
200 características y el clasificador en cascada contaba con 10 etapas de clasificadores de 20
características cada una. Las diferencias en precisión entre ambos clasificadores fueron
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
35
mínimas pero el clasificador en cascada finalizó su labor diez veces más rápido que el
clasificador fuerte.
El éxito del clasificador en cascada recae en que la mayoría de ventanas de características que
se procesarán en el clasificador no contienen ninguna cara, por lo que se deben rechazar. Así
pues, el clasificador en cascada rechazará la mayoría de ellas con los primeros clasificadores.
Para que el clasificador en cascada funcione correctamente, se requiere aplicar un algoritmo de
aprendizaje que ayude a seleccionar un clasificador eficiente. Para ello, Viola y Jones presentan
un algoritmo capaz de encontrar un clasificador óptimo, en base al número de etapas que tiene
el clasificador, el número de características que se utilizan en cada etapa y un ratio de aciertos
a alcanzar.
2.3 Imagen binaria y región de interés
Una imagen binaria no es más que una imagen en la que los píxeles
únicamente pueden tomar dos valores (0 y 1). Los colores que
acostumbran a utilizarse para representar esta imagen son el blanco y
el negro.
Para obtener una imagen binaria a partir de una imagen cualquiera es
necesario definir una función que agrupe los píxeles en un conjunto u
otro a partir de ciertas condiciones.
El objetivo de aplicar este tipo de transformaciones es aislar el fondo de una imagen de lo que
se considera la región de interés o área a procesar.
A este tipo de imágenes se les suele aplicar operadores booleanos (AND, OR, NOT o XOR)
para combinarlos con otras imágenes.
Otro punto destacable es que las imágenes binarias pierden la información referente al color,
por lo que ocupan menos y son mucho mas rápidas de procesar.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
36
2.4 Ruido y filtrado
Algunos dispositivos, debido a su arquitectura de hardware, pérdidas del sensor debido a
variaciones electromagnéticas, interferencias o saturación de los sensores, producen lo que se
conoce como ruido.
Estas interferencias en la imagen no son deseables puesto que pueden inducir a errores durante
el procesamiento de imágenes. Por otro lado, en algunas ocasiones es imposible trabajar
imágenes de alta calidad (aplicaciones en tiempo real) y, por ello, existen algunas técnicas de
filtrado que ayudan a mitigar este efecto. A continuación comentaremos algunas de ellas:
Promedio: Se puede realizar un promedio de los píxeles de dos frames para obtener una
imagen suavizada. Esta técnica se basa en la premisa de que el ruido se reparte
aleatoriamente por toda la imagen y es dificil que coincida siempre en una misma área
de la imagen.
La técnica en cuestión también se puede aplicar con una única imagen siempre y cuando
se promedien los píxeles con los píxelees vecinos.
Esta técnica funciona muy bien en imágenes en color y en escala de grises.
Desenfoque gaussiano: El desenfoque gaussiano consiste en
definir una función Gaussiana que se convolucionará por
toda la imagen para obtener una imagen más suave. Esta
imagen resultante será menos nítida puesto que los bordes
presentes en la imagen se ven afectados y produce un efecto
similar al de una cámara fotográfica desenfocada.
Aplicando un filtro de este tipo podemos llegar a difuminar
el ruido.
Operador Open: Este operador morfológico se aplica sobre imágenes binarias y está
contruido a partir de otros dos operadores morfológicos (erode y dilate) aplicados de
forma conjunta.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
37
El operador erode aplica una máscara sobre toda la imagen, la cual reduce el tamaño de
los bordes. Esta reducción del borde será directamente proporcional al tamaño de la
máscara que apliquemos.
En contraposición al operador erode, tenemos el operador dilate. El funcionamiento es
identico al anterior, solo que en vez de reducir un borde, lo amplia en función del tamaño
de la máscara que se aplique.
El objetivo de aplicar estos dos operadores de forma conjunta es, una vez más, eliminar
el ruido que se pueda encontrar en la imagen.
Tal y como podemos ver en la imagen, el operador erode hará desaparecer la mayoría
de los puntos blancos de la imagen, mientras que el operador dilate intentará restaurar,
en la medida de lo posible los efectos indeseados del operador erode (restaurará la
imagen).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
38
2.5 Centro de masas
Durante la propuesta de solución de este proyecto se observó la
necesidad de detectar dónde se ubicaban ciertas regiones de interés
respecto a la imagen.
En éste particular, se necesita saber en qué posición se encuentra la mano
para poder determinar qué movimiento se está realizando. El problema
surge en el momento en que hay que decidir cuál es la referencia a tomar
para obtener esta posición.
La referencia más sencilla de calcular, sin llevar a confusión o interpretación es el centro de
masa. Puesto que la representación de la mano viene dada por una imagen binaria, se puede
considerar que los pixeles del objeto que la representan tienen un peso unitario. Así pues, el
centro de masas, o centroide, será aquel punto (𝑥, 𝑦) del objeto para el cual hay la misma masa
en cualquier dirección (arriba, abajo, a la izquierda y a la derecha).
En este caso, dada una imagen binaria, el centro de masas se puede calcular mediante la
siguiente fórmula:
𝐶𝑒𝑛𝑡𝑟𝑜 𝑑𝑒 𝑚𝑎𝑠𝑎𝑠 𝑥 = ∑ 𝑐𝑜𝑜𝑟𝑑𝑒𝑛𝑎𝑑𝑎𝑠 𝑥 𝑑𝑒 𝑙𝑜𝑠 𝑝í𝑥𝑒𝑙𝑒𝑠
𝑁º 𝑑𝑒 𝑝í𝑥𝑒𝑙𝑒𝑠 𝑑𝑒𝑙 𝑜𝑏𝑗𝑒𝑡𝑜
𝐶𝑒𝑛𝑡𝑟𝑜 𝑑𝑒 𝑚𝑎𝑠𝑎𝑠 𝑦 = ∑ 𝑐𝑜𝑜𝑟𝑑𝑒𝑛𝑎𝑑𝑎𝑠 𝑦 𝑑𝑒 𝑙𝑜𝑠 𝑝í𝑥𝑒𝑙𝑒𝑠
𝑁º 𝑑𝑒 𝑝í𝑥𝑒𝑙𝑒𝑠 𝑑𝑒𝑙 𝑜𝑏𝑗𝑒𝑡𝑜
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
39
2.6 Dynamic Time Warping
Si tenemos dos series de tiempo:
𝐴 = 𝑎1, 𝑎2, … , 𝑎𝑛
𝐵 = 𝑏1, 𝑏2, … , 𝑏𝑚
Una forma sencilla de medir la similitud entre ambas series sería a través de la fórmula de la
distancia:
𝑑(𝐴, 𝐵) = √∑(𝑎𝑖 − 𝑏𝑖)2𝑖=𝑛
𝑖=1
ó 𝑏𝑖𝑒𝑛 𝑑(𝐴, 𝐵) = √∑|𝑎𝑖 − 𝑏𝑖|
𝑖=𝑛
𝑖=1
𝑑𝑜𝑛𝑑𝑒 𝑛 = 𝑚
El primer problema que encontraríamos es que nos sería imposible comparar series de tiempo
de distinto tamaño (𝑛 ≠ 𝑚). A pesar de este contratiempo, incluso en el caso de tener series
temporales del mismo tamaño, rápidamente detectaríamos que nos sería muy difícil medir la
similitud debido a que las series temporales son muy sensibles a variaciones sobre el eje del
tiempo.
Este hecho se puede observar fácilmente si intentamos medir la similitud entre dos señales que
son idénticas salvo por el hecho de que una está desplazada en el tiempo:
Distancia euclidiana
Dynamic Time Warping
Gráficamente se puede observar que no se pueden comparar series temporales únicamente
aplicando la fórmula euclidiana por la característica de alinear las series temporales punto a
punto.
Así pues, obtener un algoritmo que nos mida la similitud entre series temporales requiere un
alineamiento no lineal.
En 1978, Hiroaki Sakoe y Seibi Chiva, introdujeron las bases de lo que hoy día se conoce como
Dynamic Time Warping en el marco de la resolución de problemas vinculados al
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
40
reconocimiento de voz, aunque posteriormente se fue ampliando su aplicación a otras muchas
áreas.
Dynamic Time Warping (DTW) es un algoritmo utilizado para medir la similitud entre dos
secuencias que pueden variar en el tiempo o la velocidad.
2.6.1 Definición Dynamic Time Warping
Dadas dos series temporales A y B, de largo I y J respectivamente:
𝐴 = 𝑎1, 𝑎2, … , 𝑎𝑖, … , 𝑎𝐼
𝐵 = 𝑏1, 𝑏2, … , 𝑏𝑗, … , 𝑏𝐽
podemos definir F como una serie de trayectorias que alinean los índices de ambas series:
𝐹 = 𝑐1, 𝑐2, … , 𝑐𝑘, … , 𝑐𝐾 𝑑𝑜𝑛𝑑𝑒 máx(𝐼, 𝐽) ≤ 𝐾 < 𝐼 + 𝐽
Una vez alineados los puntos de ambas series, podemos definir la función distancia como la
distancia entre los valores de las series que han sido alineados:
𝑑(𝑐𝑘) = 𝑑(𝑖𝑘, 𝑗𝑘) = ||𝑎𝑖𝑘 − 𝑏𝑗𝑘||
Así mismo, definimos la suma ponderada de las distancias como:
𝑆(𝐹) = ∑ 𝑑(𝑐𝑘)
𝑘=𝐾
𝑘=1
𝑤𝑘 donde 𝑤𝑘 ≥ 0
Con las anteriores expresiones podemos generar la definición de la medida de similitud del
Dynamic Time Warping:
𝐷𝑇𝑊(𝐴, 𝐵) = mín𝐹 {𝑆(𝐹)
∑ 𝑑(𝑐𝑘)𝑘=𝐾𝑘=1 𝑤𝑘
}
Nota: El denominador se introduce para mitigar efectos sobre la cantidad de puntos K
(Coeficiente de normalización).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
41
2.6.2 Complejidad y restricciones
Existe una serie de restricciones que se pueden aplicar a la series de trayectorias F con el fin de
acotar el número de cálculos a realizar por punto. Esto nos permite mejorar considerablemente
la velocidad de los algoritmos de DTW.
Condición de borde
𝑖1 = 1, 𝑗1 = 1, 𝑖𝐾 = 𝐼, 𝑗𝐾 = 𝐽
Mediante estas restricciones establecemos los límites de la matriz de costes
Condición de monotonía
𝑖𝑘−1 ≤ 𝑖𝑘 y 𝑗𝑘−1 ≤ 𝑗𝑘
Condición de continuidad
𝑖𝑘 − 𝑖𝑘−1 ≤ 1 y 𝑗𝑘 − 𝑗𝑘−1 ≤ 1
A consecuencia de estas condiciones, el punto 𝑐𝑘−1solamente puede tomar tres valores:
𝑐𝑘−1 = {
(𝑖𝑘, 𝑗𝑘 − 1)(𝑖𝑘 − 1, 𝑗𝑘 − 1)(𝑖𝑘 − 1, 𝑗𝑘)
}
Estos tres casos corresponden, respectivamente a un avance en el eje x sobre la matriz
de costes, un avance en el eje x e y sobre la matriz de costes, o bien, un avance en el eje
y sobre la matriz de costes.
En cualquier caso, estamos asegurando que avanzamos en uno de los ejes.
Condición de ajuste de ventana
Sakoe-Chiva propusieron inicialmente la siguiente condición de ajuste de ventana:
|𝑖𝑘 − 𝑗𝑘| ≤ 𝑟 donde 𝑟 es un entero positivo
No obstante, existen otras ventanas que también son aplicadas con frecuencia. Una de
las más populares es el Paralelogramo de Itakura.
Estas restricciones aceleran el algoritmo considerablemente puesto que no se calcula
toda la matriz de costes, sino que únicamente se calculan los elementos correspondientes
a las zonas sombreadas.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
42
Estas restricciones provocan que la trayectoria y el resultado del algoritmo de Dynamic
Time Warping no sean óptimos.
Condición sobre la pendiente
Con el fin de evitar que un tramo corto de una de las series se corresponda con un tramo
largo de la otra serie, se establece la siguiente condición de que si el punto 𝑐𝑘 se mueve
m veces consecutivas sobre uno de los ejes, deberá moverse, como mínimo n veces en
la dirección diagonal, antes de volver a moverse en la misma dirección.
La forma para medir esta restricción es el parámetro
𝑝 = 𝑛 𝑚⁄
Así pues, cuanto mayor es p, mayor es la restricción.
A la izquierda: Banda de Sakoe-Chiba. A la derecha: Paralelogramo de Itakura
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
43
2.6.3 Cálculo de los coeficientes
A continuación se exponen dos formas de calcular los coeficientes de ponderación, basadas en
la restricción de continuidad descrita en el apartado anterior. Los cálculos que se exponen a
continuación pueden calcularse de forma sencilla mediante algoritmos de programación
dinámica.
Forma simétrica
𝑤𝑘 ≝ (𝑖𝑘 − 𝑖𝑘−1) + (𝑗𝑘 − 𝑗𝑘−1) ⇒𝑁 = 𝐼 + 𝐽
y se cumple que,
𝑐𝑘−1 = {
(𝑖𝑘, 𝑗𝑘 − 1)(𝑖𝑘 − 1, 𝑗𝑘 − 1)(𝑖𝑘 − 1, 𝑗𝑘)
} ⇒𝑤𝑘 = {
121}
En este caso el cálculo de Dynamic Time Warping es simétrico:
𝐷𝑇𝑊(𝐴, 𝐵) = 𝐷𝑇𝑊(𝐵, 𝐴)
Forma asimétrica
𝑤𝑘 = 𝑖𝑘 − 𝑖𝑘−1 ⇒𝑁 = 𝐼 ó 𝑤𝑘 = 𝑗𝑘 − 𝑗𝑘−1
⇒𝑁 = 𝐼
y se cumple que,
𝑐𝑘−1 = {
(𝑖𝑘, 𝑗𝑘 − 1)
(𝑖𝑘 − 1, 𝑗𝑘 − 1)(𝑖𝑘 − 1, 𝑗𝑘)
} ⇒𝑤𝑘 = {
011}
En este caso el cálculo de Dynamic Time Warping no es simétrico:
𝐷𝑇𝑊(𝐴, 𝐵) ≠ 𝐷𝑇𝑊(𝐵, 𝐴)
2.6.4 Complejidad
La complejidad del algoritmo es O(I x J) puesto que se debe llenar toda la matriz de costes. En
el caso particular en que I = J, la complejidad es O(I2). La complejidad cuadrática puede ser un
problema para series muy largas.
Otro punto importante a destacar es que en la mayoría de aplicaciones tenemos un conjunto de
n series y es imprescindible calcular el algoritmo de Dynamic Time Warping para todas ellas.
En estos casos la complejidad pasa a ser O(I2 x n2), por lo que es inevitable aplicar restricciones
que permitan acelerar los cálculos.
En el caso que no sea necesario encontrar la trayectoria óptima, gracias a las condiciones y
restricciones descritas en el apartado 2.6.2, se puede llegar a reducir el coste computacional
considerablemente (por ejemplo al aplicar las Bandas de Sakoe-Chiba o el paralelogramo de
Itakura), obteniendo un coste computacional cuadrático, pero reduciendo notablemente el
tamaño de I.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
44
2.6.5 Fast DTW
En 2004, S. Stan, P. Chan proponen el algoritmo de Fast DTW como una mejora del algoritmo
de DTW. El algoritmo propuesto es un algoritmo multinivel basado en tres puntos clave:
Reducción: Una serie de tiempo se convierte en una más pequeña que representa los
mismos datos con la mayor precisión posible y el menor tamaño.
Esta característica se consigue combinando una celda de la matriz con sus adyacentes.
El proceso se repite varias veces, obteniendo diferentes representaciones de los datos
para las distintas resoluciones.
Cada una de estas representaciones es dos veces menor que la representación anterior.
Proyección: Se encuentra un camino de distancia mínima en la resolución menor y se
utiliza como estimación inicial para calcular el camino en resoluciones superiores.
Esto determinará qué celdas deberán ser calculadas en la siguiente evaluación con la
representación de mayor resolución. Esto es especialmente importante puesto que la
matriz de costes sólo se rellena para estas celdas.
Este principio hace que el coste de esta aproximación tienda a O(N) puesto que el
tamaño del camino crece linealmente con el tamaño de la entrada de datos. Esto supone
una mejora sustancial en el rendimiento respecto el algoritmo clásico de Dynamic Time
Warping.
Refinamiento: Al utilizar como estimación inicial el camino en resoluciones superiores
nos aseguramos que estamos calculando una solución óptima para nuestro problema
local. No obstante, la solución óptima global puede no estar contenida dentro de nuestra
estimación inicial. Por ello, para refinar la solución se define como parámetro un radio
que indicará el número de celdas adicionales a añadir por cada lado del camino
proyectado a partir de resoluciones más bajas y ajustes locales.
A continuación se muestra una imagen que pretende mostrar cómo funciona la representación
multinivel:
A nivel computacional podemos ver que el algoritmo de FastDTW ha evaluado un total de 164
celdas (4 + 16 + 44 + 100), mientras que el algoritmo clásico de Dynamic Time Warping debe
evaluar 235 celdas (162).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
45
Esta variación puede parecer pequeña pero puede llegar a ser considerable para series de mayor
tamaño tal y como se pueden ver en las siguientes gráficas:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
46
3. Definición de los movimientos a detectar
Como requisito del proyecto se establece que el programa debe ser capaz de detectar un
conjunto de seis movimientos.
Tras analizar las diferentes posibilidades existentes, se observa que los movimientos a definir
en el conjunto deben describirse dentro de un plano. Esto se debe a que con una captura de
imagen no se puede describir un movimiento en tres dimensiones (como mínimo se necesitan
dos imágenes para poder aplicar técnicas de stereo motion o stereo vision).
Otro punto interesante a tener en cuenta es que los movimientos sean suficientemente diferentes
entre sí. Esto hace que sea más sencillo detectarlos y distinguirlos y, a su vez, dota al sistema
de una variedad más rica de movimientos. Este punto, a priori, no es relevante, pero de cara a
futuras aplicaciones del sistema, aporta gran valor añadido.
Tras las premisas anteriormente mencionadas, se determina que el conjunto de movimientos
está formado por los movimientos de dirección “arriba”, “abajo”, “izquierda”, “derecha”, un
movimiento circular y un movimiento de saludo.
Puesto que un usuario puede ir concatenando diferentes movimientos, se establece la restricción
de que los movimientos deben iniciar y finalizar en un mismo punto. Este hecho hace que todos
ellos partan de un origen común y no llegue a darse el caso de que el usuario se sale del campo
de visibilidad de la cámara tras sucesivos movimientos, por ejemplo, hacia la derecha.
3.1 Inicio y fin de movimiento
Otro de los puntos que se debe definir en lo que respecta a los movimientos es la detección del
inicio y fin de un movimiento.
Tal y como se indicaba anteriormente, puesto que el usuario va a concatenar múltiples
movimientos, el sistema debe ser capaz de discriminar y detectar cada uno de los movimientos.
Para facilitar esta tarea, se establece como premisa que un movimiento se inicia cuando se
detecta un movimiento significativo de la mano en escena. Así mismo, un movimiento finaliza
cuando se deja de detectar movimiento significativo en la escena.
Entenderemos como movimiento significativo, un movimiento de la mano que suponga una
variación de su posición en píxeles.
Entenderemos que se deja de detectar movimiento significativo de la mano cuando en un
período de 12 frames (medio segundo) no se detecte un movimiento de la mano que suponga
una variación de su posición en píxeles.
Gracias a estas premisas el sistema será capaz de discriminar los movimientos.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
47
3.2 Conjunto de movimientos a detectar
A continuación se definen los movimientos que el programa es capaz de reconocer:
3.2.1 Movimiento hacia arriba
Se trata de un movimiento básico, en dos pasos, en el que el usuario mueve la mano
verticalmente y hacia arriba, desde el punto inicial y, sin pausa, mueve la mano verticalmente
y hacia abajo hasta, aproximadamente, el punto inicial.
3.2.2 Movimiento hacia abajo
Este movimiento es el mismo movimiento descrito anteriormente pero en sentido opuesto. El
usuario mueve la mano verticalmente y hacia abajo desde el punto inicial y, sin pausa, mueve
la mano verticalmente y hacia arriba hasta, aproximadamente, el punto inicial.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
48
3.2.3 Movimiento hacia la derecha
Se trata de un movimiento básico, en dos pasos, en el que el usuario mueve la mano
horizontalmente hacia la derecha, desde el punto inicial y, sin pausa, mueve la mano
horizontalmente hacia la izquierda hasta, aproximadamente, el punto inicial.
3.2.4 Movimiento hacia la izquierda
Este movimiento es el mismo movimiento descrito anteriormente pero en sentido opuesto. El
usuario mueve la mano horizontalmente hacia la izquierda desde el punto inicial y, sin pausa,
mueve la mano horizontalmente hacia la derecha hasta, aproximadamente, el punto inicial.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
49
3.2.5 Movimiento circular
Se trata de un movimiento en cuatro pasos, en el que el usuario mueve la mano en forma circular
y en sentido de las agujas del reloj (sentido horario). El punto de inicio y fin se establece,
aproximadamente en la posición de las “9 horas”.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
50
3.2.6 Movimiento de saludo
Se trata de un movimiento en dos pasos, en el que el usuario mueve la mano horizontalmente
hacia la derecha, desde el punto inicial y, sin pausa, mueve la mano horizontalmente hacia la
izquierda hasta, aproximadamente, el punto inicial.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
51
4. Implementación
Tan importante como definir el proyecto es explicar cómo se ha preparado la plataforma de
desarrollo, cuáles son sus principales características, cuál es el motivo que ha llevado a elegir
ciertas librerías y un largo etcétera.
En los siguientes apartados se detallarán las diferentes decisiones que han tomado durante la
consecución del proyecto.
4.1 Plataforma de desarrollo
Para llevar a cabo este proyecto se ha tenido que preparar un entorno de desarrollo con ciertas
características técnicas. Así mismo, del amplio catálogo de librerías que existen en el mercado,
se han utilizado ciertas librerías con funcionalidades ya desarrolladas por terceros.
A continuación se desglosarán los puntos más importantes que se han evaluado en el momento
de preparar el entorno de desarrollo.
4.1.1 Entorno de desarrollo
Al no haberse fijado ningún requisito técnico, ni funcional, que establezca una plataforma
específica de trabajo, se va a realizar el desarrollo utilizando el portátil que dispongo en casa.
Las características técnicas del mismo son bastante modestas:
CPU: Intel® Core™2 Duo P8400 @ 2.26GHz.
Memoria: 4GB DDR3 RAM.
GPU: NVIDIA GeForce 9300M GS 256MB DDR3 RAM.
Cámara: Color CMOS progresiva de 370,000 pixeles (310,000 efectivos),
capturando a 80×60, 160×120, 320×240, 640×480, 176×144 o 352×288 con una
frecuencia de hasta 30 frames por segundo.
SO: Windows 10 Professional 64b.
4.1.2 Librería de visión por computador
Puesto que el propósito de este proyecto no es el de realizar y codificar una nueva librería de
visión por computador, no vamos a caer en la trampa de "rehacer la rueda" y aprovecharemos
alguna de las librerías existentes en el mercado para este propósito.
Actualmente existe una extensa oferta de librerías que ya tienen la mayoría (o la totalidad) de
los algoritmos de visión por computador que se necesitan para desarrollar este proyecto.
Además, la gran parte de las librerías existentes van respaldadas por una gran comunidad de
desarrolladores que corrigen y mejoran la eficiencia de dichos algoritmos.
Al tratarse de un proyecto académico, se han descartado todas aquellas soluciones de mercado
que requieren pago de licencias. Tras realizar dicha criba, se ha realizado una segunda criba
para seleccionar aquellas librerías que dan un soporte multiplataforma.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
52
A pesar de estas restricciones, internet ofrece una amplia variedad de librerías de visión por
computador:
OpenCV
VXL
LTI-Lib
OpenVIDIA
RAVL
Camelia
Vigra
Tuwo
BLEPO
Tlib
EmbedCV
Blobdetection
Flob
GPUCV
Torch3Vision
AAM-API
MPT
NMPT
viiteid
Al haber tal variedad, se buscó por Internet comparativas de rendimiento entre las diferentes
librerías, encontrando una en la que se analizaban las librerías VXL, LTI y OpenCV.
En esta comparativa se contrastaba el rendimiento de las tres librerías ante 4 operaciones:
Transformada de Fourier
Redimensionado de imagen
Flujo Óptico
Prueba de estrés “champiñón” de FANN
Todas estas pruebas se realizan con el mismo hardware e imágenes.
De acuerdo con la gráfica anterior, se puede observar que OpenCV tarda menos que las otras
librerías comparadas durante las pruebas.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
53
Estos resultados seguidos de la cantidad de documentación que existe tanto en libros como en
Internet, me hizo elegir a OpenCV como la librería de visión por computador a utilizar en este
proyecto.
4.1.2.1 OpenCV
OpenCV (Open Source Computer Vision Library) es una librería open
source que contiene algoritmos de visión por computador y de inteligencia
artificial (aprendizaje automático). OpenCV fue originalmente diseñada por
Intel para proporcionar una solución para aplicaciones de visión por
computador y acelerar su uso en aplicaciones comerciales.
Actualmente, esta librería cuenta con más de 2500 algoritmos optimizados, abarcando un
amplio conjunto de algoritmos clásicos de visión por computador y algoritmos de aprendizaje
automático, así como, un gran conjunto de algoritmos de última generación.
Estos algoritmos se pueden utilizar para detectar y reconocer caras, objetos y escenas, clasificar
acciones humanas, realizar seguimiento de objetos y ojos, extraer modelos 3D, establecer
marcadores para realidad aumentada y un largo etcétera.
OpenCV tiene detrás una comunidad de más de 47000 usuarios y más de 7 millones de
descargas. Esta librería se utiliza para aplicaciones comerciales en empresas como Google,
Yahoo, Microsoft, Intel, IBM, Sony, Honda, Toyota y múltiples Startups. También es
ampliamente respaldada por grupos de investigación y organismos gubernamentales.
OpenCV ha sido desarrollado en C++, aunque también dispone de interfaces para C, Python,
Java y MATLAB® y es compatible con Windows, Linux, Android y Mac OS. En caso de estar
disponibles, OpenCV saca partido de instrucciones MMX y SSE. Ahora mismo se están
desarrollando interfaces completamente integradas con OpenCL y CUDA.
4.1.3 Librería de aprendizaje por computador
Igual que sucedía con las librerías de visión por computador, el propósito de este proyecto no
es crear algoritmos de Dynamic Time Warping. Por ello, se decide utilizar alguna librería que
implemente este algoritmo.
A diferencia de lo que ocurre con las librerías de visión por computador, no hay abundancia de
librerías de aprendizaje en Java. Tras realizar una amplia búsqueda, únicamente se encontró la
librería Java-ML (Java Machine Learning), la cual todavía se encuentra en fase beta (Java-ML
release 0.17).
A pesar de encontrarse en fase beta, esta librería dispone de múltiples algoritmos de minería de
datos, clustering y clasificación.
Por lo que respecta a nuestros intereses, esta librería dispone de un algoritmo de Dynamic Time
Warping y de Fast Dynamic Time Warping totalmente operativos y con una breve
documentación de la API.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
54
4.1.4 Lenguaje de programación
Aunque la librería está desarrollada en C++, OpenCV nos proporciona un gran abanico de
posibilidades a la hora de programar (C, C++, Java, Python) e incluso ofrece también
integración con MATLAB®.
Ante este abanico de posibilidades, se han evaluado pros y contras de cada lenguaje de
programación, lo cual ha llevado a escoger Java como lenguaje de programación.
A continuación se detallan las características de este lenguaje basándose en las premisas del
proyecto:
4.1.4.1 Java
Java es un lenguaje de programación de propósito general, concurrente y
orientado a objetos, que fue diseñado específicamente para tener tan pocas
dependencias de implementación como fuera posible.
Uno de sus objetivos es permitir que los desarrolladores de aplicaciones
escriban el programa una única vez y lo ejecuten en cualquier dispositivo (característica
conocida en inglés como WORA, o “Write Once, Run Anywhere”), lo que quiere decir que, el
código que es ejecutado en una plataforma no tiene que ser recompilado para ejecutarse en otra,
sin importar la arquitectura del procesador subyacente. Este objetivo se consigue gracias a la
máquina virtual de Java (JVM).
Desventajas
Uno de los puntos más conflictivos a la hora de tomar esta decisión era si el wrapper
que proporciona OpenCV pudiese producir inestabilidad o ralentización del software
debido a una penalización muy grande en el rendimiento.
Tras revisar la documentación de OpenCV, se observa que su wrapper está
completamente integrado con las cabeceras de C++ gracias al JNI, y sus definiciones
son prácticamente idénticas a las de C++, lo cual garantiza que las rutinas estén
actualizadas y evita la inestabilidad.
En cuanto al rendimiento, se asume que hay una pequeña penalización por utilizar el
wrapper. No obstante, a pesar de codificar en Java, la librería realmente está ejecutando
el código nativo escrito en C++. Por lo tanto, los algoritmos ejecutados mediante
wrapper son tan rápidos como los algoritmos nativos en C++.
Por otro lado, se ha observado que el wrapper limita la característica WORA que
proporciona Java (el programa solo podrá ejecutarse en los sistemas para los que la
librería OpenCV está diseñada). A pesar de esto, puesto que OpenCV es compatible con
la mayoría de sistemas operativos (Windows, Linux, IOS y Android), este punto queda,
en gran medida, mitigado.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
55
Beneficios
El código Java es muy refactorizable puesto que se pueden renombrar variables, extraer
funciones y clases, y aplicar nuevas funcionalidades con facilidad y sin perder la
estructura de nuestro diseño de software.
Además, Java impide al usuario realizar accesos a posiciones de memoria de forma
descontrolada por lo que no se puede trabajar con punteros de forma explícita.
Otra característica interesante es el Garbage Collector. Mediante esta funcionalidad
aseguramos que no quedan elementos sin referenciar en memoria, que puedan producir
inestabilidad en el sistema o un consumo innecesario de la misma.
Estas propiedades hacen que el código que se genere sea robusto y fiable y se reduce en
gran medida el tiempo de desarrollo e implementación.
Por otro lado, Java está íntimamente ligado al desarrollo de aplicaciones Android. Estas
aplicaciones han sufrido un boom en los últimos años gracias a los Smartphones. Estos
dispositivos están presentes en, prácticamente, todos los hogares, por lo que, desarrollar
el software en esta plataforma es especialmente atractivo para garantizar la portabilidad
a estos terminales.
Por último, dada la experiencia laboral obtenida en los últimos años con Java y en el
desarrollo de programas con este lenguaje de programación, hace que el software a
implementar sea más robusto que en C++.
4.1.4.2 JDK & JVM 1.8
Puesto que la librería no establece ningún requisito en cuanto a
versión de JDK, finalmente se ha optado por el JDK 1.8.
Esta versión de JDK es la última versión que pone a disposición
Oracle y, aunque no se utiliza para este proyecto, esta versión de
java es totalmente compatible con la versión 2.0 de JavaFX.
Esta herramienta permite a los desarrolladores, entre otras cosas, crear aplicaciones RIA (Rich
Internet Applications) que combinan el aprovechamiento de las funciones de escritorio (cortar,
pegar, redimensionar,…) con el alcance, la flexibilidad de presentación y el despliegue de las
páginas Web, y lo mejor en multimedia (voz, video).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
56
4.1.5 Eclipse
Como entorno de desarrollo se utilizará eclipse Mars. Esta versión de la
herramienta es totalmente gratuita y es la última que hay disponible en la web
de Oracle.
Eclipse dispone de un editor de texto con un analizador sintáctico. La
compilación del código es en tiempo real. Se puede configurar con módulos JUnit para la
realización de pruebas unitarias, CVS o SVN para configurar controles de versiones, y dispone
de integración con Ant y Maven, asistentes para la creación de proyectos, clases, pruebas y un
largo etcétera.
Con el fin de facilitar el desarrollo de pantallas con JavaFX, se ha instalado el plugin e(fx)clipse.
Este plugin nos permitirá crear nuevos proyectos JavaFX, arrancar el Scene Builder desde la
IDE de eclipse y ejecutar aplicaciones de prueba.
Remarcar que, en el momento de realizar la elección del entorno de desarrollo, también se
podría haber escogido como entorno de desarrollo Netbeans. No obstante, he escogido eclipse
por estar más familiarizado con esta herramienta.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
57
4.2 Detalles de implementación
Del mismo modo que se han tomado decisiones de peso a la hora de montar el entorno de
desarrollo, se han tenido que tomar ciertas decisiones al codificar.
Estas decisiones han venido dadas por diferentes causas, ya sea por peculiaridades de las
librerías de terceros, por mejoras de rendimiento o bien por los resultados obtenidos a medida
que se desarrollaba el proyecto.
A continuación se desglosarán los puntos más importantes que se han evaluado en el momento
de preparar el entorno de desarrollo.
4.2.1 Obtención de imágenes
OpenCV es una librería de visión por computador muy completa. Además de tener
implementadas multitud de funciones para realizar tratamiento de imágenes, nos proporciona
una capa entre el Sistema Operativo y nuestro programa que permite obtener imágenes de
cualquier webcam que esté instalada en nuestro Sistema Operativo.
Para realizar esta captura de imágenes, debemos asegurar que tenemos cargadas las librerías de
OpenCV. Dicha carga se realiza mediante el siguiente comando:
//Cargamos las librerias de OpenCV
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Una vez cargadas las librerías, OpenCV proporciona una clase Java llamada VideoCapture que
encapsula todas las funcionalidades relacionadas con la captura de imágenes.
Una de las funciones más relevantes es la función open. Dicha función es la que activa la
webcam de nuestro sistema para realizar la captura de imágenes.
En nuestro caso, al tener únicamente conectada una cámara web, se decidió obtener, por
defecto, imágenes de la primera webcam que exista en el dispositivo (en nuestro caso es la
webcam integrada en el monitor del portátil). Esta captura se hace mediante la siguiente
función:
VideoCapture captura = null;
captura = new VideoCapture();
//Siempre capturamos de la Webcam por defecto
captura.open(0);
Un punto muy importante a destacar es que OpenCV obtendrá imágenes en el formato que
tengamos asignado por defecto en nuestro Sistema Operativo (en el caso del entorno de trabajo
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
58
en el que se ha desarrollado el proyecto, estaba preestablecido un formato de 640×480 píxeles
por imagen).
Tal y como se pudo observar durante la consecución del proyecto, este punto es crítico para el
rendimiento de la aplicación, puesto que no se procesa a igual velocidad una imagen de 640x480
píxeles que una imagen de 320x240 píxeles (1/4 de tamaño).
Tanto es así que si se intentaba únicamente capturar imágenes a 640x480 píxeles de resolución,
el sistema requería de media 333ms para obtener una imagen. Rebajando la resolución a
320x240 píxeles, el sistema necesitaba poco más de 96 ms para obtener una captura de imagen.
Al no haber un requisito marcado en cuanto a tamaño de imagen, y puesto que el sistema que
se está construyendo no requiere mostrar ni trabajar con altas resoluciones, se decidió bajar la
resolución mediante código. Este cambio de resolución también está soportado por OpenCV, y
se puede implementar de forma dinámica mediante la siguiente pieza de código:
int FRAME_WIDTH = 320;
int FRAME_HEIGHT = 240;
captura.set(Videoio.CV_CAP_PROP_FRAME_WIDTH, FRAME_WIDTH);
captura.set(Videoio.CV_CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT);
Finalmente, otro punto crítico que se observó en el momento de capturar imágenes es que éstas
no podían capturarse y procesarse secuencialmente.
Si las imágenes se procesaban secuencialmente, el sistema podía procesar poco más de 4
imágenes por segundo (FPS). Esta tasa es muy pobre y obligaba a buscar una solución para
obtener tasas mucho más acordes a un sistema que debe procesar imágenes en tiempo real.
Por ello, tras investigar posibles soluciones, se observó que se podían ejecutar capturas de forma
periódica, sin necesidad de que las anteriores hubiesen acabado.
Esta funcionalidad nos la da la clase Timer de Java. Para hacerla funcionar se le debe indicar la
frecuencia con la que queremos que ejecute nuestra pieza de código. También permite controlar
si queremos que la ejecute con cierto retraso o inmediatamente tras transcurrir la frecuencia. En
nuestro caso, siempre ejecutaremos el código de forma inmediata:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
59
long framerate = 1000/30; //30 FPS
Timer timer = null;
timer = new Timer();
timer.schedule(new TimerTask()
{
public void run()
{
motor();
}
}, 0, framerate);
Esta solución requiere que se controlen los FPS que se pueden procesar en el sistema sin que el
sistema llegue a saturarse de threads hambrientos de CPU.
Destacar que la función motor es la función que aglutina todo el algoritmo de detección de
movimientos, desde su captura, hasta la última transformación de imágenes.
4.2.2 Imagen especular
Tras revisar las imágenes que se obtenían por la webcam integrada se observó que eran
imágenes especulares de la escena en cuestión. Esto hacía que cuando un usuario movía la mano
hacia la izquierda, en la imagen resultante la estaba moviendo a la derecha y viceversa.
Este comportamiento, aparte de ser extraño a la vista, producía que la detección de los
movimientos no fuese la esperada (ante un movimiento en el que se esperaba una detección a
derechas, detectaba una detección a izquierdas y viceversa).
Para corregirlo, existían dos posibilidades:
Intercambiar los patrones de detección de movimientos hacia la izquierda por los
patrones de detección hacia la derecha y, modificar la dirección del movimiento de
rotación en círculos.
Realizar una transformación especular una vez realizada la captura.
Por simplicidad y coherencia, se decidió aplicar la transformación especular, a pesar de que
implica realizar una operación adicional de bajo coste.
Esta transformación se realiza con el siguiente código:
Mat snap = new Mat();
captura.read(snap);
Core.flip(snap, frame, 1);
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
60
4.2.3 Algoritmo de Viola & Jones
El algoritmo de Viola & Jones para detectar caras viene eficientemente implementado en las
librerías de OpenCV.
Para que funcione correctamente debemos indicar cuál es la ruta en la cual se encuentran los
clasificadores de Haar que requiere el algoritmo Viola & Jones para funcionar:
String RUTA_CLASIFICADOR =
"D:/PFC/Software/OpenCV3.1/opencv/build/etc/lbpcascades/lbpcascade_frontalf
ace.xml";
CascadeClassifier faceDetector = null;
faceDetector = new CascadeClassifier(RUTA_CLASIFICADOR);
Una vez instanciado el clasificador, debemos realizar una transformación de imagen capturada
para transformarla, de una imagen a color, a una imagen en escala de grises. Esta transformación
es imprescindible puesto que el algoritmo de Viola & Jones requiere como prerequisito trabajar
con una imagen en escala de grises.
Mat gray_frame = new Mat();
Imgproc.cvtColor(detect_frame, gray_frame, Imgproc.COLOR_BGR2GRAY);
Una vez cumplimos los requisitos establecidos por el algoritmo, procedemos a realizar la
llamada al algoritmo de Viola & Jones:
faceDetections = new MatOfRect();
faceDetector.detectMultiScale(gray_frame, faceDetections);
La implementación del algoritmo en OpenCV no retorna como resultado una imagen con la
detección de la cara, sino que retorna una estructura de datos que representa una caja envolvente
de la región de interés (en nuestro caso, la cara).
OpenCV delega la responsabilidad de tratar estos puntos al usuario. Esta solución es mucho
más versátil, puesto que permite construir desarrollos adicionales que trabajen con esta
información.
4.2.4 Filtrado de imágenes
Cuando capturamos imágenes siempre encontramos lo que se denomina “ruido blanco”. El
ruido blanco no es más que el conjunto de pequeñas interferencias aleatorias que aparecen al
capturar una imagen.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
61
Para evitarlas, disponemos de multitud de técnicas. En nuestro caso, durante la elaboración del
proyecto se utilizaron dos de ellas (blur y open), en diferentes puntos y con diferentes
propósitos.
La primera de las técnicas que se utilizaron es el blur (difuminación). Tal y como su nombre
indica, el blur consiste en difuminar la imagen, de forma que todos los píxeles que conforman
el ruido blanco desaparecerán al obtener información de los píxeles colindantes.
Esta técnica es muy efectiva cuando se quiere eliminar ruido en áreas muy pequeñas (píxeles).
En nuestro caso, la hemos utilizado justo antes de obtener la componente cromática de nuestra
región de interés.
OpenCV dispone de ésta función implementada y se puede utilizar de forma muy simple tal y
como se muestra a continuación:
Mat blurredImage = new Mat();
Imgproc.blur(frame, blurredImage, new Size(tam_x, tam_y));
Tal y como se puede ver, únicamente tenemos que indicar la imagen original, la imagen
resultante y el tamaño del patrón que utilizaremos para aplicar la técnica de difuminación (en
nuestro caso se utiliza un patrón de 7x7 píxeles).
La segunda de las técnicas es la operación de filtrado llamada open. Esta técnica realmente está
compuesta de dos operaciones llamadas erode y dilate.
Esta técnica se aplica para eliminar ruido en imágenes binarizadas (pequeñas regiones que se
han incluido en una imagen binarizada pero que realmente no queremos que se incluyan).
Mediante el operador erode se eliminan los píxeles más próximos a la frontera de la imagen. Si
la zona es suficientemente pequeña, el operador de erode la hará desaparecer.
Mediante el operador dilate se pretende recuperar la información que el operador dilate hizo
desaparecer. Esta transformación jamás dejará la imagen tal y como estaba originalmente, pero
esto no es un punto crítico en la consecución de este proyecto.
OpenCV también dispone de ésta función implementada y se puede utilizar de forma muy
simple tal y como se muestra a continuación:
Mat outputImage = new Mat();
Mat element = getKernelFromShape(elementSize, elementShape);
Imgproc.morphologyEx(input,outputImage, Imgproc.MORPH_OPEN, element);
En este punto se debe destacar que la función de OpenCV responsable de filtrar requiere que le
definamos una ventana de cierto tamaño y forma. En este caso, tras realizar algunas pruebas de
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
62
forma empírica, se observó que con una ventana de 7x7 píxeles se conseguía eliminar la
mayoría de “ruido” al binarizar, sin perder la región de interés.
4.2.5 Binarización de imágenes
Al intentar binarizar la imagen por primera vez, se observó que no se estaba binarizando en el
rango de colores esperado. Esto era debido a que la librería de OpenCV no implementa el
formato RGB, sino que implementa el formato BGR. Esencialmente es el mismo espacio de
colores, pero los bytes de los canales rojo y azul son cambiados de orden.
Este punto, a pesar de parecer intrascendente, es de vital importancia, puesto que si no se tiene
conocimiento de ello, las trasformaciones entre los diferentes espacios de colores pueden
provocar un cambio de color en la imagen y, posteriormente, puede provocar problemas con el
filtrado de color.
Una vez tenemos en cuenta este detalle, se puede proceder a convertir la imagen del formato
RGB a HSV mediante a la función cvtColor que viene implementada en OpenCV por lo que no
es necesario codificarla.
public Mat aplicarThreshold(Mat frame)
{
Mat thresFrame = new Mat();
//Convertimos la imagen a HSV para poder aplicar Threshold
Imgproc.cvtColor(frame, thresFrame, Imgproc.COLOR_RGB2HSV);
Core.inRange(thresFrame, new Scalar(start_hue, start_sat, start_val),
new Scalar(end_hue, end_sat, end_val), thresFrame);
return thresFrame;
}
Una vez tenemos la imagen en el espacio HSV, podemos proceder a hacer una binarización de
la imagen en función del color de la mano. Para ello, determinamos un rango de valores en el
canal del matiz y la saturación y obtenemos todo el rango del canal valor (no lo filtramos).
En este punto es importante conocer cómo esta implementada la API de OpenCV puesto que el
componente matiz solo puede tomar valores entre 0º y 180º. Cualquier otro valor por encima
de 180º se reduce aplicando el operador mod 180.
Una vez aplicada la función imRange, OpenCV nos devuelve la imagen debidamente
binarizada.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
63
4.2.6 Región de interés
Tras implementar una función que calculara el centro de masas tal y como se describe en el
apartado 0, se comprobó que dicho algoritmo no era suficiente para los requisitos del proyecto.
La función no era suficientemente eficiente ni tampoco tenía tolerancia ante regiones inconexas.
Por ello, finalmente se decidió utilizar una función nativa de OpenCV que calcula cajas
envolventes sobre una imagen binarizada.
contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(threshFrame, contours, new Mat(),
Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);
En este caso, la siguiente función nos genera una estructura de datos que contiene los puntos
que definen las cajas envolventes que se han detectado sobre la imagen binaria.
Al poder haber más de una caja envolvente, se detectó la necesidad de encontrar cuál de todas
es aquella que representa la mano. Tras analizarlas brevemente, se observa que la mano siempre
coincide con la caja envolvente de mayor tamaño (la que tiene mayor área).
Por ello, se construye un pequeño algoritmo que se queda con la caja envolvente de mayor
tamaño:
int objeto = 0;
double maxarea = 0;
for (int i = 0; i < contours.size(); i++)
{
double actualarea = Imgproc.contourArea(contours.get(i));
if (actualarea > maxarea)
{
objeto = i;
maxarea = actualarea;
}
}
Tras calcular cuál es nuestra región de interés, procedemos a calcular el centro de la caja
envolvente:
Moments p = Imgproc.moments(contours.get(objeto), false);
int x = (int) (p.get_m10() / p.get_m00());
int y = (int) (p.get_m01() / p.get_m00());
El centro de la caja envolvente no acostumbra a coincidir con el centro de masas de la imagen
binarizada, ahora bien, es una buena aproximación y es computacionalmente más sencilla.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
64
Puesto que no es estrictamente necesario tomar referencias de la posición de la mano a partir
del centro de masas, utilizaremos como referencia el centro de la caja envolvente.
4.2.7 Dynamic Time Warping
Cuando hemos detectado un movimiento significativo se debe aplicar el algoritmo de Dynamic
Time Warping para ver a cuál de todos se asemeja más.
El único punto que hay que tener en cuenta es que un movimiento en el plano tiene dos
componentes, x e y. Esto significa que debemos aplicar la comparación entre la componente x
de nuestro movimiento con la componente x de todos los movimientos de referencia. Así
mismo, debemos proceder de idéntico modo con todos la componente y.
Para poder realizar esta acción, en primer lugar tenemos que instanciar la librería y cargar los
movimientos:
FastDTW dtw = new FastDTW(5);
//Cargamos el movimiento significativo
Instance curr_x = new
DenseInstance(Movimiento.obtenerArray_X(movimiento.obtenerMovimiento()));
Instance curr_y = new
DenseInstance(Movimiento.obtenerArray_Y(movimiento.obtenerMovimiento()));
//Cargamos el movimiento referencia
Instance x = new DenseInstance(Movimiento.obtenerArray_X(key));
Instance y = new DenseInstance(Movimiento.obtenerArray_Y(key));
Una vez tenemos preparados los movimientos, procedemos a compararlos mediante el
algoritmo de Dynamic Time Warping:
double dist_x = dtw.measure(curr_x, x);
double dist_y = dtw.measure(curr_y, y);
Una vez tenemos la distancia de cada una de las componentes, debemos integrar este resultado.
Para ello, sumaremos la distancia de cada una de las componentes, obteniendo así una única
distancia entre el movimiento significativo y el movimiento de referencia.
double dist = dist_x + dist_y;
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
65
4.2.8 Clasificador
El clasificador utilizado para determinar qué movimiento se asemeja más al movimiento de
referencia es un clasificador de “mayor similitud”.
Puesto que el algoritmo de Dynamic Time Warping está devolviendo una distancia, para
nosotros, el movimiento de referencia será el que se encuentre a menor distancia.
Para evitar que un movimiento cualquiera provoque falsos positivos, estableceremos un umbral
tal que, si es rebasado, el movimiento se descarte y, por lo tanto, no sea tenido en consideración.
Para realizar este comparador, iteramos sobre todos los movimientos de referencia, guardando
aquellos que no superen el umbral y minimicen la distancia
//Cargamos el movimiento significativo
Instance curr_x = new
DenseInstance(Movimiento.obtenerArray_X(movimiento.obtenerMovimiento()));
Instance curr_y = new
DenseInstance(Movimiento.obtenerArray_Y(movimiento.obtenerMovimiento()));
String out = null;
double min = CUTOFF;
//Iteramos los movimientos de referencia
Iterator<List<Point>> it = lista_movimientos.keySet().iterator();
while(it.hasNext())
{
//Cargamos los movimientos de referencia
List<Point> key = (List<Point>) it.next();
Instance x = new DenseInstance(Movimiento.obtenerArray_X(key));
Instance y = new DenseInstance(Movimiento.obtenerArray_Y(key));
//Aplicamos DTW
double dist_x = dtw.measure(curr_x, x);
double dist_y = dtw.measure(curr_y, y);
double dist = dist_x + dist_y;
if(dist<min)
{
//Obtenemos una nueva distancia minima
out = lista_movimientos.get(key);
min = dist;
}
}
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
66
5. Diseño de la GUI
Por lo que respecta al diseño de la interfaz gráfica, no se estableció ningún criterio o restricción
a seguir, por lo que se optó por implementar una interfaz gráfica sobria que cubriese las
necesidades básicas de un usuario estándar.
Puesto que por definición, este proyecto se considera una interfaz, se decidió que, inicialmente,
la aplicación no debía tener activa ninguna ventana. De este modo se evitarían posibles
molestias al usuario.
Así pues, inicialmente la aplicación arranca en la barra del Sistema Operativo, en modo tray:
De esta aplicación en modo tray aparece un sencillo menú que únicamente nos deja realizar
cuatro acciones:
Obtener información acerca del programa.
Mostrar una ventana de debug.
Activar/Desactivar el reconocimiento de movimientos.
Elegir la interfaz de salida
Salir de la aplicación.
La primera opción nos abrirá una ventana con información relativa al proyecto. Esta ventana es
meramente informativa y no admite ningún tipo de interacción, salvo un botón de “Aceptar”,
que procederá al cierre de la ventana.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
67
La segunda opción procede a abrir una ventana de Debug. En ella no se observará nada
remarcable, salvo que la aplicación esté capturando movimientos. En ese caso, la pantalla
mostrará cuatro ventanas.
En la primera de ellas se podrá ver la imagen original que se está capturando.
En la segunda de ellas se podrá ver la imagen original a la cual se le ha aplicado el algoritmo
de Viola & Jones (detección de la cara).
En la tercera de ellas se podrá observar la imagen binarizada, en la cual se muestra la región de
interés (mano derecha).
En la última de ellas se podrá observar la imagen original, indicando a su vez el centro de masas
de la región de interés (mano derecha).
Adicionalmente, en caso que se detecte un movimiento, la ventana mostrará un mensaje con el
movimiento detectado.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
68
Esta ventana no es necesaria a efectos de usabilidad de la interfaz, pero es muy útil a efectos de
visualizar cuál es el comportamiento de la interfaz en un momento determinado.
La tercera opción únicamente activa o desactiva la detección de movimientos. Este menú es el
responsable de activar o desactivar la funcionalidad básica de este proyecto.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
69
Las dos siguientes opciones permiten activar y desactivar la interfaz de salida que deseemos.
En caso que queramos que el programa interactúe con la interfaz del teclado, deberemos escoger
la opción “Activar Teclado”. En caso de querer activar la interfaz del ratón, deberemos escoger
la opción “Activar Ratón”.
Del mismo modo que la opción de “Activar Reconocimiento”, basta con quitar la selección para
deshabilitar la interfaz.
Este menú es bastante versátil, puesto que permite activar varias interfaces simultáneamente.
Esto significa que, para nuestro caso, podríamos activar la interfaz del teclado y la interfaz del
ratón a la vez.
A continuación se muestra el diagrama de secuencia que se puede seguir al utilizar la GUI:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
71
7. Patrones de software utilizados A la hora de abordar un proyecto de cierta envergadura se
deben tener en cuenta las buenas prácticas que nos aporta el
diseño de software.
A continuación se muestra cómo se han integrado diferentes
patrones de diseño a este proyecto.
7.1 Patrón Modelo-Vista-Controlador
Uno de los patrones de diseño utilizados en este
proyecto es el patrón Modelo-Vista-Controlador
(MVC).
Este patrón se caracteriza por cómo aísla los datos y
la lógica de negocio de una aplicación de la interfaz
de usuario y el módulo encargado de gestionar los
eventos y las comunicaciones.
Este patrón se compone de tres elementos
diferenciados, tal y como su nombre indica:
Modelo
Vista
Controlador
Mediante el modelo tenemos la representación de la información de nuestro sistema, por lo que,
se encargará de gestionar todos los accesos a la información.
Todas las peticiones de acceso o manipulación de datos llegarán al modelo a través del
controlador.
Por otro lado, el controlador tiene por objetivo responder ante los diferentes eventos que se
producen en la aplicación. Estos eventos pueden ser, desde disparadores, a acciones realizadas
por el usuario.
Así pues, el controlador será el responsable de realizar las peticiones al modelo. También puede
gestionar ciertos eventos con la vista (por ejemplo, desplazamientos por documentos).
Por último tenemos la vista, la cual se encarga de presentar los datos del modelo en un formato
adecuado para interactuar (generalmente se utiliza una GUI).
El objetivo que se pretende con este patrón es que la representación de los datos en la GUI sea
totalmente independiente del modelo, de tal forma que un cambio en la vista no tenga afectación
sobre la lógica del modelo. Del mismo modo, un cambio en cómo se captura o cómo se actúa
ante ciertos eventos no tiene que afectar al modelo.
7.1.1 Interacción entre los componentes
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
72
A continuación se detalla el flujo de control que siguen los diferentes componentes que
forman el patrón MVC:
1. El usuario interactúa con la interfaz de usuario.
Por ejemplo, el usuario pulsa un botón.
2. El controlador recibe, por parte de los objetos de la vista, la notificación de la acción
solicitada por el usuario, por lo que se procesa el evento que llega.
3. El controlador accede al modelo, invocándolo para realizar una alguna acción propia de
la lógica de negocio.
Por ejemplo, capturar imágenes desde la cámara web.
4. El controlador delega a los objetos de la vista la tarea de desplegar la interfaz de usuario.
La vista obtiene sus datos del modelo para generar la interfaz de usuario donde se
reflejan los cambios en el modelo.
Por ejemplo, se produce un cambio en el frame capturado y se muestra por pantalla.
5. La interfaz de usuario espera nuevas interacciones del usuario, comenzando el ciclo
nuevamente.
7.1.2 Detalles de construcción
En este apartado detallamos las partes de código más relevantes, donde se muestra cómo se ha
implementado el patrón MVC. El siguiente esquema ilustra, a grandes rasgos, cómo interactúan
los diferentes módulos entre sí y qué relaciones se derivan entre ellos:
Todo el flujo del programa se inicia en el controlador, el cual es instanciado por el programa
principal.
Cuando se llama al constructor del módulo controlador, éste instancia tanto la Vista como el
Modelo:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
73
private Controlador()
{
//Instanciamos Modelo y Vista
modelo = new Modelo();
vista = Vista.getInstance();
//Patron Observador entre Modelo y Vista
modelo.addObserver(vista);
Adicionalmente, se utiliza el constructor suscribir la Vista al Modelo. Así pues, la relación entre
la Vista y el Modelo se establece gracias al patrón Observador, el cual se explica en detalle en
el siguiente apartado.
Por último, queda pendiente explicar cómo se trasladan los eventos de las ventanas al
controlador, para que, en función de ciertos eventos, interactúe con el Modelo.
En primer lugar, se crean los listeners en la clase Controlador. A continuación mostramos uno
de ellos a modo de ejemplo:
public void actionPerformed(java.awt.event.ActionEvent e)
{
if(e.getActionCommand() == "Acerca")
{
vista.mostrarAcerca();
}
if(e.getActionCommand() == "Aceptar")
{
vista.ocultarAcerca();
} …
Este listener se utilizará para procesar los eventos de las ventanas que se deseen. Por ello, los
diferentes componentes de las ventanas implementadas en la Vista deben añadirlo y, así,
delegarle la responsabilidad de la gestión de los diferentes eventos:
public void addControlador(Controlador controlador)
{
aceptar.addActionListener(controlador);
}
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
74
7.2 Patrón Observador
Durante la explicación del patrón Modelo-Vista-Controlador, se ha comentado que el Modelo,
idealmente, no debe tener conocimiento directo sobre la Vista.
Esto es así para poder aislar el Modelo de cualquier tipo de cambio sobre la Vista o viceversa.
Para facilitar esta tarea, en el proyecto hemos hecho uso del patrón Observador.
El patrón Observador provee cierta indirección entre el Modelo y la Vista, permitiendo al
Modelo notificar a los interesados (en nuestro caso, a la Vista) cualquier cambio.
Un objeto Vista puede registrarse con el modelo y esperar los cambios, pero aun así, el modelo
en sí mismo sigue sin saber nada de la Vista.
Tal y como se puede ver a continuación, la clase modelo se crea extendiendo la clase
observable, por lo que todas sus variables globales son susceptibles de ser observadas mediante
el patrón Observador.
public class Modelo extends java.util.Observable
{
private List<ByteArrayInputStream> images = null;
Otro punto importante a tener en cuenta es que cuando el módulo que es observado modifica
sus datos, debe notificarlo a todos los observadores. Para ello hay que suscribir las clases del
siguiente modo:
//Patron Observador entre Modelo y Vista
modelo.addObserver(vista);
Por otro lado, cada vez que se modifica una imagen en el motor de detección de movimientos,
se notifica de la siguiente forma:
setChanged();
notifyObservers(images);
Para finalizar, tenemos la clase Vista, la cual implementa el patrón Observador:
public class Vista extends JFrame implements java.util.Observer
{
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
75
En este caso, la clase Vista está subscrita a cualquier cambio que se dé en la clase Modelo. Para
garantizar que recibe los eventos de modificación en el modelo de datos, existe una función
update, que se activa de forma asíncrona cuando se notifica un cambio desde el modelo:
public void update(Observable obs, Object obj)
{
if (obj instanceof ArrayList<?>)
{
ArrayList<?> array = (ArrayList<?>) obj;
debug.actualiza(array);
}
}
Tal y como se puede ver en el ejemplo, se ha evitado hacer uso de tipos de datos compuestos o
de tipos de datos relacionados con las librerías de Visión por Computador o con las librerías de
Aprendizaje.
También se puede observar que la clase Debug actualiza la vista sin tener ningún acoplamiento
directo con la clase Modelo:
public void actualiza(ArrayList<?> b)
{
try
{
originalFrame.setIcon(new
ImageIcon(ImageIO.read((ByteArrayInputStream) b.get(0))));
violaFrame.setIcon(new
ImageIcon(ImageIO.read((ByteArrayInputStream) b.get(1))));
thresholdFrame.setIcon(new
ImageIcon(ImageIO.read((ByteArrayInputStream) b.get(2))));
trackingFrame.setIcon(new
ImageIcon(ImageIO.read((ByteArrayInputStream) b.get(3))));
}
catch(Exception e)
{
System.out.println("Problema al capturar imagen");
}
}
Tal y como se puede observar, con este paradigma, se consigue aislar por completo la vista del
modelo de datos y las librerías que se están utilizando.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
76
7.3 Patrón Singleton
El patrón Singleton es un patrón de software diseñado para restringir la creación de objetos
pertenecientes a una clase, garantizando que sólo se tenga una instancia y proporcionar un punto
de acceso global a ella.
Este patrón se implementa creando en la clase un método público que crea una instancia del
objeto si, y solo si, todavía no existe ninguna instancia. Para asegurar que la clase no puede ser
instanciada nuevamente, se regula el alcance del constructor con modificadores de acceso
(protegidos o privados).
Sus características principales son:
La propia clase es responsable de crear la única instancia.
Permite el acceso global a dicha instancia mediante un método de clase.
Declara el constructor de clase como privado para que no sea instanciable directamente.
En el sistema que se ha construido, se han detectado diferentes clases que son susceptibles de
tener una única instancia. A modo de ejemplo, se adjunta cómo se ha implementado el patrón
Singleton en el proyecto:
Para empezar, se debe añadir una variable global y privada en clase que queremos implementar
el patrón Singleton. Esta variable será del mismo tipo que la clase en cuestión:
public class Controlador implements ActionListener, ItemListener
{
//Implementamos clase singleton
private static Controlador controlador;
Seguidamente se crea una función en la que validaremos si la variable global anteriormente
creada está instanciada o no.
Si la variable no está instanciada, la función llamará al constructor y creará una instancia nueva.
En caso contrario, la función retornará la instancia guardada en la variable global:
public static synchronized Controlador getInstance()
{
if(controlador == null)
{
controlador = new Controlador();
}
return controlador;
}
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
77
Por último, debemos sobrecargar el constructor por defecto, haciendo que éste sea privado.
De este modo se evita que se pueda instanciar por error:
private Controlador()
{
...
7.4 Arquitectura en 3 capas
Otra de las decisiones importantes a la hora de realizar este proyecto, recae en el momento de
decidir cuántas capas se utilizan para construir el software.
Al tratarse de una aplicación que trabaja con datos en tiempo real, puede hacernos pensar en
construir una aplicación monolítica, dado que, al haber menos módulos, se reducen, en parte,
los costes de realizar múltiples llamadas en diferentes módulos del código.
No obstante, al tratarse de una interfaz de usuario, da a pensar que puede ser modificada y
adaptada en el futuro, por lo que tener componentes fácilmente cambiables y reusables cobra
sentido.
Aunque se trata de una aplicación en tiempo real, los tiempos de procesado de imágenes no son
críticos, dado que los sistemas actuales son suficientemente potentes como para cubrir la
pequeña penalización que nos aporta un sistema software construido en capas.
Así pues, una vez decidido que el sistema debe construirse con una separación lógica entre
capas, lo único que queda por saber es cuántas capas se deben implementar.
Por definición, el patrón Modelo-Vista-Controlador, nos está proporcionando una separación
lógica entre la Vista, la cual consideraremos como capa de presentación y el Modelo, el cual
consideraremos como capa de negocio.
El Controlador es un elemento que queda en una zona intermedia entre la capa de presentación
y la capa de negocio, puesto que interactúa entre ambas capas.
Así pues, solo nos quedaría definir dónde se encuentra la capa de datos. En este caso particular,
la capa de datos interactúa con la capa de negocio mediante el patrón Data Access Object
(DAO).
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
78
7.5 Patrón Data Access Object
Así pues, solo nos quedaría definir dónde se encuentra la capa de datos. En este caso particular,
la capa de datos interactúa con la capa de negocio mediante el patrón DAO.
El primer motivo por el que se plantea utilizar el patrón DAO es que este patrón permite aislar
por completo los objetos de negocio del modo en que se manipula la información. Así mismo,
otro punto interesante es que se aísla la tecnología en la que los datos se hacen persistentes. De
este modo, la capa de negocio delega la responsabilidad de acceder a los datos al DAO.
Para implementar este patrón debemos empezar por construir la clase Factory, la cual se
encarga de generar los objetos FactoryDAO para cada una de las fuentes de datos.
En este caso, únicamente implementaremos la case CfgFactoryDAO:
public abstract class FactoryDAO
{
public static final int CFG_FACTORY = 1;
public abstract MovimientosDAO getMovimientosDAO();
public static FactoryDAO getFactory(int claveFactory)
{
switch(claveFactory)
{
case CFG_FACTORY:
return new CfgFactoryDAO();
default:
throw new IllegalArgumentException();
}
}
}
Seguidamente, se definen los métodos que tienen los DAO’s. En nuestro caso, obtenemos las
posiciones de los movimientos:
public interface MovimientosDAO
{
ArrayList obtenerMovimientos() throws Exception;
}
Otro punto a tener en cuenta, es que se debe extender la clase FactoryDAO y sobrescribir el
método getMovimientosDAO para crear un objeto que consuma la fuente de datos que se
necesita:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
79
public class TxtFactoryDAO extends FactoryDAO
{
@Override
public MovimientosDAO getMovimientosDAO()
{
return new MovimientosCfgFactoryDAO();
}
}
Una vez podemos recuperar el DAO de la fuente de datos, debemos proceder a implementar las
diferentes operaciones con las que consumiremos la fuente de datos:
public class MovimientosCfgFactoryDAO implements MovimientosDAO
{
public MovimientosCfgFactoryDAO(){}
public ArrayList<Point> obtenerMovimientos() throws Exception
{
//Implementamos obtención de datos
//throw new UnsupportedOperationException("Funcionalidad no
soportada");
}
}
Una vez finalizada la implementación del DAO, podemos consumir datos obteniendo el objeto
Factory que represente nuestro origen de datos y posteriormente, realizando la llamada que
obtiene los datos:
//Obtenemos la factoria DAO
FactoryDAO cfgFactory = FactoryDAO.getFactory(FactoryDAO.TXT_FACTORY);
MovimientosDAO movimientosDAO = cfgFactory.getMovimientosDAO();
//Utilizamos funciones del DAO
ArrayList<Point> listamovimientos = movimientosDAO.obtenerMovimientos();
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
80
8. Diagrama de Clases
8.1 Diagrama de clases detallado MVC
1
1
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
81
8.2 Diagrama de clases detallado Vista
1
1 1 1
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
82
8.3 Diagrama de clases detallado Modelo
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
83
8.4 Diagrama de clases detallado ProcesadorFrame
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
84
8.5 Diagrama de clases detallado Detector
1
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
85
8.6 Diagrama de clases detallado DAO
1
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
86
9. Conclusiones
Con este proyecto hemos conseguido crear una interfaz Persona-Computador desde cero que,
salvando las distancias, consigue funcionar de forma similar a muchas soluciones de mercado
(Wii Remote, Play Station Move o Microsoft Kinect), con la salvedad de que esta solución utiliza
una simple cámara (no intervienen sensores específicos, mandos, ni elementos de luz).
Un punto remarcable al respecto es que la mayoría de los algoritmos utilizados para
implementar la interfaz son relativamente antiguos (Dynamic Time Warping 1978, AdaBoost
1995, Viola & Jones 2000), y han sufrido pocos cambios con el tiempo. En contrapunto, las
interfaces Persona-Computador son un tema de actualidad. Sin ir más lejos, las interfaces
anteriormente citadas son relativamente modernas (Wii Remote 2006, Play Station Move 2010
o Microsoft Kinect 2011).
Por lo que respecta a los resultados, considero que es especialmente satisfactorio el ratio de
detección de movimientos que se ha obtenido. Este ratio seguramente encaja con el esperado
en un proyecto de esta envergadura, no obstante, ya sea por desconocimiento o por ignorancia,
está bastante alejado del ratio que esperaba obtener antes de abordar el proyecto.
Otro punto a remarcar es que el sistema es mucho más robusto de lo que podía imaginarme al
inicio. El hecho de que el sistema pueda binarizar dinámicamente hace que sea mucho más
tolerante a cambios de luz y de escena. Así mismo, no es tan dependiente de configuraciones
específicas que pueden hacer que el sistema funcione en unas condiciones y en otras no.
Además de los puntos anteriormente citados, este trabajo me ha permitido abordar un proyecto
real de Visión por Computador, donde he podido profundizar en los conocimientos de esta
materia y me ha permitido trabajar con una librería de Visión por Computador real, saliendo
del área de confort que nos da Matlab. Por otro lado, durante el transcurso del proyecto, he
logrado aprender algoritmos como el de Viola & Jones que eran totalmente desconocidos para
mi hasta el momento.
A pesar de que soy consciente de que hay muchos aspectos a mejorar y seguir desarrollando a
partir de este trabajo, se puede afirmar que se han cumplido los principales objetivos que se
habían marcado al inicio del proyecto.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
87
10. Líneas de futuro
Durante el desarrollo de este proyecto se han detectado algunos aspectos que son susceptibles
de mejorar. No obstante, puesto que el proyecto tiene una duración limitada, estos no se han
podido incluir en la línea de trabajo.
Por ello se han recogido y se citan a continuación para que, en un futuro, se puedan desarrollar
y mejorar este proyecto:
Captura de frames adaptativa
Se ha detectado que el proceso de detección de movimientos tiene un consumo de CPU
bastante elevado. Esto, para un portátil de hoy en día no es una limitación, de hecho, si
el usuario no está realizando tareas intensivas con su ordenador probablemente no lo
aprecie.
Así pues, el problema recae en el hecho de portar este proyecto a dispositivos móviles.
Los recursos hardware de estos dispositivos son mucho más limitados, por lo que muy
probablemente, en el peor de los casos, la interfaz pueda llegar a saturarse, bloqueando
por completo el dispositivo.
Para abordar este problema se propone hacer un control adaptativo de los frames por
segundo que se capturan, de forma que se limite el número de frames en función de la
potencia de cálculo del dispositivo. Esta calibración es relativamente sencilla de
automatizar y evitaría el problema anteriormente citado.
Trabajar con dos manos
El proyecto actual trabaja con la restricción de que habrá únicamente una mano en la
escena. Seguramente, añadir una mano adicional, conlleva bastantes complicaciones a
tener en cuenta a la hora de implementar la interfaz, pero enriquecería y ampliaría
considerablemente el abanico de posibilidades que brinda este proyecto.
Robustez en la detección de gestos
Se ha detectado que, en casos concretos, el sistema no es todo lo fiable que se esperaría
de él. Un ejemplo se da cuando aparece en escena un usuario en manga corta.
Ante casos como este, el algoritmo de binarización incluye partes como el antebrazo, lo
cual desplaza el centro de masas y produce que las detecciones de movimiento sean
menos precisas.
Por ello, se propone como trabajo futuro incluir una función para evitar estas casuísticas.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
88
Variable velocidad
El sistema actual detecta movimientos a diferentes velocidades, tanto los rápidos como
los lentos, pero en ningún caso hace distinción entre ellos.
Se propone mejorar el sistema con una variación en el algoritmo de detección para saber
si se trata de un movimiento rápido o lento, y en función del resultado, aplicar
variaciones en las acciones de las interfaces.
Por ejemplo, si se aplica un movimiento hacia la derecha de manera rápida, se puede
lograr que el movimiento del cursor sea mayor que cuando se hace un movimiento de
forma lenta.
Tracking
Actualmente se puede mover el cursor del ratón concatenando movimientos en la
dirección deseada, pero, sin lugar a dudas, la interacción es bastante más complicada.
Para casos como la gestión de un escritorio, puede ser más útil hacer un tracking de la
mano que reconocer ciertos movimientos.
Por ello, se plantea la posibilidad de que el usuario pueda configurar dos modos de uso,
(tracking/gestos), en función de sus necesidades y gustos.
GUI y apariencia
Actualmente la GUI ha sido construida sobre un tray de Sistema Operativo. En caso de
no haber tray, la aplicación no arranca. La decisión de arrancar la aplicación en tray vino
a raíz de querer evitar que nuestra interfaz interfiriese en el escritorio del usuario.
Esta limitación puede evitarse haciendo que ésta arranque en modo ventana siempre y
cuando no haya tray.
Otro punto a tener en consideración es que la aplicación muestra todos los mensajes de
aplicación en castellano. Dado que el mundo tiende a globalizarse, se propone como
trabajo futuro internacionalizar la aplicación.
Ampliar el set de movimientos
El sistema que se ha construido funciona con un conjunto de 6 movimientos.
Aplicando algunos cambios al algoritmo de clasificación para hacerlo más sofisticado,
se podría ampliar el conjunto de movimientos, haciendo que el sistema que se ha
construido fuera mucho más dinámico.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
89
11. Bibliografía
[1] A decision theoretic generalization of on-line learning and application to boosting
R. Schapire, Y. Freund
AT&T Bell Laboratories. USA, 1995.
[2] A method of detecting and recognising hand gestures using OpenCV (2)
Anonimous
http://www.andol.me/a-method-of-detecting-and-recognising-hand-gestures-using-
opencv-2/, 2012
[3] A practical introduction to Computer Vision with OpenCV
K. Dawson-Howe
Wiley, 2014
[4] Algoritmo de Viola-Jones para detección de rostros en procesadores gráficos
T. Díaz, J.L. Viloria, R. Socorro, O. Ferrer
http://web.archive.org/web/20121107040603/http://renia.cujae.edu.cu/index.php/revist
acientifica/article/view/151/pdf_56
[5] Clasificadores Débiles – AdaBoost
A. Morales
http://catarina.udlap.mx/u_dl_a/tales/documentos/lmt/morales_s_aa/capitulo3.pdf
[6] Dynamic Programming Algorithm Optimization for Spoken Word Recognition
H. Sakoe, S. Chiba
IEEE Transaction on Acoustics, Speech, and Signal Processing. ASSP-26, 43-49,
1978.
[7] Exact indexing of dynamic time warping
E. Keogh, C. Ratanamahatana
Knowledge and Information Systems, 2004.
[8] Gesture recognition using OpenCV + Python
V. Sharma
http://vipulsharma20.blogspot.com.es/2015/03/gesture-recognition-using-opencv-
python.html, 2015
[9] Hand and Finger Detection using JavaCV
A. Milhaly
https://www.javacodegeeks.com/2012/12/hand-and-finger-detection-using-
javacv.html, 2012
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
90
[10] Hand gesture recognition using Computer Vision
R. Lockton, B. College
http://research.microsoft.com/en-us/um/people/awf/bmvc02/project.pdf,
[11] Hand gesture recognition via model fitting in energy minimization
Roy
http://www.morethantechnical.com/2010/12/28/hand-gesture-recognition-via-model-
fitting-in-energy-minimization-wopencv/, 2011
[12] Hand gesture using OpenCV
A. Tatipamula
http://anikettatipamula.blogspot.com.es/2012/02/hand-gesture-using-opencv.html,
2012
[13] Hand tracking and gesture detection (OpenCV)
L. Srinivasan
https://s-ln.in/2013/04/18/hand-tracking-and-gesture-detection-opencv/, 2013
[14] Hand tracking and recognition with OpenCV
S. Andresen
http://simena86.github.io/blog/2013/08/12/hand-tracking-and-recognition-with-
opencv/, 2014
[15] Hands gesture recognition
A. Kirillov
http://www.codeproject.com/Articles/26280/Hands-Gesture-Recognition, 2008
[16] Java Swing, 2nd Edition
M. Loy, R. Eckstein, D. Wood, J. Elliot, B. Cole
O’Reilly Media, 2002
[17] Java Machine Learning Library (Java-ML)
http://java-ml.sourceforge.net/
[18] La bíblia del Java 2
S. Holzner
Anaya Multimedia, 2000
[19] Learning OpenCV
G. Bradski, A. Kaehler
O’Reilly Media, Inc, 2008
[20] Minimum Prediction Residual Principle Applied to Speech Recognition
F. Itakura
IEEE Transaction on Acoustics, Speech, and Signal Processing. ASSP-23, 52-72,
1975.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
91
[21] Modelo de color HSV
Wikipedia
https://es.wikipedia.org/wiki/Modelo_de_color_HSV
[22] OpenCV 3.0 Computer Vision with Java
D. Lélis
Packt Publishing, 2015
[23] OpenCV Java tutorials
L. De Russis, A. Sacco
http://opencv-java-tutorials.readthedocs.org/en/latest/index.html, 2014
[24] OpenCV Python hand gesture recognition
Anonimous
http://creat-tabu.blogspot.com.es/2013/08/opencv-python-hand-gesture-
recognition.html, 2013
[25] Página oficial de OpenCV
http://opencv.org/
[26] Rapid Object Detection using a Boosted Cascade of Simple Features.
P. Viola, M. Jones.
Conference on Computer Vision and Pattern Recognition, 2001.
[27] Real time finger tracking and contour detection for gesture recognition using OpenCV
R.M. Gurav
https://www.researchgate.net/publication/282956557_Real_time_finger_tracking_and
_contour_detection_for_gesture_recognition_using_OpenCV, 2015
[28] Robust Real-Time Face Detection
P. Viola, M. Jones.
International Journal of Computer Vision 57(2) 137-154, 2004.
[29] Simple Hand Tracking with Kinect + OpenCV
A. Berg
http://forum.libcinder.org/topic/simple-hand-tracking-with-kinect-opencv, 2011
[30] The image processing Handbook, Fifth Edition
J. Russ
CRC Press, 2006
[31] The simplest Model View Controller (MVC) Java Example
J. Mack
http://www.austintek.com/mvc/, 2011
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
92
[32] Toward Accurate Dynamic Time Warping in Linear Time and Space
S. Stan, P. Chan
Space Intelligent Data Analysis Vol. 11, Number 5, 561-580, 2007.
[33] UML y patrones. Introducción al análisis y diseño orientado a objetos
C. Larman
Pearson, 1999
[34] Using OpenCV Java with eclipse
http://docs.opencv.org/3.0-
beta/doc/tutorials/introduction/java_eclipse/java_eclipse.html
[35] Using hand gestures to control mouse pointer in c sharp
Anonimous
http://www.andol.me/using-hand-gestures-to-control-mouse-pointer-in-c-sharp/, 2012
[36] Vision-based User Interface Programming in Java
A. Davison
Amazon Digital Services LLC, 2013
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
93
Anexo A. Preparación del entorno de trabajo
Este anexo detalla todos los pasos a seguir para disponer de un entorno de trabajo
completamente funcional.
Paso 1: Instalar JDK de Java
En primer lugar, descargaremos el Java Development Kit (versión 1.8) de la página
oficial de Oracle. En el momento de crear la memoria del proyecto está disponible la
versión 1.8 update 91 en la siguiente URL:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-
2133151.html
Esta versión de JDK está disponible para múltiples sistemas operativos y arquitecturas
de procesador. Únicamente debemos asegurar que descargamos la versión apropiada
para nuestro sistema operativo.
Paso 2: Instalar eclipse
Una vez disponemos de nuestro Java Development Kit, procederemos a descargar
eclipse de su página oficial. En el momento de crear la memoria del proyecto está
disponible la versión 4.5.2 en la siguiente URL: https://eclipse.org/mars/
Al igual que con nuestra JDK, deberemos elegir una versión compatible tanto con
nuestro sistema operativo como con nuestra arquitectura del procesador.
Al tratarse de un entorno de desarrollo, existen diferentes paquetes. En nuestro caso
utilizamos el paquete “Eclipse IDE for Java Developers”.
Paso 3: Instalar OpenCV
Por último, necesitamos instalar las librerías de visión por computador de OpenCV.
Estas librerías se pueden obtener gratuitamente desde la página web oficial. En el
momento de crear la memoria del proyecto, está disponible la versión 3.1 en la siguiente
URL: http://opencv.org/
Una vez más, debemos descargar una versión de la librería que sea compatible con
nuestro sistema operativo.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
94
El instalable de OpenCV nos dejará elegir en qué ruta deseamos extraer las librerías. Es
importante tomar nota de esta ruta puesto que deberemos utilizarla para configurar las
variables de entorno de nuestro sistema operativo.
Paso 4: Variables de entorno
Puesto que este proyecto ha utilizado un entorno de trabajo en Windows, a continuación
se muestra cómo modificar las variables de entorno en este sistema operativo. El
procedimiento sería análogo en otros sistemas operativos como Linux.
Para que OpenCV funcione correctamente se debe configurar la variable de entorno
PATH de forma que apunte las librerías de OpenCV.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
95
Para configurarlo accederemos a Sistema Configuración avanzada de sistema
Variables de entorno.
Una vez dentro, editaremos la variable de sistema PATH y nos aseguraremos que está
apuntando a la carpeta build correspondiente a la arquitectura de nuestro procesador, de
lo contrario, las librerías no funcionarán adecuadamente.
Paso 5: Importar el proyecto
El siguiente paso es importar el proyecto actual a la instalación de Eclipse.
Para ello, accederemos al menú File Import y elegiremos la opción General
Existing Projects into Workspace
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
96
Seguidamente, buscamos en el workspace del Proyecto de final de Carrera y elegimos
la carpeta PFC_java tal y como se muestra en la imagen.
Tras finalizar este paso, se habrá importado el proyecto correctamente.
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
97
Paso 6: Referenciar la librería de OpenCV (opcional)
El proyecto se ha creado de forma que todas las librerías están autocontenidas.
En caso de modificar la versión de OpenCV se requeriría incluir las nuevas librerías.
Para ello abrimos las propiedades del proyecto y nos dirigimos a “Java Build Path” y
abrimos la pestaña de librerías.
En esta ventana deberíamos incluir la librería JAR correspondiente a nuestra versión de
OpenCV.
Debería aparecer incluida tal y como se muestra en la siguiente captura de pantalla:
Interfaz persona-ordenador mediante lenguaje gestual PFC Curso 2015-2016
98
Paso 7: Modificar referencias en código
La clase AnalizadorCara contiene una constante llamada RUTA_CLASIFICADOR, la
cual apunta a un fichero de OpenCV utilizado para cargar el clasificador en cascada del
algoritmo de Viola & Jones.
Esta ruta debería cambiarse por la ruta en la que se haya instalado OpenCV, de lo
contrario el algoritmo de detección de caras utilizado en este proyecto no funcionará.