Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Diseño e implementación
de aplicaciones interactivas
para exposiciones y paseos
Proyecto de tesis de grado de la carrera Ingeniería en Sistemas
Mayo de 2016
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
3.2.3.2 Descubrimiento con memoria ................................................................. 73
1
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
2
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
Figura 3.35 - Representación de sonidos reproducidos en verde, y no reproducidos en rojo.
Sin variación de sonidos a reproducir. ................................................................ 64
3
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
4
Diagrama 3.17 - Clase DiscoveryModel con sus atributos iniciales. ...................................... 71
Diagrama 3.18 - Clase ColorManager actualizado para retornar color sin controlar su uso. .... 72
Code snippet 3.1 - Incorporación de métodos para atrapar los eventos de flujos de datos. ......27
Code 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
Code snippet 3.23 - Cuerpo del método update del controlador. ............................................72
5
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.
6
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.
7
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.
8
1.1 Motivación
9
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.
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
desarrolladas.
10
Al finalizar se encuentra la sección de Bibliografía, en donde se listan todas aquellas
fuentes que fueron utilizadas para completar el informe actual.
11
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.
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).
12
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.
13
Figura 2.3 - Dispositivo WiiMote
14
Figura 2.5 - Dispositivo Kinect
2.1.1 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
emitir rayos de luz infrarroja y luego el sensor de profundidad IR captura aquellos
15
rayos que vuelven reflejados. Estos rayos luego son convertidos en información de
profundidad midiendo la distancia entre un objeto y el sensor.
16
Figura 2.8 - Arreglo de micrófonos del dispositivo Kinect marcados en violeta.
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
persona en esa posición, mientras que los valores del „1‟ al „6‟ identifican a los
17
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.
18
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.
19
Figura 2.12 - Interacción en el Museo de Louvre con el uso de Nintendo 3DS y códigos QR.
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
conceptos relevantes.
20
Figura 2.14 - Live Projection Mapping - EVA 2013
21
Figura 2.16 - ‘Play Work Build’ en el National Building Museum.
22
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).
23
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).
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.
24
Capítulo 3
Capítulo 3 Diseño e Implementación
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
acceso (Figura 3.1).
25
Figura 3.1 - Interacción del dispositivo Kinect con la aplicación a través del Kinect SDK
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.
26
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.
if (null != sensor)
{
// Agrega controlador de evento para cuando haya nuevo frame de esqueleto
sensor.SkeletonFrameReady += skeletonFrameReady;
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
de un arreglo de tipo Skeleton, que luego podrá ser consultado (Code snippet 3.2).
27
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.
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.
28
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.
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();
Dentro del load, el controlador debe inicializar cualquier recurso que vaya a ser
necesario, además del modelo. El recurso que será común a todas las aplicaciones
29
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.
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().
30
Figura 3.4 - Secuencia de llamados para la actualización del modelo.
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.
31
Figura 3.6 - Transformación de los datos por el método getTotalSkeletons.
32
Figura 3.8 - Transformación de los datos por el método isSkeletonAvailable.
Figura 3.10 - Espacio del esqueleto (izquierda) comparado con los valores de
profundidad (derecha).
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
33
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.
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
incorporado sobre el gestor en esta última etapa se encuentra resaltado.
34
Diagrama 3.3 - Estructura de los controladores.
3.1.2 Modelo
35
Figura 3.14 - Comunicación entre los componentes del sistema.
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).
36
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.
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.
Como es el caso de los controladores y los modelos, las vistas también deben seguir
un formato. Afortunadamente, el diseño de la vista se dio de forma natural.
37
3.1.3 Vista
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
la situación y cerrar la aplicación (Figura 3.17).
38
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 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
arquitectura, se utilizaron dos tipos de vistas, XNA y Windows Forms.
39
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>.
40
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.
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
de captura del Kinect, el video comienza a responder a sus movimientos (Figura 3.20).
41
Figura 3.20 - Idea básica sobre el funcionamiento del Reproductor de Video
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
datos.
42
Cómo sólo se va a utilizar la posición de una persona, es necesario habilitar los frames
de esqueletos, pero no los frames de profundidad. Para esta aplicación se va a utilizar
la funcionalidad para verificar si hay algún esqueleto rastreado para luego preguntar
por su posición.
43
método update es el que va a ir variando a lo largo de las diferentes etapas, y es en
donde se va a ir inyectando de a poco la funcionalidad.
44
Para incorporar la reproducción hacia atrás, primero hay que incorporar nuevos datos
al modelo: lastPosition y newPosition. El valor indicando la nueva posición es la que
será actualizada por el controlador y lastPosition será actualizado constantemente por
el modelo. Los valores de posiciones serán los determinantes del próximo frame a
reproducir. Un valor indicando la posición del video, actualFrame, es el que recibirá la
vista de getData de VideoModel (Diagrama 3.7).
45
public override bool update()
{
if (isSkeletonAvailable())
{
Point newPosition = getFirstSkeletonPosition();
myModel.setNewPosition(newPosition.X);
}
else
{
myModel.setNewPosition(-1);
}
myModel.update();
}
Code snippet 3.6 - Código correspondiente al método update de VideoController.
| |
El dato es extraído de un archivo de configuración en XML [31] para facilitar su
modificación rápida sin la necesidad de recompilar el código. Como se verá más
adelante, se van a levantar algunos valores más, por lo tanto se creó una clase
singleton[32], Configuration, que está al alcance de cualquier elemento de la aplicación
(Diagrama 3.8).
46
El flujo de la actividad para este caso se puede ver en la Figura 3.24. Más adelante se
verá la necesidad de incorporar otro control más, ya que con el simple hecho de saber
si un esqueleto se movió no será suficiente.
Figura 3.24 - Flujo de actividad para la reproducción del video con control de movimiento.
Sólo queda determinar el próximo frame a mostrar una vez que se aseguró que existe
un esqueleto y que éste se movió. Para generar una reproducción hacia atrás se
utilizará otra funcionalidad brindada por Emgu CV. A través de
video.SetCaptureProperty(property, newValue), la biblioteca permite modificar los
valores de cualquier propiedad del video. El parámetro property debe ser un tipo de
CvEnum.CAP_PROP. Para poder manipular la posición del frame actual,
específicamente CV_CAP_PROP_POS_FRAMES. El segundo parámetro newValue
debe ser fijado con el valor del frame anterior al que se debe reproducir a
continuación.
video.setCaptureProperty(CV_CAP_PROP_POS_FRAMES, newPosition);
imageBox.Image = video.QueryFrame();
}
Code snippet 3.7 - Cuerpo del método draw de la vista.
47
último método devuelve la nueva posición del video. A través de setCaptureProperty
explicado anteriormente, se establece la nueva propiedad obtenida. Al instante, la vista
ejecuta video.QueryFrame() para setear la imagen del ImageBox (Code snippet 3.7).
El cálculo del siguiente frame se computa a partir del frame actual. El atributo utilizado
es actualFrame, que comienza en 0 y se va actualizando a medida que se va
reproduciendo el video. FRAME es una constante inicializada con el número que
equivale a un frame, también extraída del archivo de configuración.
Hay que prestar atención al valor que multiplica a FRAME. Es necesario que
mínimamente sea un 2 ya que hay que tener en cuenta que el valor resultante es
utilizado para establecer la posición actual del video. Entonces, cuando se llame a
video.QueryFrame(), se va a obtener el frame que le sigue al actual (Figura 3.25). Más
adelante, en la versión final, se verá el uso de otros valores.
Cabe aclarar que el frame rate de la vista no es el mismo que el de Kinect. Es por eso
que el controlador será llamado algunas veces en los que los datos siguen siendo los
mismos. Es aquí en donde se utiliza la funcionalidad brindada por el gestor de Kinect
de reiniciar los datos guardados. Al comienzo del método se hace una consulta, así el
controlador sólo analiza los datos si, y sólo si, hay un nuevo frame para analizar.
48
3.2.1.1 Reproducción cámara lenta y acelerada
49
Figura 3.27 - Modo de reproducción acelerado.
Para generar una aproximación al objetivo final, el próximo paso fue unificar los dos
casos anteriores en uno, así se da la posibilidad de manipular un video de tres
maneras diferentes: hacia atrás, en cámara lenta, o acelerado. Evitando tener
complejidad en el análisis de la posición del jugador, se optó por dividir el área del
juego a la mitad. En efecto, si el jugador se mueve del lado derecho, el video se
reproduce en modo acelerado; si el jugador se mueve del lado izquierdo, el video se
reproduce en reversa; y, por último, si el jugador no se mueve, el video se reproduce
en cámara lenta (Diagrama 3.10).
50
Diagrama 3.10 - Etapa 2 - Interacción entre los modos de reproducción.
En esta etapa previa a la final, se debe incorporar una nueva condición. Luego de
determinar si la persona se movió, se consulta por la posición. Primero se toma un
valor que determina la mitad del área de juego. Si la posición horizontal (X) actual del
esqueleto es menor a éste valor, significa que se movió del lado izquierdo,
estableciendo como nuevo estado BACKWARDS. En caso contrario, se produjo un
movimiento del lado derecho, pasando al estado FAST FORWARD. Según los
distintos estados se utiliza el cálculo del próximo frame como se utilizó en las etapas
anteriores del desarrollo.
Por un lado se debe actualizar el estado. El método updateState es el que debe variar
cuando se quiere cambiar la lógica del cambio de estados. Más adelante se mostrará
su versión final en Code snippet 3.10.
51
Una vez que se conoce el estado actual, el cálculo del próximo frame es el mismo. La
funcionalidad se engloba dentro de updateActualFrame (Code snippet 3.9). Durante
el desarrollo del reproductor del video, se encontró con un problema. Al estar en el
estado BACKWARDS, y en el frame 0, era imposible recuperar el próximo frame. Lo
mismo pasaba cuando el estado era SLOW_MOTION o FASTFORWARD y se
encontraba en el último frame. Este problema se solucionó incorporando un control
que se puede ver reflejado en este método.
Hay dos casos posibles, querer acceder a un frame negativo, o acceder a un frame
mayor a finalFrame. finalFrame es un atributo que se incorporó al modelo con el
objetivo de este control. Si se trata del caso de un frame negativo, habría que
establecer un número de frame anterior a finalFrame. Por el contrario, si ya se llegó al
final, es necesario volver al comienzo del video, estableciendo el frame actual a 0.
Finalmente se puede llegar al objetivo final sin mayores cambios. Inicialmente estando
en el estado SLOW MOTION, el siguiente estado va a depender de la dirección en la
cual se mueva. La dirección se determina haciendo una comparación entre la posición
horizontal recientemente actualizada por el controlador, y la posición anterior guardada
52
por el modelo. Si la nueva posición es menor que la posición guardada, significa que la
persona se movió hacia la izquierda, en cambio si la posición nueva es mayor que la
posición guardada, la persona se movió hacia la derecha.
En el Code snippet 3.10 se puede ver la lógica del cambio de estados final. Si no hay
esqueleto disponible traqueado o si hay un esqueleto pero éste no se movió, el estado
pasa a SLOW_MOTION.
setVideoSpeed(Math.Abs(lastPosition - newPosition));
lastPosition = newPosition;
}
}
else
{
state = VideoModel.SLOW_MOTION;
}
}
Code snippet 3.10 - Método updateState().
En el Code snippet 3.10 se puede ver el uso de una función interna setVideoSpeed().
Una vez que la máquina de estados funcionó como se esperaba, se incorporó también
la velocidad como un dato adicional a tener en cuenta a la hora de calcular el próximo
frame a mostrar. Entonces, el jugador no sólo maneja la dirección del video, sino que
también la velocidad. Este efecto hace que pareciera que el video está siguiendo a la
persona. Esta vez, el cálculo de velocidad se realiza con la diferencia entre la posición
actual y la posición anterior del jugador, sólo que el valor que se toma en cuenta es el
valor absoluto. Cuanta más grande sea la diferencia, más grande será la velocidad.
53
multiplicar por 2 el frame, también multiplicará por la velocidad. La reproducción
acelerada no multiplicará más por una constante, y sólo multiplicará por la velocidad.
De esta manera, si la persona se mueve lo suficientemente lento, la reproducción es
en modo normal.
Backwards:
Fast forward:
<Configuration>
<!--Velocidad mínima-->
<MinSpeed>2</MinSpeed>
<!--Velocidad máxima-->
<MaxSpeed>10</MaxSpeed>
<!--Movimiento insignificante
Al disminuir, aumenta la sensibilidad de movimiento-->
<InsignificantMovement>5</InsignificantMovement>
Habiendo logrado toda esta funcionalidad, se puede decir que se terminó con la etapa
final. El video responde a la dirección de los jugadores, y también a la velocidad en la
que se movieron. Se utilizó la arquitectura explicada previamente, utilizando el
controlador abstracto KinectController y la interfaz de modelo IModel. De todos los
transformadores implementados, sólo se utilizaron unos pocos, que fueron los
necesarios para este desarrollo.
54
cómo la vista que contiene un modelo y un controlador, no tiene ningún conocimiento
de la fuente del controlador, en este caso KinectDevice, y el controlador que tiene un
modelo, no necesita saber nada de la vista. El modelo sólo necesita conocer el objeto
que necesita la vista para poder instanciarlo y devolverlo cuando es pedido.
3.2.2 Hinchada
El efecto que se busca es que a medida que se sume gente, se reproduzcan más
sonidos y se genere una gran hinchada. Si sólo hay una persona, se reproduce, por
ejemplo, una multitud hablando. Al sumarse otra persona, se reproducen palmas, y
55
luego gritos, bombos, etc. En la Figura 3.28 se intenta demostrar la intensidad de los
sonidos reproducidos con respecto a la cantidad de gente y sus movimientos.
56
donde se muestra una hinchada de un partido de tenis. Nuevamente, este video debe
ser modificado fácilmente para mantener la usabilidad y el alcance.
Teniendo en mente el objetivo visual de la aplicación, se decidió utilizar una vista XNA.
Durante esta fase, no es necesaria la recepción de datos del modelo de datos, ya que
no se va a mostrar ningún objeto. Sin embargo, la reproducción del sonido se realiza
dentro del método update del modelo, PlayersModel. Al finalizar, antes de cerrar la
aplicación se llama al método Stop() del reproductor de audio, cuando
PlayersController se lo indica al modelo desde el unload.
57
3.2.2.2 Reproducción múltiple
La siguiente etapa involucra varios sonidos (Figura 3.31). Por este motivo se decidió
crear una clase singleton AudioManager, que contenga una lista de audios, y que se
encargue de la comunicación directa con los objetos de audio. Esta clase se basa en
sólo 3 métodos, load(), play(int track) y stop(int track).
Dentro del método load se carga una lista de sonidos. Luego, a través de los métodos
play y stop, reproduce y para de reproducir el sonido dependiendo del número que
recibe por parámetro. Este número indica la posición en la lista, que siempre mantiene
el mismo orden.
58
ejecutando play, y desde el contador hasta que se llegue a la cantidad de sonidos
disponibles, ejecutar stop (Diagrama 3.12).
59
tipo de objetos y como clave se utiliza un entero que indica la posición de un sonido en
la lista (Diagrama 3.13). A través de los canales se puede incorporar también los
efectos de fade in y fade out.
60
public void play(int track)
{
if (!channels.ContainsKey(track))
{
Sound sound = sounds.ElementAt(track);
Channel channel;
//Reproducción comienza en pausa = true
system.playSound(sound, true, channel);
channels.Add(track, channel);
fadeIn(channel);
}
}
Code snippet 3.12 - Cuerpo del método play utilizando la biblioteca FMOD.
En esta etapa se encontró una limitación, ya que el dispositivo Kinect sólo puede
llevarle el rastro a 6 esqueletos. Este número es muy pequeño para poder apreciar el
crecimiento de los sonidos, ya que sólo 6 pistas podrían ser reproducidas, y limita las
opciones de entretenimiento. Para poder incorporar más sonidos, se decidió tomar en
cuenta el movimiento vertical de las personas, para incentivar movimientos de los
61
brazos hacia arriba y saltos. Ahora, la hinchada, es decir, la reproducción de sonidos,
crece también por el movimiento, y no sólo por la cantidad. Un público inquieto hace
que la hinchada aumente y es una manera entretenida de alentar.
myModel.update();
}
return count;
}
Code snippet 3.14 - Cuerpo del método update de PlayersController junto al transformador
privado getAudioCounter.
62
Diagrama 3.14 - Clase PlayersModel que mantiene el último contador con el que fue
actualizado.
En un primer lugar, el nuevo valor de cantidad de personas puede ser mayor que el
valor anterior. En este caso que se ve reflejado en la Figura 3.33, se debe ejecutar el
método play para todos aquellos audios que se encuentren en una posición entre el
contador mantenido por el modelo, y la cantidad de personas que le indica
PlayersController.
Luego, se puede dar que el nuevo valor sea menor que la cantidad de sonidos
reproducidos, como se ve en la Figura 3.34. Por lo tanto se deben parar de reproducir
aquellos sonidos que se encuentran en el rango correspondiente.
63
Por último, los valores pueden ser iguales (Figura 3.35). De esta manera, no se
produce ningún cambio, y se evita la comunicación innecesaria con AudioManager.
Para mantener la generalidad del proyecto, es necesario que los archivos de audio
sean levantados dinámicamente. Desde el comienzo se decidió utilizar un archivo
XML, Audios.xml (Code snippet 3.15), que contenga una lista de audios que luego
serán levantados desde AudioManager dentro de load.
<Table>
<Audio>/Audio/1.Aplausos.wav</Audio>
<Audio>/Audio/2.Animos.wav</Audio>
<Audio>/Audio/3.Publico.wav</Audio>
<Audio>/Audio/4.GranAplauso.wav</Audio>
<Audio>/Audio/5.Rebelion.wav</Audio>
<Audio>/Audio/6.MarchaMilitar.wav</Audio>
</Table>
Code snippet 3.15 - Ruta de los archivos de audio dentro de Audios.xml
64
Al comienzo de la aplicación, la vista, además de inicializar el controlador, comienza a
reproducir el video en loop y sin audio. XNA brinda este servicio sin más dificultades
como se puede ver en el Code snippet 3.16[36].
videoPlayer.IsLooped = true;
videoPlayer.IsMuted = true;
videoPlayer.Play(myVideoFile);
...
}
Code snippet 3.16 - Porción del cuerpo del método load de la vista relacionado a la
reproducción de video de fondo.
Luego, en cada momento del tiempo, ejecuta el método update del controlador e
inmediatamente el getData del modelo. En esta ocasión, el tipo de datos obtenido es
un arreglo de colores. Por lo tanto, el siguiente paso es crear una Texture2D, y
establecerle los colores que se recibieron (Code snippet 3.17).
Una vez creada la textura, la vista la debe mostrar. Como se desea mostrar las
siluetas de las personas por encima, primero se dibuja el siguiente frame del video, y
luego la textura recientemente creada. En aquellos píxeles que tienen un color
transparente, se podrá percibir el video de fondo.
65
Para llevar a cabo el dibujo de las personas en la pantalla, es necesario incluir datos al
modelo que se destacan en el Diagrama 3.15. Un arreglo de enteros, que representa
un frame, indica los id de los jugadores. También es necesario incluir un color por cada
id de jugador, con el fin de poder colorear a cada uno de ellos con un color diferente.
colors es una estructura Hash que como clave contiene los id de los jugadores y como
valor un objeto de tipo Color. Como se mencionó anteriormente, el máximo de
jugadores es 6. Esto limita los valores que pueden tomar los id, donde sus valores
posibles son del 1 al 6.
66
Figura 3.36 - Establecimiento de colores con respecto a los identificadores de los jugadores.
67
al azar de su lista, y previamente a retornarlo, controla que no esté siendo usado a
través una lista de booleanos. Una vez obtenidos los colores necesarios, actualiza al
modelo a través de setColors (Code snippet 3.18).
myModel.update();
}
Code snippet 3.19 - Cuerpo del método update del controlador actualizado.
68
3.2.3 Descubrir la imagen
Cada niño va a ayudar a destapar la imagen. Los movimientos de sus cuerpos irán
despintando el cobertor, con la necesidad de moverse por el espacio y saltar para
llegar a aquellos lugares inalcanzables de otra manera. Pero para mantener
incentivados a los más pequeños, la imagen se irá volviendo a tapar cuando no haya
movimientos (Figura 3.37).
69
De manera contraria a la aplicación anterior en donde la imagen de la persona tapaba
el video, ahora el jugador con su cuerpo tiene la función de despintar. El desarrollo se
realizó en 3 etapas. En primer lugar, se buscó mostrar la imagen de fondo sólo en
aquellos lugares en donde se encuentren las personas modificándose en cada
momento del tiempo. Luego, se incorpora la memoria, es decir, mantener despintados
aquellos píxeles que fueron tocados alguna vez por algún jugador. Por último se
incorporó el recubrimiento de la imagen junto con un pequeño efecto visual.
spriteBatch.End();
}
Code snippet 3.20 - Cuerpo del método draw de la vista al dibujar textura sobre imagen de
fondo.
70
Diagrama 3.17 - Clase DiscoveryModel con sus atributos iniciales.
71
public override bool load()
{
myModel = new DiscoveryModel();
bool connected = kinect.initializeKinect();
if (connected)
{
//Habilitación de flujo de datos
kinect.enableSkeletonStream();
kinect.enableDepthStream();
Diagrama 3.18 - Clase ColorManager actualizado para retornar color sin controlar su uso.
myModel.update();
}
Code snippet 3.23 - Cuerpo del método update del controlador.
72
El resultado obtenido logró mostrar la imagen de fondo sólo en aquellos lugares en
donde se encuentren las personas. El siguiente paso involucra mantener en memoria
todos aquellos píxeles que alguna vez fueron tocados.
Como se puede ver en el Code snippet 3.21, el método update del modelo, en cada
momento del tiempo se inicializan todos los píxeles. Aquellos que tienen un jugador en
transparente, y aquellos que no, con un color predeterminado. La solución tomada en
esta segunda etapa fue inicializar el arreglo discoveryArray desde un principio todo de
un sólo color. Luego, cuando update es llamado por el controlador, sólo se consulta
por los píxeles en donde hay jugadores, en ese caso poniendo el color transparente
(Figura 3.38).
73
3.2.3.3 Recubrimiento de la imagen
Entonces ahora el método update del modelo, realiza una acción sobre el arreglo de
retorno dependiendo de si existe o no un jugador en esa posición. En el caso de que
pertenezca a un jugador, se hace más transparente ese color, es decir, disminuye el
valor alpha. En el caso de que no haya ningún jugador asociado, el nivel de
transparencia disminuye, tapando así la imagen. Esta lógica se ve en la Figura 3.39.
Es importante que estos factores sean modificables. Para ello, como en el Reproductor
de Video, se utiliza el archivo configuration.xml que es levantado al Singleton
Configuration. En este caso, el Singleton sólo es utilizado por el modelo.
74
Esto permitió que recién al pasar 10 frames sin movimientos, la transparencia
disminuya en 1/255.
[] ⌊ [ ]⌋
A la hora de crear una nueva aplicación, se debe tener en claro cuáles son los datos
necesarios a incorporar en el modelo, y cuál es el objeto necesario para la vista. El
controlador debe establecer todos los atributos del modelo, y luego ejecutar update.
Es aquí en donde el modelo crea el objeto para la vista específico a la aplicación en
cuestión. La vista, además de inicializarse con todas las propiedades necesarias, debe
actualizar el controlador y recuperar los datos del modelo para mostrar una imagen por
pantalla.
75
Capítulo 4
Capítulo 4 Pruebas
Este capítulo se basa en las pruebas realizadas sobre las aplicaciones que fueron
explicadas en el capítulo 3, Diseño e Implementación. Se comienza explicando 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 a
aplicación, indicando aquellos aspectos positivos, y también aquellos que deben
corregirse.
4.1 Contexto
76
Como se mencionó en los capítulos anteriores, el dispositivo Kinect no detecta más de
seis personas. Sin embargo, para las pruebas fue necesario incluir una mayor
cantidad. Es imposible controlar que, a la hora de usar las aplicaciones, sólo haya una
cantidad determinada de personas. Las pruebas se hicieron con ocho personas
activas.
4.2 Aplicaciones
Una vez que el ambiente estuvo preparado y las personas presentes, se comenzó con
una explicación. Se aclaró a los participantes que las aplicaciones que iban a probar
iban a estar en un museo o paseo relacionado al tenis. Durante las pruebas se
midieron sus reacciones y luego se tomaron sus opiniones.
La reproducción del video está pensada para ser controlada sólo por un usuario.
Además de imposible, va en contra de la interactividad controlar que sólo una persona
lo use por vez. La idea es que una persona que visite el museo sea libre, y se pueda
divertir junto a los otros. Por eso, se llevó a probar la reproducción del video con
muchas personas. Es correcto que sólo responda a una, pero el objetivo es que siga
funcionando aunque haya más de una persona.
Figura 4.2 - Prueba del reproductor del video con una sola persona moviéndose hacia la derecha.
Los resultados obtenidos al realizar pruebas con una sola persona son ideales. La
serie de imágenes de la Figura 4.2 muestran la evidencia de las pruebas realizadas
con una sola persona que se mueve hacia la derecha. Los movimientos hacia la
derecha, como se explica en el capítulo anterior 3.2.1, hace que el video avance, es
decir, se reproduzca de manera normal, pero a una velocidad variante.
77
Figura 4.3 - Prueba del reproductor del video con varias personas en fila hacia la izquierda.
Esta prueba fue un éxito. Se notó a las personas entretenidas, y con ganas de
probarlo. Además, como también se ve en la Figura 3.2, intentaban copiar los
movimientos de la persona que se estaba proyectando.
Las mismas personas decidieron realizar una prueba como si caminaran en un pasillo
del museo en fila (Figura 4.3). En este caso el movimiento es hacia la izquierda. Como
se explica en la sección 3.2.1, este tipo de movimiento genera una reproducción hacia
atrás, es decir, backwards. Esta prueba en cuestión generó una confusión.
Como las personas caminan hacia la izquierda, esperaron que la persona del video se
mueva también hacia la izquierda. En este caso en particular, utilizando este video, la
persona se mueve hacia la izquierda en reproducción normal, por lo tanto al
reproducirse hacia atrás, se mueve hacia la derecha. La funcionalidad es correcta,
pero el video elegido hizo confundir a los usuarios.
Como resultado de esta prueba se puede concluir que hay que tener en cuenta los
movimientos de las personas que se reproducen en el video proyectado. Para
aumentar el efecto en la gente, es ideal que las personas hagan movimientos hacia la
derecha en una reproducción normal.
78
4.2.2 Hinchada
Figura 4.4 - Pruebas realizadas sobre la ‘Hinchada’ con todas las personas a la vez.
A lo largo de esta prueba, se nota una reacción muy divertida de parte de los
participantes. Inmediatamente se pusieron a saltar y mover los brazos, y jugaban a
quedarse quietos para ver cómo respondía la aplicación. La prueba fue acompañada
con muchas risas (Figura 4.4).
79
Figura 4.5 - Dos personas detectadas como una sola cuando sus esqueletos se tocan.
Luego de realizar las pruebas sobre esta aplicación, se concluyó que es muy
importante la elección de los sonidos. Recordando, si hay 6 personas quietas en frente
al sensor, se van a reproducir los primeros 6 sonidos. Si estas 6 personas se mueven,
se van a reproducir 12 sonidos. Hay que tener en cuenta que los primeros sonidos
sean leves, para que las personas tengan la necesidad de moverse para sentir la
hinchada.
La última aplicación probada fue Descubrir la imagen. Las pruebas realizadas cuando
se desarrolló, se basaron en una o dos personas. Los valores de aparición y
desaparición de la imagen fueron acomodados a ese contexto. Pero el objetivo es que
pueda ser usada por muchas personas a la vez sin inconvenientes.
Estando la imagen totalmente tapada, una persona pasó en frente al Kinect, y se dio
cuenta que con su cuerpo podía descubrirla, momento retratado en la Figura 4.6). En
este primer paso se logró el objetivo, que incentiva a las personas a moverse por el
espacio horizontal, como también en el vertical, para descubrir la imagen.
80
Figura 4.6 - Proceso inicial de ‘Descubrir la imagen’ con una sola persona.
81
Figura 4.8 - Personas jugando con sus poses y eligiendo qué partes de la imagen descubrir.
La prueba en general, a pesar de los índices mal establecidos, fue exitosa. Las
personas esperaban a que se vuelva a tapar para ir pasando de a uno y jugar a hacer
poses. También jugaban con las partes de la imagen que destapaban y las que
dejaban escondidas (Figura 4.8).
82
Capítulo 5
Capítulo 5 Conclusiones
En este capítulo se presentan las conclusiones encontradas luego de realizar el
proyecto en cuestión. El mismo se encuentra dividido en dos secciones. En primer
lugar se detallan los resultados obtenidos respecto a los objetivos propuestos; luego,
se proponen trabajos futuros sobre la plataforma y las aplicaciones desarrolladas.
Para probar la plataforma se crearon tres aplicaciones base que son detalladas en la
sección 2 del capítulo „Diseño e Implementación‟. El primer punto de los objetivos que
se buscó cumplir es que estas aplicaciones sean reutilizables, es decir, sin importar
para qué contexto fueron pensadas, pueden adaptarse fácilmente a cualquier otro.
Esto fue posible gracias al diseño de las aplicaciones y el correcto uso de archivos de
configuración.
83
interactividad entre las personas y el sistema. Se encontraron leves problemas en dos
de las aplicaciones donde el usuario quedó confundido. Sin embargo, estos problemas
son solucionados desde archivos de configuración que se pueden ir adaptando sin
problemas, en caso de ser necesario, a un público en particular. Si el público no se ve
atraído por una imagen o un video, o los sonidos no los satisfacen, éstos se pueden
adaptar.
84
Como una continuación al proyecto, se podría pensar en una cuarta aplicación que
interactúe con el usuario incorporando acciones que utilicen las reglas de la física. La
imaginación de los creadores puede ir más allá todavía teniendo como base una
aplicación de este estilo, en donde pueden entrar en acción diversos objetos que
interactúan con el cuerpo, manteniendo un efecto similar al real.
Se puede crear, también, un nuevo punto de vista proyectado sobre las personas. Este
tipo de aplicaciones requiere un mayor esfuerzo en la instalación del ambiente. El
efecto provocado pretende ser totalmente diferente a las aplicaciones que se tuvieron
en cuenta hasta el momento. Generalmente, al proyectar sobre personas, quién
controla la aplicación no es el espectador.
Con respecto a las aplicaciones existentes, también se pueden realizar mejoras con
respecto a la funcionalidad. Se podría incorporar dinamismo en las imágenes y videos
que se muestran de fondo. Tomando como ejemplo „Descubrir la imagen‟, después de
un determinado tiempo, se podría cambiar la imagen de fondo para mantener
motivados a los usuarios.
En la aplicación „Hinchada‟ se puede incorporar una lógica más compleja para manejar
los audios reproducidos. Por ejemplo, reproducir sonidos suaves por cada persona
quieta, y reproducir sonidos fuertes adicionales por cada persona que se mueve.
Hasta el momento, sólo importa un número referido a la suma de personas
independientemente de si están quietas o en movimiento, como tampoco se encuentra
distinción entre los sonidos reproducidos.
85
Referencias
[1] Wii Remote
URL: http://es.metroid.wikia.com/wiki/Wii_Remote
[2] Leap Motion
URL: http://blog.leapmotion.com/hardware-to-software-how-does-
the-leap-motion-controller-work
[3] Kinect
URL: https://en.wikipedia.org/wiki/Kinect
[4] Virtual Rehab
URL: http://www.virtualrehab.info/es
[5] Manuel Armenteros Gallardo. “Aprendizaje de las reglas del Fútbol a través del
videojuego”. ICONO 14, nº 8 (2006)
[6] Ralph Lauren London 4D
URL: https://www.youtube.com/watch?v=H4JYpF5DpFo
[7] Video Mapping
URL: https://es.wikipedia.org/wiki/V%C3%ADdeo_mapping
[8] SDK para Kinect desarrollado por Microsoft
URL: https://dev.windows.com/en-us/kinect
[9] CLI
URL: https://en.wikipedia.org/wiki/Command-line_interface
[10] GUI
URL:https://es.wikipedia.org/wiki/Interfaz_gr%C3%A1fica_de_usuario
[11] NUI
URL:http://cyrilandersontraining.com/2014/05/02/natural-user-
interfaces-nui
[12] Kinect SDK 1.8
URL: https://msdn.microsoft.com/en-us/library/hh855347.aspx
[13] Kinect SDK 2.0
URL: https://msdn.microsoft.com/en-us/library/dn799271.aspx
[14] Una Nintendo 3DS para descubrir el Louvre
URL: http://www.xataka.com/videojuegos/una-nintendo-3ds-para-
descubrir-el-louvre
[15] Museon
86
URL: http://www.museon.nl
[16] PuppyIR - An Open Source Environment to Construct Information Services for
Children
URL: http://hmi.ewi.utwente.nl/puppyir/
[17] Expo EVA
URL: http://expoeva.com/
[18] Live projection Mapping EVA 2013
URL: https://www.behance.net/gallery/9353869/Live-Projection-
Mapping-Kinect
[19] Piso Interactivo
URL: http://www.pisointeractivo.net/
[20] National Building Museum
URL: http://www.nbm.org/exhibitions-
collections/exhibitions/play-work-build.html
[21] Video Oficial National Building Museum - Minuto en donde se presenta Play
Work Build
URL: https://youtu.be/w9t9vhvC8Z0?t=147
[22] Cleveland Museum of Art
URL: http://www.clevelandart.org/gallery-one/interactives
[23] Transforming the Art Museum Experience - Galery One
URL: http://mw2013.museumsandtheweb.com/paper/transforming-the-
art-museum-experience-gallery-one-2
[24] Chicago Sports Museum
URL: http://www.harrycarays.com/chicago-sports-museum
[25] Museo de la memoria México
URL: http://www.random.com.mx/projects/project3/index.html
[26] Emgu CV
URL: http://www.emgu.com/wiki/index.php/Main_Page
[27] Open CV
URL: http://opencv.org/
[28] FMOD
URL: http://www.fmod.org/
[29] XNA
URL: https://es.wikipedia.org/wiki/Microsoft_XNA
[30] Trygve Reenskaug. “The Model-View-Controller (MVC) Its Past and
Present”. University of Oslo. (2003)
87
[31] XML
URL: https://en.wikipedia.org/wiki/XML
[32] Singleton Design Pattern
URL: https://sourcemaking.com/design_patterns/singleton
[33] Finite-state machine
URL: https://en.wikipedia.org/wiki/Finite-state_machine
[34] SoundPlayer Class
URL: https://msdn.microsoft.com/en-
us/library/system.media.soundplayer(v=vs.110).aspx
[35] MediaPlayer Class
URL: https://msdn.microsoft.com/en-
us/library/system.windows.media.mediaplayer(v=vs.110).aspx
[36] Playing a Video - XNA
URL: https://msdn.microsoft.com/en-us/library/dd904198.aspx
[37] Color Alpha Property
URL: https://msdn.microsoft.com/en-
us/library/system.drawing.color.a(v=vs.110).aspx
88