Título: Interfaz persona-ordenador mediante lenguaje ...

99
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:

Transcript of Título: Interfaz persona-ordenador mediante lenguaje ...

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

1

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

3

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

5

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

20

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

25

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

70

6. Diagrama de bloques

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á.