UNIVERSIDAD NACIONAL DEL CENTRO DE LA PROVINCIA DE BUENOS AIRES
Diseño e implementación
de aplicaciones interactivas
para exposiciones y paseos
Proyecto de tesis de grado de la carrera Ingeniería en Sistemas
Alumna: Solange Marquez Figueroa
[email protected]
Director: Dr. Cristian García Bauza
1
Tabla de contenido
Tabla de contenido ... 1
Índice de figuras ... 2
Índice de diagramas... 4
Índice de code snippets ... 5
Agradecimientos ... 6
Resumen... 7
Capítulo 1 Introducción ... 8
1.1 Motivación ... 9
1.2 Solución propuesta ... 9
1.3 Organización del informe ... 10
Capítulo 2 Interactividad ... 12
2.1 Evolución de la Interfaz de usuario ... 12
2.1.1 Kinect... 15
2.2 Interactividad en paseos y museos ... 19
2.3 Tecnologías utilizadas ... 24
Capítulo 3 Diseño e Implementación ... 25
3.1 Arquitectura propuesta ... 25
3.1.1 Controlador... 25
3.1.2 Modelo ... 35
3.1.3 Vista... 38
3.2 Diseño de cada aplicación ... 41
3.2.1 Reproductor de video ... 41
3.2.1.1 Reproducción normal y hacia atrás ... 43
3.2.1.1 Reproducción cámara lenta y acelerada ... 49
3.2.1.3 Unificación de estados de reproducción ... 50
3.2.2 Hinchada ... 55
3.2.2.1 Reproducción de un sonido ... 57
3.2.2.2 Reproducción múltiple ... 58
3.2.2.3 Reproducción dinámica ... 61
3.2.2.4 Carga de sonidos ... 64
3.2.2.5 Interfaz gráfica ... 64
3.2.3 Descubrir la imagen ... 69
3.2.3.1 Descubrimiento sin memoria... 70
2
3.2.3.3 Recubrimiento de la imagen ... 74
Capítulo 4 Pruebas ... 76
4.1 Contexto ... 76
4.2 Aplicaciones ... 77
4.2.1 Reproductor de video ... 77
4.2.2 Hinchada ... 79
4.2.3 Descubrir la imagen ... 80
Capítulo 5 Conclusiones ... 83
5.1 Resultados obtenidos ... 83
5.2 Trabajos futuros ... 84
Referencias ... 86
Índice de figuras
Figura 2.1 - Evolución de las interfaces de usuario. ... 12Figura 2.2 - Interfaces de usuario (CLI, GUI y NUI respectivamente) ... 13
Figura 2.3 - Dispositivo WiiMote ... 14
Figura 2.4 - Dispositivo Leap Motion ... 14
Figura 2.5 - Dispositivo Kinect ... 15
Figura 2.6 - Componentes del dispositivo Kinect ... 15
Figura 2.7 - Rango de inclinación ... 16
Figura 2.8 - Arreglo de micrófonos del dispositivo Kinect marcados en violeta. ... 17
Figura 2.9 - Frames de profundidad. ... 17
Figura 2.10 - Frames de esqueletos. ... 18
Figura 2.11 - Veinte articulaciones rastreadas en un esqueleto. ... 18
Figura 2.12 - Interacción en el Museo de Louvre con el uso de Nintendo 3DS y códigos QR. . 20 Figura 2.13 - Juego en Museon con la utilización de PuppyIR. ... 20
Figura 2.14 - Live Projection Mapping - EVA 2013 ... 21
Figura 2.15 - Pisos interactivos en eventos. ... 21
Figura 2.16 - „Play Work Build‟ en el National Building Museum. ... 22
Figura 2.17 - „Strike a pose‟ en Cleveland Museum of Art. ... 22
Figura 2.18 - Juego interactivo relacionado al Básquet en Chicago Sports Museum. ... 23
Figura 2.19 - Avatares en Sedena. ... 23
Figura 3.1 - Interacción del dispositivo Kinect con la aplicación a través del Kinect SDK ... 26
Figura 3.2 - Secuencia de llamados para la inicialización ... 30
3
Figura 3.4 - Secuencia de llamados para la actualización del modelo. ... 31
Figura 3.5 - Comunicación necesaria entre el controlador y gestor de Kinect... 31
Figura 3.6 - Transformación de los datos por el método getTotalSkeletons. ... 32
Figura 3.7 - Diferentes estados de rastreo: PositionOnly (izquierda) y Tracked (derecha)... 32
Figura 3.8 - Transformación de los datos por el método isSkeletonAvailable. ... 33
Figura 3.9 - Transformación de los datos por el método getFirstSkeletonPosition. ... 33
Figura 3.10 - Espacio del esqueleto (izquierda) comparado con los valores de profundidad (derecha). ... 33
Figura 3.11 - Transformación de los datos por el método getSkeletonPositions. ... 34
Figura 3.12 - Transformación de los datos por el método getPlayersId. ... 34
Figura 3.13 - Transformación de los datos por el método isPlayerOnPixel. ... 34
Figura 3.14 - Comunicación entre los componentes del sistema. ... 36
Figura 3.15 - Posibles usos de los datos por el modelo ... 37
Figura 3.16 - Comunicación necesaria entre la vista y el modelo. ... 38
Figura 3.17 - Secuencia de llamados para la inicialización ... 39
Figura 3.18 - Secuencia de llamados para la actualización de la vista. ... 39
Figura 3.19 - Secuencia de llamados para terminar la aplicación. ... 40
Figura 3.20 - Idea básica sobre el funcionamiento del Reproductor de Video ... 42
Figura 3.21 - Acción de los movimientos ... 42
Figura 3.22 - Etapa 0 - Modos de reproducción de video de normal a hacia atrás. ... 43
Figura 3.23 - Modo de reproducción normal. ... 44
Figura 3.24 - Flujo de actividad para la reproducción del video con control de movimiento. .... 47
Figura 3.25 - Modo de reproducción hacia atrás ... 48
Figura 3.26 - Etapa 1 - Modos de reproducción de video. ... 49
Figura 3.27 - Modo de reproducción acelerado. ... 50
Figura 3.28 - Intensidad de sonidos de acuerdo a la cantidad de personas y sus movimientos. ... 56
Figura 3.29 - Parte visual de la aplicación Hinchada. ... 56
Figura 3.30 - Reproducción sin fin de un audio. ... 57
Figura 3.31 - Reproducción sin fin de múltiples audios. ... 58
Figura 3.32 - Secuencia de llamados para gestionar audios. ... 60
Figura 3.33 - Representación de sonidos reproducidos en verde, y no reproducidos en rojo. Variación en crecimiento de sonidos a reproducir... 63
Figura 3.34 - Representación de sonidos reproducidos en verde, y no reproducidos en rojo. Variación en disminución de sonidos a reproducir. ... 63
4
Figura 3.36 - Establecimiento de colores con respecto a los identificadores de los jugadores. 67
Figura 3.37 - Idea básica sobre el funcionamiento de „Descubrir la imagen‟ ... 69
Figura 3.38 - Establecimiento de transparencias con respecto a la existencia de los jugadores. ... 73
Figura 3.39 - Establecimiento de niveles transparencias con respecto a la existencia de los jugadores. ... 74
Figura 4.1 - Contexto de las pruebas realizadas. ... 76
Figura 4.2 - Prueba del reproductor del video con una sola persona moviéndose hacia la derecha. ... 77
Figura 4.3 - Prueba del reproductor del video con varias personas en fila hacia la izquierda. . 78 Figura 4.4 - Pruebas realizadas sobre la „Hinchada‟ con todas las personas a la vez. ... 79
Figura 4.5 - Dos personas detectadas como una sola cuando sus esqueletos se tocan. ... 80
Figura 4.6 - Proceso inicial de „Descubrir la imagen‟ con una sola persona. ... 81
Figura 4.7 - Descubriendo la imagen con muchas personas. ... 81
Figura 4.8 - Personas jugando con sus poses y eligiendo qué partes de la imagen descubrir. 82
Índice de diagramas
Diagrama 3.1 - Clase KinectDevice en la etapa de inicialización ... 26Diagrama 3.2 - Clase KinectDevice luego de la etapa de comunicación con el dispositivo físico. ... 29
Diagrama 3.3 - Estructura de los controladores. ... 35
Diagrama 3.4 - Interfaz IModel con dos modelos de ejemplo. ... 36
Diagrama 3.5 - Incorporación de la vista al controlador y modelo. ... 40
Diagrama 3.6 - Incorporación del video a la vista ... 44
Diagrama 3.7 - Clase VideoModel - Incorporación de atributos y métodos. ... 45
Diagrama 3.8 - Comunicación del controlador con el Singleton Configuration. ... 46
Diagrama 3.9 - Incorporación de nuevos atributos a Configuration y nueva comunicación con la vista. ... 49
Diagrama 3.10 - Etapa 2 - Interacción entre los modos de reproducción. ... 51
Diagrama 3.11 - Diagrama de clases de la aplicación del reproductor de video. ... 55
Diagrama 3.12 - Relación entre PlayersModel y AudioManager. ... 59
Diagrama 3.13 - Clase AudioManager incorporando atributos específicos a la biblioteca FMOD ... 59
Diagrama 3.14 - Clase PlayersModel que mantiene el último contador con el que fue actualizado. ... 63
Diagrama 3.15 - Clase PlayersModel - Incorporación de atributos y métodos. ... 66
5
Diagrama 3.17 - Clase DiscoveryModel con sus atributos iniciales. ... 71
Diagrama 3.18 - Clase ColorManager actualizado para retornar color sin controlar su uso. .... 72
Índice de code snippets
Code snippet 3.1 - Incorporación de métodos para atrapar los eventos de flujos de datos. ...27Code snippet 3.2 - Captura de evento de nuevo frame de esqueletos. ...28
Code snippet 3.3 - Captura de evento de nuevo frame de profundidad. ...28
Code snippet 3.4 - Interfaz IController ...29
Code snippet 3.5 - Métodos de VideoController load y unload. ...43
Code snippet 3.6 - Código correspondiente al método update de VideoController. ...46
Code snippet 3.7 - Cuerpo del método draw de la vista. ...47
Code snippet 3.8 - Implementación de update como una máquina de estados. ...51
Code snippet 3.9 - Implementación del método updateActualFrame() utilizado por update(). ...52
Code snippet 3.10 - Método updateState(). ...53
Code snippet 3.11 - Versión final del archivo configuration.xml ...54
Code snippet 3.12 - Cuerpo del método play utilizando la biblioteca FMOD. ...61
Code snippet 3.13 - Cuerpo del método stop utilizando la biblioteca FMOD. ...61
Code snippet 3.14 - Cuerpo del método update de PlayersController junto al transformador privado getAudioCounter. ...62
Code snippet 3.15 - Ruta de los archivos de audio dentro de Audios.xml ...64
Code snippet 3.16 - Porción del cuerpo del método load de la vista relacionado a la reproducción de video de fondo. ...65
Code snippet 3.17 - Cuerpo del método draw al dibujar siluetas sobre el video. ...65
Code snippet 3.18 - Cuerpo del método load del controlador. ...68
Code snippet 3.19 - Cuerpo del método update del controlador actualizado. ...68
Code snippet 3.20 - Cuerpo del método draw de la vista al dibujar textura sobre imagen de fondo. ...70
Code snippet 3.21 - Cuerpo método update del modelo. ...71
Code snippet 3.22 - Cuerpo del método load del controlador. ...72
6
Agradecimientos
A mis papás principalmente, por apoyarme cada día a lo largo de toda mi
carrera incondicionalmente. Por darme todas las posibilidades de llegar a este
punto, y aguantarme en esos días más complicados.
A mi hermanita Antonia, por levantarme el ánimo y darme una sonrisa cada
minuto compartido.
Al resto de mi familia, abuelos, tías y primos, por preocuparse y preguntar
siempre con buena onda.
A Giuli, Marian, Franco, Santi, Jorge, y amigos de la facultad, todos, que se
bancaron mis explicaciones de la tesis, y gracias a ellos realicé las pruebas
7
Resumen
La aparición de nueva tecnología capaz de reconocer los movimientos del cuerpo,
revolucionó las interfaces de usuario. Se encuentra en pleno crecimiento la creación
de aplicaciones interactivas que explotan estas tecnologías para ser usadas, luego, en
diversos ambientes como la medicina, el deporte y exposiciones, entre otros.
Si bien existen herramientas que facilitan el acceso a los datos brindados por los
dispositivos, no se logra simplificar su uso. Para la creación de aplicaciones es
necesario tener un conocimiento previo para lograr la manipulación de los datos, y
luego realizar acciones que respondan a los mismos.
En este trabajo se presenta una plataforma para facilitar la creación de diversas
aplicaciones interactivas que responden a movimientos del cuerpo. El desarrollo se
basó particularmente en el dispositivo Kinect. Esto permite que una persona con
conocimiento limitado en lo que respecta a la detección de los cuerpos, pueda crear su
propia aplicación.
Para la creación de esta plataforma, se investigaron diferentes paseos turísticos
alrededor del mundo que incorporan interactividad. Se consideraron algunas
posibilidades para luego desarrollarlas en la forma de tres aplicaciones interactivas
relacionadas al tenis. El interés demostrado hacia este deporte y en focalizar parte de
la interacción en él, se basó en la impronta que tiene esta disciplina en la ciudad de
Tandil, cuna de tenistas, y la posibilidad de brindar soporte virtual en la posible
creación de un museo interactivo. El desarrollo finalizó con las pruebas
8
Capítulo
1
Capítulo 1
Introducción
El avance tecnológico en estos últimos años, hizo que la interacción entre el humano y
cualquier dispositivo sea mucho más intuitiva. Las pantallas táctiles hicieron posible
este acercamiento, eliminando la necesidad de un teclado y mouse, haciendo posible
la dominación de un dispositivo sólo con el tacto. Pero eso no es todo, la incorporación
de reconocimiento de movimientos del cuerpo, revolucionó la manera de interactuar
con una máquina.
Wii Remote[1], Leap Motion[2] y Kinect[3] son una serie de controladores de juegos y
entretenimiento capaces de reconocer los movimientos del cuerpo, para luego realizar
acciones con su análisis. El dispositivo Kinect se destaca por la utilización de
diferentes sensores para la detección completa del cuerpo humano. Fue desarrollado
por Microsoft para la videoconsola Xbox 360 y es capaz de reconocer gestos,
comandos de voz, objetos e imágenes.
La aparición en el mercado de estas innovaciones provocó una revolución en la
creación de aplicaciones altamente interactivas. Se pueden apreciar en diferentes
disciplinas, por ejemplo en la medicina[4], con el uso del dispositivo Kinect, para el
desarrollo de habilidades en personas con necesidades especiales derivadas de la
discapacidad así como también en diferentes tipos de rehabilitación; en campo del
deporte[5] hay sistemas para mejorar distintas técnicas de juego; y en el
entretenimiento[6], se puede ver la utilización de Video Mapping[7] en diversos eventos
como recitales y desfiles.
Más aún, su alcance no termina ahí: la interactividad se puede ver en crecimiento en
muchos aspectos de la vida cotidiana, abriendo una cantidad infinita de posibilidades
9
1.1 Motivación
Si bien existen varias herramientas[8], para el desarrollo de aplicaciones interactivas,
como el SDK para Kinect, se necesita de un conocimiento previo para la manipulación
de los datos y las diferentes acciones que se quieran realizar. Así, se presentó el
desafío de desarrollar una serie de aplicaciones que utilicen el dispositivo Kinect y
manipulen los datos de diversas maneras probándolo en un escenario específico.
Hoy en día existe en el mundo un crecimiento de museos interactivos. Se llaman así a
aquellos museos que rompen la barrera del „No tocar‟ y en donde lo prohibido es
quedarse quieto. Con el objetivo de transformar un simple paseo por el museo, en un
paso más allá, con rasgos aún más interesantes y atrapantes. De esta forma un
recorrido silencioso y cauteloso puede transformarse en una experiencia divertida e
innovadora.
Con la incorporación de nuevas tecnologías, los museos permiten aprender jugando.
La unión del arte y la tecnología abre un gran camino de posibilidades. La
interactividad se lleva a cabo a través de dispositivos como los celulares y tabletas,
como así también el Kinect previamente mencionado.
En la ciudad de Tandil, Buenos Aires, se encuentra el proyecto de inaugurar un museo
de tenis. Pero este museo no pretende ser uno más: será el primer museo interactivo
de la ciudad, en donde las personas que lo visiten puedan participar de diferentes
actividades divertidas y atrapantes, donde adultos y niños puedan disfrutarlo de una
manera diferente. Esto generaría un encanto superior a la ciudad, atrayendo así a una
mayor cantidad de turistas.
La principal motivación en desarrollar una serie de aplicaciones que puedan ser
utilizadas en este museo, es la de evaluar qué tan reutilizables pueden ser, para qué
público son adaptables y la facilidad de que en un futuro una persona ajena al
proyecto pueda crear una aplicación.
1.2 Solución propuesta
El objetivo de este trabajo, es el de incorporar la parte interactiva a dicho museo de
tenis a través de la implementación de una serie de aplicaciones que utilizan Kinect.
Estas aplicaciones tendrán su foco en el museo, pero su alcance no será limitado. Se
10
Se pretende propiciar un ambiente en el que los adultos puedan divertirse como niños,
y que los niños disfruten del recorrido por un museo sin las limitaciones que
usualmente se deben tener. Considerando este objetivo, se desarrollarán algunas
aplicaciones que involucren la manipulación de video, audio y también imágenes.
Las aplicaciones van a tener el fin de mantener al público en continuo movimiento. En
todo momento, se mantendrá el enfoque en el objetivo principal que es la de no tener
limitaciones en el alcance del uso de las aplicaciones y la facilidad de la creación de
una nueva.
1.3 Organización del informe
El presente informe se divide en 5 capítulos. El Capítulo 1 es el actual, donde se
encuentra una introducción general al proyecto.
El Capítulo 2 llamado Interactividad, contiene el contexto actual y antecedentes
relacionados al trabajo. Se introducen conceptos de interactividad con el usuario y se
muestra la evolución de las tecnologías relacionadas. Se hace especial hincapié en el
dispositivo Kinect el cual se utiliza a lo largo de todo el proyecto. También se muestra
un relevamiento de algunos museos y paseos existentes que utilizan algún tipo de
tecnología para incluir interactividad. Por último, se proporciona un panorama general
de las tecnologías usadas para la creación de las aplicaciones.
El Capítulo 3, Diseño e Implementación, es específico y central al proyecto. Se
encuentra dividido en dos secciones: en primer lugar se expone la arquitectura
propuesta en donde se explican todos sus componentes y luego, se detalla la
instanciación de la arquitectura en tres diferentes aplicaciones.
El Capítulo 4 se basa en los resultados de las pruebas realizadas sobre las
aplicaciones que fueron explicadas en el Capítulo 3. Comienza detallando el contexto
de las pruebas, los elementos utilizados y la cantidad de personas que asistieron.
Luego se pasa a describir los resultados de las pruebas, aplicación por aplicación,
indicando aquellos aspectos positivos, y también aquellos que deben corregirse.
El Capítulo 5, engloba las conclusiones del trabajo en dos secciones: en primer lugar
se detallan los resultados obtenidos con respecto a los objetivos propuestos; luego se
proponen posibles trabajos futuros sobre la plataforma y las aplicaciones
11
Al finalizar se encuentra la sección de Bibliografía, en donde se listan todas aquellas
12
Capítulo
2
Capítulo 2
Interactividad
En este capítulo se introducen los conceptos de interactividad con el usuario. Se hará
un recorrido sobre la evolución de la tecnología. Como la plataforma creada en este
proyecto se basa en el dispositivo Kinect, se incluirán las especificaciones necesarias
relacionadas a su uso. Luego se mostrará la forma en que se utiliza la interactividad
específicamente en el contexto de paseos y museos. Por último, se dará un panorama
general de las tecnologías usadas para la creación de las aplicaciones.
2.1 Evolución de la Interfaz de usuario
La interfaz de usuario es el medio con que el usuario puede comunicarse con una
máquina. Éstas fueron evolucionando a través del tiempo, siendo cada vez más
intuitivas. Se pueden clasificar según la forma de interacción con el usuario, CLI, GUI o
NUI (Figura 2.1).
Figura 2.1 - Evolución de las interfaces de usuario.
Las CLI[9], command-line interface o también interfaz de líneas de comando, permiten
a los usuarios dar instrucciones a algún programa informático por medio de una línea
de texto simple. Como se basa únicamente en la entrada y salida de texto, toda la
13
realiza generalmente en su totalidad con un teclado. Esta interfaz existe casi desde los
comienzos de la computación.
Las GUI[10], graphical user interface, en español interfaz gráfica de usuario, surgen
como evolución de las interfaces de línea de comandos. Éstas cuentan con el uso de
imágenes gráficas, incluyendo ventanas, íconos y menús. Estos objetos son
manipulados por un mouse y por lo general se pueden operar de forma limitada por un
teclado también. Su principal uso, consiste en proporcionar un entorno visual sencillo
que permita la comunicación con el sistema operativo de una máquina.
Las NUI[11], natural user interface, es el tipo de interfaz de usuario en las que se
interactúa con un sistema sin utilizar dispositivos de entrada. La idea general es que
en lugar de tener medios artificiales de entrada, el usuario interactúa con la máquina
de una manera más similar a la que utiliza para interactuar con las personas y objetos
en el mundo real, y de una manera más directa. Esto quiere decir, interactuar a través
del tacto, los gestos del cuerpo, las expresiones faciales, y el lenguaje.
Figura 2.2 - Interfaces de usuario (CLI, GUI y NUI respectivamente)
Hoy nos encontramos en el inicio de la próxima revolución, pasando de interfaces
gráficas de usuario (GUI) a interfaces naturales de usuario. La sociedad está en
constante movimiento, llena de información y muy comunicativa. Es por esto que la
computadora de escritorio ya no cumple con las necesidades y demandas requeridas
por una sociedad en continua evolución. En la actualidad, se usan los teléfonos
móviles, tabletas y pantallas táctiles de variados tamaños, incluso hasta del tamaño de
una mesa de conferencia para permanecer conectados, satisfacer necesidades y
lograr objetivos. Sin embargo, NUI es más que tocar algo con el dedo en lugar de
hacer clic con un mouse. Wii Remote (WiiMote)[1], Leap Motion[2] y Kinect[3] son
ejemplos de una serie de controladores de juegos y entretenimiento que son capaces
de reconocer los movimientos del cuerpo (o partes de ellos), y realizar acciones con su
14
Figura 2.3 - Dispositivo WiiMote
WiiMote[1] (Figura 2.3) es un dispositivo que tiene la capacidad de detección de
movimiento. Permite al usuario manipular e interactuar con elementos en pantalla a
través de reconocimiento de gestos y señalando a través del uso de tecnología de
acelerómetro ADXL330 y sensor óptico PixArt. Es el controlador principal para
Nintendo Wii, que gracias al sensor óptico, le permite determinar el lugar al que el
Wiimote está apuntando, independientemente del tipo o tamaño de la televisión.
Figura 2.4 - Dispositivo Leap Motion
Leap Motion[2] (Figura 2.4) es un dispositivo sensor que soporta movimientos de la
mano y de los dedos como entrada, análogo a un mouse, pero no requiere contacto
con las manos. El corazón del dispositivo consta de dos cámaras y tres LEDs
infrarrojos. Cuenta con un gran espacio de interacción que toma la forma de una
pirámide invertida. Anteriormente, el rango de visión se limitaba a 60 cm, luego de
15
Figura 2.5 - Dispositivo Kinect
Kinect[3] (Figura 2.5) es una línea de sensores de movimiento de entrada para
Microsoft Xbox 360 y Xbox One como también para PCs. El uso de cámaras y otros
complementos periféricos, permite a los usuarios controlar e interactuar con su
consola/computadora sin la necesidad de un controlador de juego, a través de una
interfaz natural de usuario usando gestos y comandos de voz. Como el proyecto
desarrollado se basa exclusivamente en el dispositivo Kinect, a continuación se
incluyen detalles del dispositivo:
2.1.1 Kinect
Figura 2.6 - Componentes del dispositivo Kinect
El dispositivo Kinect tiene una serie de componentes que hacen a su funcionamiento[12]
que se muestran en la Figura 2.6. Una cámara RGB con una resolución de 1280x960
permite la captura de imágenes de colores. Un emitidor infrarrojo (IR) se encarga de
16
rayos que vuelven reflejados. Estos rayos luego son convertidos en información de
profundidad midiendo la distancia entre un objeto y el sensor.
Un arreglo de cuatro micrófonos captura sonidos. Por la cantidad de micrófonos es
posible grabar audio, como así también encontrar la ubicación de la fuente de sonido y
la dirección de la onda de audio. Por último, un acelerómetro de 3 dimensiones con un
rango de 2G, donde G es la aceleración correspondiente a la gravedad, permite
determinar la orientación del Kinect.
Figura 2.7 - Rango de inclinación
El ángulo de visibilidad del dispositivo Kinect es de 43° en el espacio vertical, y de 57°
en horizontal. Debido a la inclinación motorizada, el espacio vertical puede moverse
27° hacia arriba o hacia abajo como se puede ver en la Figura 2.7.
Si están habilitados, el Kinect puede capturar audio, color y datos de profundidad, y
procesar los datos de profundidad para generar datos de esqueletos. Estos datos son
presentados en la forma de flujos de datos que se pueden controlar y acceder desde
las aplicaciones a través del SDK del dispositivo Kinect. Las aplicaciones
desarrolladas para este proyecto en particular, sólo utilizan los flujos de datos de
profundidad y de esqueletos.
El arreglo de micrófonos captura datos de audio a una resolución de 24 bits. Se
pueden ver en color lila en la Figura 2.8. Esto permite una precisión en un rango
dinámico de datos de voz, desde un habla normal a tres o más metros de distancia,
hasta una persona gritando. Además de capturar audio en alta definición, permite
focalizar en un audio proveniente de un lugar en particular, identificar la dirección del
17
Figura 2.8 - Arreglo de micrófonos del dispositivo Kinect marcados en violeta.
El flujo de datos de color es simplemente la imagen obtenida como si fuera a través de
una cámara web. Está disponible en diferentes resoluciones y formatos. El formato
determina si el flujo está codificado como RGB, YUV o Bayer. Sólo se pueden utilizar
una resolución y un formato a la vez. El sensor utiliza una conexión a través del puerto
USB lo que provee un determinado ancho de banda. La elección de la resolución
determina cómo es usado ese ancho de banda. Las imágenes en alta definición
utilizan más datos, pero se actualizan menos frecuentemente. Al bajar la resolución, se
actualizan más frecuentemente pero se pierde la calidad de la imagen debido a la
compresión.
Figura 2.9 - Frames de profundidad.
Cada frame del flujo de profundidad está formado por píxeles que contienen la
distancia en milímetros desde la cámara hasta el objeto más cercano. Este flujo une
dos tipos de datos distintos. Por un lado se encuentra la distancia, pero también se
toma en cuenta los datos de los jugadores segmentados. Cada dato es un entero
indicando el índice de un único jugador detectado (Figura 2.9).
El dispositivo Kinect procesa el flujo de profundidad para identificar hasta seis figuras
humanas. Los datos de la segmentación de jugadores sólo están disponibles si está
habilitado el rastreo de esqueletos. El valor „0‟ indica que no se encontró ninguna
18
jugadores. Un uso muy común de esta segmentación es para separar un usuario
específico de una imagen de color o de profundidad.
Figura 2.10 - Frames de esqueletos.
El rastreo de esqueletos permite al dispositivo Kinect reconocer personas y seguir sus
movimientos. Utilizando la cámara infrarroja, Kinect puede reconocer hasta 6 personas
en el área de visibilidad del sensor. De estos, sólo dos son rastreados en detalle, esto
es, se pueden detectar sus articulaciones en el espacio y rastrearlas en el tiempo
(Figura 2.10).
Los esqueletos en un frame pueden tener un estado de seguimiento de „rastreado‟ o „sólo posición‟. Aquellos „rastreados‟ proveen información detallada sobre la posición
de veinte articulaciones del cuerpo del usuario (Figura 2.11). En cambio, cuando un
esqueleto tiene un estado de „sólo posición‟, se tiene la información sobre la posición
del usuario, pero ningún detalle con respecto a las articulaciones.
19
Las aplicaciones pueden utilizar cada articulación para realizar acciones. Por ejemplo,
se puede utilizar la mano para guiar un cursor o simplemente dibujar la posición de las
articulaciones en pantalla. Una articulación también se puede clasificar en tres
estados: „rastreada‟ para una articulación claramente visible, „inferida‟ cuando no está claramente visible y se infiere su posición, o „no rastreada‟.
En octubre de 2014, surgió una nueva versión del SDK del dispositivo Kinect[13]. Se
amplió el campo de visión horizontal y vertical para la captura de profundidad y de
color. La captura de color es HD, los infrarrojos son independientes de la luz y hubo
mejoras con los micrófonos. La cantidad de esqueletos rastreados en detalle aumenta
de 2 a 6, y la cantidad de articulaciones rastreadas pasan de 20 a 25 cada uno,
incluyendo los pulgares. También es posible utilizar el dispositivo desde múltiples
aplicaciones.
2.2 Interactividad en paseos y museos
En la actualidad existe en el mundo un crecimiento de museos interactivos. Se llaman
así a aquellos museos que rompen la barrera del „No tocar‟ y en donde lo prohibido es
quedarse quieto. Con el objetivo de transformar un simple paseo por el museo, en un
paso más allá, con rasgos aún más interesantes y atrapantes. De esta forma un
recorrido silencioso y cauteloso puede transformarse en una experiencia divertida e
innovadora.
Con la incorporación de nuevas tecnologías, los museos nos permiten aprender
jugando. La unión del arte y la ciencia abre un gran camino de posibilidades. La
interactividad se lleva a cabo a través de dispositivos como los celulares y tabletas,
como así también el Kinect previamente mencionado.
El Museo del Louvre[14] incluyó la interactividad a sus recorridos utilizando códigos QR
y un dispositivo portátil Nintendo 3DS, ideal para descubrir el museo parisino (Figura
2.12). Este dispositivo pasó a ser el audio-guía oficial, sustituyendo a los modelos
tradicionales. Incluye mapas interactivos, recreaciones en 3D de obras e información
adicional sobre las mismas. La información brindada permite ser traducida a los
principales idiomas como el español, francés, alemán, japonés, coreano, italiano o
20
Figura 2.12 - Interacción en el Museo de Louvre con el uso de Nintendo 3DS y códigos QR.
Museon[15] es un museo de cultura y ciencia que incorpora interactividad en todas sus
exposiciones. Cree firmemente en la idea de que se aprende más rápido si se puede
poner en práctica la teoría que se aprendió. Repartidos por todo el museo se
encuentran unos terminales que permiten a las personas identificarse con un código
de barras y formula preguntas para comprobar la significatividad educativa de la visita.
Figura 2.13 - Juego en Museon con la utilización de PuppyIR.
A través de la tecnología del proyecto PuppyIR[16], el museo permite crear recorridos
interactivos en equipos, comenzando y terminando en terminales multi-táctiles (Figura
2.13). Durante el recorrido, el equipo debe recolectar elementos para luego llevarlos a
una terminal al finalizar. Aquí, el equipo deberá unir los elementos recolectados con
21
Figura 2.14 - Live Projection Mapping - EVA 2013
EVA[17] es la conferencia de desarrollo de videojuegos más importante de
Latinoamérica. Se realiza anualmente desde 2003 y cuenta con talleres y conferencias
especialmente pensadas para presentar las últimas novedades en áreas como
Programación, Arte, Publishing y Game Design. En la edición 2013 se realizó una
proyección en vivo sobre un grupo de bailarines utilizando Kinect[18]. Se debió ajustar
manualmente su posición para que su punto de vista coincida con el punto de vista del
proyector (Figura 2.14).
Figura 2.15 - Pisos interactivos en eventos.
La empresa Piso Interactivo[19] está ubicada en Guadalajara, México. Son creadores
de software e instalaciones interactivas para museos, diseño de interiores,
ambientación, eventos sociales y exposiciones. La Figura 2.15 muestra el uso de una
22
Figura 2.16 - ‘Play Work Build’ en el National Building Museum.
National Building Museum[20], de Washington DC, es un museo de arquitectura, diseño,
ingeniería, construcción y planeamiento urbano. Incorporó a sus visitas una aplicación
interactiva para los niños llamada „Play Work Build‟[21] que usa el cuerpo para construir
paredes virtuales al mantenerse quietos y destruirlas con los movimientos. Esto se
desarrolló gracias a la utilización del dispositivo Kinect (Figura 2.16).
Figura 2.17 - ‘Strike a pose’ en Cleveland Museum of Art.
Cleveland Museum of Art[22] [23], ubicado en Ohio, se especializa en arte Asiático y
Egipcio. Su recorrido ofrece al espectador una serie de aplicaciones que permiten
interactuar con el arte, como „Strike a pose‟ que reta a imitar las poses de diferentes esculturas. Como se puede ver en la Figura 2.17, al igual que „Play Work Build‟, utiliza
23
Figura 2.18 - Juego interactivo relacionado al Básquet en Chicago Sports Museum.
Chicago Sports Museum[24] es un museo que fue diseñado con un foco en la
interactividad y entretenimiento. Una de las actividades más interesantes que este
museo brinda, es la de imitar alguna jugada específica de Básquet, Fútbol, Baseball, o
Jockey. En la imagen se puede ver un juego de Básquet en un contexto similar al real,
que gracias al Kinect, un avatar de un jugador profesional sigue los movimientos de la
persona que lo juega (Figura 2.18).
Figura 2.19 - Avatares en Sedena.
En el museo creado en honor a las Fuerzas Armadas de México[25] se incluyó una
exhibición digital multi sensorial. Para ello, se realizaron instalaciones electrónicas que
24
logró incorporar modelos en 3D que al detectar la presencia de una persona cobran
vida y simulan los movimientos que realizan los visitantes (Figura 2.19).
2.3 Tecnologías utilizadas
El próximo capítulo se centra en el diseño e implementación de una serie de
aplicaciones interactivas. Estas aplicaciones utilizan video y audio para su
comunicación con el usuario. Existen diversas tecnologías que permiten la
manipulación de estos elementos.
Con respecto a la reproducción de video, se utilizó una biblioteca que permite
manipular los videos frame a frame. Emgu CV[26] es un wrapper para la biblioteca de
procesamiento de imágenes OpenCV. De esta manera se permite acceder a las
funciones de OpenCV[27] desde cualquier lenguaje .NET.
Luego, para la reproducción de audio se utilizó la biblioteca FMOD[28] que puede
manejar a los sonidos en un alto nivel, incorporando diferentes efectos. El uso de esta
biblioteca permite una mayor extensibilidad a la hora de incorporar nuevas
aplicaciones de audio. Reproduce y mezcla archivos de sonido de diversos formatos
en muchos sistemas operativos.
Para manipular la vista a nivel de píxel, o simplemente mostrar imágenes o videos sin
la necesidad de dinámicamente manipularlos, la vista XNA[29] es ideal. Brinda en un
alto nivel la interacción de la aplicación con la vista. Permite mostrar imágenes y
videos en diferentes capas superpuestas, y la creación de una nueva textura a mostrar
es muy sencilla.
A continuación se muestra el diseño de una plataforma para la creación de
aplicaciones interactivas. Luego, junto al uso de las tecnologías, se realiza la
25
Capítulo
3
Capítulo 3
Diseño e Implementación
El capítulo de implementación está dividido en dos partes. En primer lugar se describe
la arquitectura de software de la plataforma desarrollada. En esta sección se
presentan los componentes (y relaciones entre ellos) de las aplicaciones realizadas a
modo de ejemplo de utilización de la plataforma, como el funcionamiento de cada
aplicación. En segundo lugar se muestran también diagramas y partes de código
necesarios para ayudar a describir el funcionamiento de la plataforma descripta.
3.1 Arquitectura propuesta
Tal como se describió en el Capítulo 2, el desarrollo se centra en poder capturar y
distribuir información brindada por el Kinect, de una forma estandarizada y eficiente.
La plataforma está inclinada hacia la creación de aplicaciones para el entretenimiento,
interactuando con el público a través de la vista y el oído.
En las siguientes secciones se explicarán los componentes que forman parte de la
plataforma, para llevar a cabo cualquier aplicación deseada. El patrón de la
arquitectura está basado en Model-View-Controller[30]. Cada sección detallará en
manera progresiva la creación del modelo, del controlador y de la vista, para llegar por
último a sus versiones finales.
3.1.1 Controlador
Al inicio del proyecto, se tenía en claro que se iban a desarrollar una serie de
aplicaciones las cuales serían controladas por las personas, a través del dispositivo de
Kinect. Para este fin, se debía crear un gestor que sea el encargado de la
comunicación con el aparato físico. Toda comunicación entre el gestor y el dispositivo
físico se realiza a través del Kinect SDK, que brinda diversas posibilidades para el
26
Figura 3.1 - Interacción del dispositivo Kinect con la aplicación a través del Kinect SDK
El gestor, llamado KinectDevice, se fue implementando progresivamente. A lo largo de
los siguientes párrafos se explicará el camino tomado para su desarrollo, hasta llegar a
la versión final con todos sus métodos y atributos. Sus datos son crudos, y el
controlador es el encargado de tomar estos datos, transformarlos y actualizar el
modelo de datos.
La funcionalidad indispensable para comenzar a utilizar el gestor, es la inicialización.
Dentro de initializeKinect se conecta al dispositivo físico, y devuelve un dato para
indicar si la conexión fue exitosa o no. Internamente, busca el primer sensor conectado
y lo guarda como un atributo de la clase para ser usado en cualquier momento. Por
último, ejecuta la acción Start sobre el sensor.
Una vez inicializado, es fundamental la liberación del recurso físico. Por tal motivo, se
incorporó stopKinect. Aquí, a través del sensor guardado, le indica al Kinect que frene
el flujo de datos.
En el curso de esta primera etapa, se incluyeron sólo aquellos métodos primitivos. En
el Diagrama 3.1 se pueden ver aquellos que permiten la inicialización y la liberación
del dispositivo. También se incluye el método privado que es utilizado internamente
para obtener el primer sensor conectado, y el atributo privado que es fijado por el
mismo.
27
Como se mencionó en el capítulo anterior, para poder utilizar los datos brindados por
el dispositivo Kinect, se deben habilitar los diferentes flujos que se vayan a utilizar.
Cada flujo de datos dispara un evento indicando un nuevo frame. Se debe tener un
método asociado a cada uno de ellos para poder atraparlos y así guardar los datos
necesarios. Para el propósito actual sólo se van a utilizar dos: Skeleton Stream y
Depth Stream. Como fue descripto anteriormente, el Skeleton Stream brinda
información sobre los esqueletos encontrados, y el Depth Stream sobre la profundidad
de estos esqueletos, identificando a cada jugador. Su necesidad se verá especificada
en las próximas secciones.
Se debió modificar initializeKinect para incorporar los eventos de Kinect. En el caso
de que se encuentre un sensor disponible, se establecen aquellos métodos
encargados de atrapar el evento (Code snippet 3.1). Entonces, si el flujo de datos está
habilitado, en cada momento en el que kinect tiene un nuevo frame disponible, activa
el evento y KinectDevice puede tomar los datos deseados y los mantiene actualizados
para tenerlos disponibles cuando sean solicitados por algún controlador. En el caso en
que en el futuro se quiera incorporar un nuevo flujo de datos, es aquí donde se debe
incluir el nuevo evento especificando la funcionalidad determinada.
if (null != sensor) {
// Agrega controlador de evento para cuando haya nuevo frame de esqueleto
sensor.SkeletonFrameReady += skeletonFrameReady;
// Agrega controlador de evento para cuando haya nuevo frame de profundidad
sensor.DepthFrameReady += depthFrameReady; }
Code snippet 3.1 - Incorporación de métodos para atrapar los eventos de flujos de datos.
El evento disparado cuando un frame de esqueleto está listo, emite sus argumentos
del tipo SkeletonFrameReadyEventArgs. Dentro de los argumentos se encuentra un
SkeletonFrame el cual el gestor utiliza para tomar los datos de los esqueletos en forma
28
private void skeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null) {
if (skeletons == null)
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons); }
} }
Code snippet 3.2 - Captura de evento de nuevo frame de esqueletos.
El evento disparado cuando un frame de profundidad está listo, es similar al anterior.
Sus argumentos contienen un DepthImageFrame dentro de
DepthImageFrameReadyEventArgs. El DepthImageFrame es utilizado para tomar los
datos de los píxeles de profundidad, y guardarlos en un arreglo de tipo
DepthImagePixel (Code snippet 3.3).
private void depthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame depthImageFrame = e.OpenDepthImageFrame())
{
if (depthImageFrame != null) {
if (depthPixels == null)
depthPixels = new Skeleton[depthImageFrame.PixelDataLength];
depthImageFrame.CopyDepthImagePixelDataTo(depthPixels); }
} }
Code snippet 3.3 - Captura de evento de nuevo frame de profundidad.
Se debe permitir a cada aplicación habilitar el o los flujos de datos que se utilicen, para
no estar recibiendo frames que son totalmente innecesarios. Se provee este servicio a
través de enableSkeletonStrem e enableDepthStream para habilitar cada uno de los
flujos previamente mencionados.
Durante el desarrollo de la primera aplicación se vio necesario borrar aquellos
esqueletos obtenidos del SkeletonFrame. En efecto, también se incorporó esta nueva
posibilidad implementando resetSkeletons, el cual tiene como única funcionalidad
eliminar el arreglo de esqueletos.
Resumiendo, en esta etapa se agregó funcionalidad relacionada a los flujos de datos.
29
como métodos privados, aquellos que se encargan de atrapar los eventos y mantener
actualizados los datos: depthPixels y skeletons. Los getters son indispensables para
obtener aquellos datos actualizados. Por último, se permite borrar datos. En el
Diagrama 3.2 se pueden ver resaltadas aquellas actualizaciones de la clase.
Diagrama 3.2 - Clase KinectDevice luego de la etapa de comunicación con el dispositivo físico.
El próximo paso es crear un controlador que utilice el gestor de Kinect como un
recurso. Tal como se mencionó anteriormente, el controlador se encarga de inicializar
el dispositivo Kinect, y luego tomará los datos crudos de KinectDevice, los
transformará y actualizará al modelo. Para mejorar la abstracción, y permitir así en un
futuro la incorporación de cualquier tipo de controlador de una manera sencilla, se
formalizó una estructura.
Es así que se llegó al diseño de los controladores. Cada controlador creado debe
implementar una interfaz IController. Sus métodos se pueden dividir fácilmente en tres:
load, update y unload, estandarizando la división de funcionalidad (Code snippet 3.4).
interface IController
{
//Inicialización de cualquier recurso necesario
bool load();
//Transformación de datos //Actualización del modelo
void update();
//Liberación de los recursos
void unload(); }
Code snippet 3.4 - Interfaz IController
Dentro del load, el controlador debe inicializar cualquier recurso que vaya a ser
30
específicas de este proyecto, es el KinectDevice. Otros recursos utilizados también en
esta ocasión pueden ser un gestor de colores y/o un gestor de audio. Estos se verán
explicados a lo largo de las secciones 3.2.2 y 3.2.3, junto con las últimas dos
aplicaciones que los utilizan.
Si se produjo algún problema dentro de la inicialización, el método se encarga de
indicar la situación a través de un booleano de retorno (Figura 3.2). De esta manera, la
vista es capaz de reaccionar. Sus acciones se verán en la sección correspondiente al
explicar el componente de la vista.
Figura 3.2 - Secuencia de llamados para la inicialización
El método unload debe contener la funcionalidad para liberar los recursos. Cada
controlador tendrá que liberar dentro de este método, todos sus recursos utilizados
(Figura 3.3). En este proyecto en particular, todos los controladores utilizan Kinect, por
lo tanto deberán liberarlo a través de kinectDevice.stopKinect().
Figura 3.3 - Secuencia de llamados para terminar la aplicación.
El update se ejecuta constantemente. En su cuerpo, el controlador debe realizar un
análisis de los datos y actualizar el modelo con los datos necesarios (Figura 3.4). Esta
31
Figura 3.4 - Secuencia de llamados para la actualización del modelo.
En este proyecto en particular, dentro del método update se debe encontrar la
comunicación con el gestor de Kinect. Previo a la actualización del modelo, se deben
transformar los datos. La transformación de los datos es la misma para cualquier
controlador que utilice la clase KinectDevice.
Por este motivo, se decidió crear una clase abstracta, KinectController, que sea un tipo
de IController. En ella se encontrarán todos los métodos necesarios para evitar la
repetición de código, y así facilitar la creación de un nuevo controlador dependiente de
Kinect. En la Figura 3.5 se puede ver su comunicación con KinectDevice.
Figura 3.5 - Comunicación necesaria entre el controlador y gestor de Kinect.
En las siguientes secciones se verá la forma en que cada aplicación desarrollada
permitió incorporar nuevos métodos y modificar la estructura básica de la plataforma
planteada, explicando también el uso de cada uno. A continuación se pasará a
mencionar aquellos que fueron agregados a KinectController a lo largo de todo el
desarrollo.
Como se nombró anteriormente, a través del SkeletonFrame, se mantiene un arreglo
de tipo Skeleton. Esta información brinda al controlador un conjunto amplio de datos y
en diversas formas. En este caso se puede determinar si hay algún esqueleto
traqueado, acceder a la cantidad de esqueletos encontrados, o también a sus
32
Figura 3.6 - Transformación de los datos por el método getTotalSkeletons.
La cantidad de esqueletos encontrados se obtiene a través de getTotalSkeletons()
(Figura 3.6). Como se mencionó en las especificaciones del Kinect dentro del capítulo
2, cada esqueleto tiene la propiedad TrackingState. Sus posibles valores son
PositionOnly, Tracked, o NotTracked. El estado Tracked indica que el esqueleto tiene
sus articulaciones rastreadas. Un esqueleto con PositionOnly sólo contiene su posición
general. NotTracked significa que no se rastreó el esqueleto. Este método en particular
cuenta aquellos esqueletos que como TrackingState tengan PositionOnly o Tracked
(Figura 3.7).
Figura 3.7 - Diferentes estados de rastreo: PositionOnly (izquierda) y Tracked (derecha)
Para consultar si un hay un esqueleto disponible, se puede utilizar el método
isSkeletonAvailable(). Se encarga de devolver un boolean indicando si existe en aquel
arreglo de esqueletos, algún esqueleto con TrackingState igual a Tracked (Figura 3.8).
33
Figura 3.8 - Transformación de los datos por el método isSkeletonAvailable.
A través del método getFirstSkeletonPosition(), se obtiene la posición del primer
esqueleto rastreado, es decir, con TrackingState igual a Tracked (Figura 3.9).
Nuevamente, este método consulta internamente por el primer esqueleto rastreado. La
posición de retorno es de tipo Point, pero la posición del esqueleto es de tipo
SkeletonPoint. Por lo tanto fue necesaria la incorporación de la funcionalidad para
solucionar la diferencia. Se incorporó un nuevo método a KinectDevice.
Figura 3.9 - Transformación de los datos por el método getFirstSkeletonPosition.
El método skeletonPointToScreen se encarga de mapear un SkeletonPoint a un
punto de pantalla. Los puntos de esqueletos están expresados en metros mapeados a
la habitación (Figura 3.10). El sensor del Kinect tiene un CoordinateMapper que tiene
la capacidad de traducir estos puntos a un DepthPoint a través del método
MapSkeletonPointToDepthPoint y la resolución de pantalla. Un DepthPoint se mide
en milímetros, y por lo contrario al punto de esqueleto, representa la posición dentro
del frame. Entonces, puede devolver un Point inicializado con los valores X e Y del
DepthPoint obtenido.
Más adelante se verá que también fue necesario consultar por todas las posiciones de
todos los esqueletos. Para ello existe también la transformación de Figura 3.10 - Espacio del esqueleto (izquierda) comparado con los valores de
34
getSkeletonPositions(), que devuelve un arreglo de Point de la longitud del arreglo de
esqueletos (Figura 3.11). En cada elemento guarda la posición mapeada a pantalla de
cada Skeleton.Position que se encuentra con un TrackingState de PositionOnly o
Tracked. En el caso de que el esqueleto no está traqueado, se inicializa un Point con
valores negativos indicando la situación.
Figura 3.11 - Transformación de los datos por el método getSkeletonPositions.
Volviendo a los diferentes tipos de frames, a través del DepthFrame se mantiene un
arreglo de tipo DepthImagePixel. El gestor de Kinect sólo brinda un método,
getDepthPixels(), para que cualquier controlador lo pueda acceder. KinectController se
encarga de recorrer este arreglo para quedarse sólo son los datos necesarios. Así se
forma un arreglo de enteros indicando el id de cada jugador en cada píxel (Figura
3.12). El método encargado de la transformación es getPlayersId().
Figura 3.12 - Transformación de los datos por el método getPlayersId.
También es posible convertirlo en un arreglo de booleanos. De esta manera, en cada
posición del arreglo se indica si hay o no algún jugador (Figura 3.13).
Figura 3.13 - Transformación de los datos por el método isPlayerOnPixel.
Entonces, a lo largo de esta etapa, se obtuvo una interfaz que debe implementar todo
controlador. Esta interfaz incluye métodos para la inicialización, actualización y
finalización. Como todo controlador dependiente de Kinect debe transformar los datos
de KinectDevice, se pensó en una clase abstracta que contenga a los
transformadores. Luego, cada controlador específico para cada aplicación deberá
extenderlo. A continuación se muestra la relación entre la interfaz IController, la clase
abstracta KinectController y el gestor KinectDevice (Diagrama 3.3). El método
35
Diagrama 3.3 - Estructura de los controladores.
El gestor de Kinect no tiene ningún conocimiento de su entorno. Éste es simplemente
un proveedor de servicios a los controladores que lo necesiten. En una mirada
general, se puede decir que los controladores son los encargados de inicializar el
gestor, transformar los datos, y, una vez finalizada la ejecución, liberarlo.
Cada método de los controladores, heredados de IController, son en algún momento
llamados desde alguna vista. Previo a actualizar la interfaz de usuario, se recuperarán
los datos del modelo. La vista será desarrollada más adelante. A continuación se
procederá a explicar el modelo de datos.
3.1.2 Modelo
El modelo es el encargado de generar un objeto basado en las actualizaciones del
controlador que luego la vista pueda utilizar para actualizarse. En la Figura 3.14 se
muestra la comunicación necesaria entre los distintos componentes del sistema. En
esta sección se procederá a explicar sólo las relaciones que se encuentran resaltadas,
esto es, la relación con el controlador explicado en la sección anterior y la
36
Figura 3.14 - Comunicación entre los componentes del sistema.
Cualquier modelo creado deberá brindar a la vista un método que le devuelva un
objeto específico. Como el tipo de datos que necesita la vista depende de cada vista
específica y del contexto de la aplicación, el tipo devuelto por el modelo debe ser
genérico.
Para abstraer todo tipo de modelo, se creó la interfaz IModel que sólo contiene dos
métodos, update y getData. El primero se encarga de crear un objeto a partir de los
atributos actualizados por el controlador, para que luego pueda ser devuelto en el
segundo. getData devuelve un objeto de tipo object, que luego la vista sabrá entender.
Entonces, cada modelo creado deberá implementar a esta interfaz, e instanciar un
objeto específico a una vista y a un determinado contexto (Diagrama 3.4).
Diagrama 3.4 - Interfaz IModel con dos modelos de ejemplo.
Cada implementación de un modelo es específica a la funcionalidad deseada de cada
aplicación. Previo a poder crear el objeto de devolución, el modelo deberá tener todos
sus atributos actualizados por el controlador. Dependiendo del objetivo del modelo, se
37
contenga un entero que indique la cantidad de personas, un punto indicando la
posición de una persona en específico, o también puede necesitar un arreglo de
posiciones. Las implementaciones de tres modelos diferentes se verán en la sección
3.2.
Por último, el controlador ejecuta el método update, en donde se crea el objeto
específico a la vista, o se realiza alguna otra acción según los datos previamente
establecidos. Este objeto será creado de diferentes maneras dependiendo del objetivo
final de cada aplicación.
El método getData se ejecuta constantemente por una vista. Cuando es llamado,
significa que el controlador ya actualizó el modelo. Es aquí donde se devuelve el
objeto específicoque fue creado previamente en la actualización.
Los modelos tienen infinitas posibilidades sobre lo que se puede mostrar utilizando los
datos disponibles. En las siguientes secciones se mostrará cómo funcionan algunos
modelos, y los resultados obtenidos en el desarrollo de aplicaciones. La creación de
nuevos modelos para ser actualizados por un controlador de tipo KinectController es
muy sencilla.
En las imágenes que se muestran en la Figura 3.15, se ven 3 posibles
representaciones de los objetos que crean los modelos. En la primera imagen se ve el
uso de la posición general de cada esqueleto para mostrar una calavera por cada
jugador. Esto se puede lograr obteniendo las posiciones de todos los esqueletos.
También se puede generar un contador, por ejemplo, jugando con la cantidad de
esqueletos rastreados. Utilizando las posiciones de un esqueleto, se pueden mostrar
todas sus articulaciones. Y de esta manera, con el uso de la imaginación, se pueden
crear una cantidad infinita de aplicaciones.
Figura 3.15 - Posibles usos de los datos por el modelo
Como es el caso de los controladores y los modelos, las vistas también deben seguir
38
3.1.3 Vista
La vista es la encargada de mostrar a través de la interfaz gráfica lo que el usuario
debe ver, creando una representación del modelo con el que se interactúa mediante
un controlador. Su funcionalidad principal es la de recibir un objeto, como por ejemplo
un arreglo de colores, o simplemente un valor entero, crear un frame de acuerdo a
estos datos, y mostrarlo por pantalla (Figura 3.16). Pero eso no es todo. Para llegar a
ello, es necesaria cierta configuración y comunicación con los demás componentes.
Previo a obtener los datos del modelo, la vista debe indicar al controlador que lo
actualice. Por ende, es indispensable que contenga un atributo de tipo IController y
otro de tipo IModel.
Figura 3.16 - Comunicación necesaria entre la vista y el modelo.
Al iniciarse la aplicación, es necesario inicializar todos aquellos componentes de la
vista. Es posible establecer una imagen o un video de fondo, la resolución de la
pantalla, si se quiere o no en pantalla completa, o si se quiere mostrar o no el mouse,
entre otras opciones. Todas estas aplicaciones, en particular, son pantalla completa y
el mouse no está visible.
Una vez que se inicializó a ella misma, debe instanciar el controlador y el modelo con
tipos no abstractos de cada uno de ellos. Y ahora sí, debe inicializar el controlador a
través del load. Este método devuelve a la vista un boolean indicando si la carga se
realizó correctamente. Es posible que se intente inicializar y por ejemplo el dispositivo
Kinect no esté conectado. En estos casos, la vista se encarga de avisarle al usuario de
39
Figura 3.17 - Secuencia de llamados para la inicialización
Hasta esta instancia se tiene una vista recientemente inicializada, que contiene un
controlador inicializado y un modelo de datos. Los recursos necesarios se encuentran
inicializados por el controlador. Queda un paso importante a realizar por la vista para
comenzar con la visualización.
El siguiente paso es dar comienzo a un evento que se produce constantemente en el
tiempo, un timer que su función es actualizar la vista. Dentro de este método disparado
en cada momento del tiempo, draw, la vista debe llamar al update del controlador.
Este método, como se mencionó en la sección anterior, transforma los datos crudos
para seguidamente actualizar al modelo. Luego, la vista debe llamar al método
getData del modelo. Dependiendo de la vista, la manera de crear el frame a mostrar y
la manera en dibujar sobre la pantalla varía (Figura 3.18).
Figura 3.18 - Secuencia de llamados para la actualización de la vista.
El método getData del modelo, devuelve un objeto genérico que la vista utilizará para
crear el objeto a mostrar. Como se verá en la sección de la instanciación de la
40
Estas vistas difieren en el tipo del objeto que muestran. Las vistas de XNA, por
ejemplo, utilizan una Texture2D que dibujan sobre pantalla. Windows Forms, con el
uso de la biblioteca Emgu CV, necesita de un Image<Bgr,byte>. Los datos recibidos
por el modelo pueden variar, por ejemplo entre un arreglo de colores para inicializar
una Texture2D, o un entero indicando la posición de un video para obtener un
Image<Bgr,byte>.
En algún momento, después de haber utilizado la aplicación el tiempo necesario, se va
a querer detenerla. La vista debe atrapar un evento que le permita identificar cuándo el
usuario desea cerrarla. En este caso en particular se usa la tecla escape. El método
llamado cuando se produce ese evento, es el que llama al último método del
controlador, unload. Recordando, el unload se encarga de liberar todos los recursos
utilizados (Figura 3.19).
Figura 3.19 - Secuencia de llamados para terminar la aplicación.
Concluyendo con el diseño de la vista, se puede poner un nombre formal a sus
métodos, dividiendo así correctamente su funcionalidad. El método de inicialización es
un load, que además de inicializar la vista, inicializa el controlador. A partir de ese
momento se dispara un evento constantemente, que llama al método draw de la vista,
dentro del cual se encuentra el update del controlador, el getData del modelo y la
creación del objeto que actualiza la pantalla. Por último, el evento de una tecla ejecuta
el método close, y justo antes de cerrar la aplicación, ejecuta el unload del controlador
(Diagrama 3.5).
41
En la siguiente sección se procederá a explicar la creación de las aplicaciones. Desde
el pensamiento que llevó a implementarlas, se las recorrerá a través de los primeros
pasos, y luego cómo fueron evolucionando hacia las versiones finales. No se dejará de
lado las diferencias y similitudes que hay entre todas ellas.
3.2 Diseño de cada aplicación
Como se mencionó en el capítulo de introducción, la idea es generar una plataforma
para el desarrollo de aplicaciones en el entretenimiento, específicamente para su uso
en museos. Para poder cumplir con el objetivo se fueron pensando aplicaciones para
ser implementadas y así instanciar la arquitectura que se explicó en la sección
anterior.
La instanciación de las aplicaciones se realizó con un fin específico, éstas serían
usadas en un museo de tenis. Se realizó un relevamiento de aplicaciones interactivas
en el contexto de museos y paseos. También se hizo una investigación sobre el uso
de la interactividad en el deporte. Los resultados obtenidos se encuentran a lo largo de
los capítulos uno, „Introducción‟ y 2, „Interactividad‟. Luego de observar diferentes
aplicaciones y de diferentes contextos se comenzó a pensar en aplicaciones
concretas.
A continuación se explicará el proceso que tuvo el desarrollo de cada aplicación. Se
podrán observar desde los primeros pasos y cómo fueron evolucionando para llegar al
objetivo. Se mostrará cómo fueron instanciados cada uno de los componentes de la
arquitectura y los detalles técnicos específicos de cada aplicación.
3.2.1 Reproductor de video
Para comenzar, se quería realizar algo que atraiga al público, dando un efecto
sorpresa. Es así que se pensó en la reproducción de un video. Con la incorporación de
Kinect generaría ese efecto sorpresa que se buscaba. Una persona de lejos, ve la
reproducción de un video en cámara lenta. Al acercarse, es decir, al entrar en el área
42
Figura 3.20 - Idea básica sobre el funcionamiento del Reproductor de Video
El objetivo final es implementar un reproductor de video que reproduzca de manera
constante un video en cámara lenta, y al pasar una persona por el frente de la
instalación, (dependiendo de la dirección) avance a una velocidad mayor o retroceda.
En la Figura 3.21 se intenta mostrar la idea en una secuencia de salto cuando no hay
movimientos y cuando hay movimientos hacia derecha e izquierda respectivamente.
Figura 3.21 - Acción de los movimientos
(a) Cámara lenta (b) Movimiento hacia derecha (c) Movimiento hacia izquierda
Durante su desarrollo, se pasó por varias etapas antes de llegar a la versión final.
Cada etapa incorpora algo de funcionalidad nueva. A lo largo de esta sección se
explicarán cada una de ellas. Lo que es común a todas las versiones, es el uso de los