scieee AI-readable full text Open interactive document viewer

Repositorio Institucional de Documentos

Abstract

La idea principal de este proyecto fin de carrera (PFC) consiste en conseguir que los niños muy pequeños puedan interactuar con software y elementos informáticos de una manera más natural, sin depender de los dispositivos básicos, como ratón o teclado, sino usando cualquier tipo de juguete o con sus propias manos. Para lograr este propósito, este PFC se centró en el estudio y ampliación de un software de reconocimiento visual para dispositivos tabletop. El trabajo se realiza sobre NIKvision, una mesa de interacción tangible especialmente diseñada para su uso por niños pequeños. En primer lugar se ha realizado un estudio de los elementos del sistema de NIKvision para, posteriormente, realizar varias fases de análisis e implementación de las distintas funcionalidades necesarias. La primera fase consiste en la búsqueda de reglas para poder crear marcadores personalizados, con la finalidad de que sean capaces de adaptarse a las distintas formas que poseen los juguetes y que puedan tener una determinada forma o significado, no sólo para el ordenador, si no también para los niños (formas de animales, objetos, etc.). La siguiente fase consiste en la modificación del framework de ReacTIVision para permitir la captura de dibujos realizados por los niños en un folio de papel. Estos dibujos estarán marcados con un marcador personalizado diseñado en la fase anterior, para luego poder trabajar con ellos en juegos o aplicaciones que usen la mesa como soporte. La última fase consiste en permitir la detección de movimientos y pulsaciones de las manos de los niños sobre la mesa, así como la detección de juguetes “planos” (juguetes que no lleven marcas especiales en su base) y la orientación que éstos tengan. A partir de cada una de las mejoras se han creado varios juegos para comprobar su funcionamiento. También se ha creado un juego que recoge todo lo implementado en la fases anteriores. El juego captura uno o varios dibujos, realizados en un folio con un fiducial personalizado, para luego poder interaccionar con las versiones digitales de éstos. Los dibujos se muestran en la superficie del tabletop repetidas veces para que el niño pueda golpearlos con sus manos, haciendo que desaparezcan, o desplazarlos a través de la pantalla con sus manos. Enjuanes Traín, Alejandro; Baldassarri Santa Lucía, Sandra; Marco Rubio, Javier

Full text

Ficha Técnica Proyecto Fin de Carrera Título: Adaptación de algoritmos de reconocimiento visual para la implementación de juegos para niños basados en dispositivos Tabletop. Autor: Alejandro Enjuanes Traín D.N.I.: 76922080Y Titulación: Ingeniería Informática Directores: Sandra Baldassarri Santalucía Javier Marco Rubio Departamento: Informática e Ingeniería de Sistemas Centro: Centro Politécnico Superior Universidad: Universidad de Zaragoza Fecha: Diciembre 2010 1 Adaptación de algoritmos de reconocimiento visual para la implementación de juegos para niños basados en dispositivos Tabletop Resumen La idea principal de este proyecto fin de carrera (PFC) consiste en conseguir que los niños muy pequeños puedan interactuar con software y elementos informáticos de una manera más natural, sin depender de los dispositivos básicos, como ratón o teclado, sino usando cualquier tipo de juguete o con sus propias manos. Para lograr este propósito, este PFC se centró en el estudio y ampliación de un software de reconocimiento visual para dispositivos tabletop. El trabajo se realiza sobre NIKvision, una mesa de interacción tangible especialmente diseñada para su uso por niños pequeños. En primer lugar se ha realizado un estudio de los elementos del sistema de NIKvision para, posteriormente, realizar varias fases de análisis e implementación de las distintas funcionalidades necesarias. La primera fase consiste en la búsqueda de reglas para poder crear marcadores personalizados, con la finalidad de que sean capaces de adaptarse a las distintas formas que poseen los juguetes y que puedan tener una determinada forma o significado, no sólo para el ordenador, si no también para los niños (formas de animales, objetos, etc.). La siguiente fase consiste en la modificación del framework de ReacTIVision para permitir la captura de dibujos realizados por los niños en un folio de papel. Estos dibujos estarán marcados con un marcador personalizado diseñado en la fase anterior, para luego poder trabajar con ellos en juegos o aplicaciones que usen la mesa como soporte. La última fase consiste en permitir la detección de movimientos y pulsaciones de las manos de los niños sobre la mesa, así como la detección de juguetes “planos” (juguetes que no lleven marcas especiales en su base) y la orientación que éstos tengan. A partir de cada una de las mejoras se han creado varios juegos para comprobar su funcionamiento. También se ha creado un juego que recoge todo lo implementado en la fases anteriores. El juego captura uno o varios dibujos, realizados en un folio con un fiducial personalizado, para luego poder interaccionar con las versiones digitales de éstos. Los dibujos se muestran en la superficie del tabletop repetidas veces para que el niño pueda golpearlos con sus manos, haciendo que desaparezcan, o desplazarlos a través de la pantalla con sus manos. 2 Índice General Resumen..............................................................................................................................2 Índice General......................................................................................................................3 Capítulo 1. Introducción........................................................................................................5 Motivación inicial..............................................................................................................5 Contexto de desarrollo.....................................................................................................6 Objetivos..........................................................................................................................7 Herramientas....................................................................................................................8 Organización memoria.....................................................................................................9 Capítulo 2. Personalización de fiduciales...........................................................................10 ¿Qué son los fiduciales?................................................................................................10 Representación de los fiduciales....................................................................................11 Formato del fichero........................................................................................................12 Personalización..............................................................................................................13 Capítulo 3. Tratamiento de dibujos.....................................................................................17 Análisis de requisitos......................................................................................................17 Análisis del proceso de detección de fiduciales.............................................................18 Proceso de captura de imagen......................................................................................18 Detección del papel....................................................................................................19 Rectificación de la imagen.........................................................................................20 Limpieza de la imagen...............................................................................................22 Tratamiento posterior del dibujo.....................................................................................23 Configuración de los valores de tamaño........................................................................24 Capítulo 4. Tratamiento de blobs........................................................................................25 Análisis de requisitos......................................................................................................25 Proceso de detección de blobs......................................................................................25 Cálculo de la orientación de blobs.................................................................................28 Envío de la información..................................................................................................30 Configuración de los valores de tamaño........................................................................30 Capítulo 5. Resultados.......................................................................................................32 Juego de asteroides (Personalización de fiduciales).....................................................32 Juego de pintar dibujos (Tratamiento de dibujos)...........................................................33 Juegos de desplazamiento y golpeo con las manos (detección de blobs).....................35 3 Conclusiones..................................................................................................................37 Capítulo 6. Conclusiones....................................................................................................38 Cumplimiento de los objetivos principales......................................................................38 Valoración, opinión y experiencia conseguidas..............................................................38 Trabajo futuro.................................................................................................................39 Anexo 1. Glosario de términos...........................................................................................40 Anexo 2. Estructura de ReacTIVision.................................................................................42 ¿En qué consiste ReacTIVision?...................................................................................42 Funcionamiento de ReacTIVision...................................................................................43 Lectura de la información de la cámara.....................................................................44 Procesadores de información....................................................................................45 Flujo de datos de ReacTIVision.................................................................................48 Diagrama de relación entre clases.................................................................................50 Diagrama de relación entre clases.................................................................................51 Anexo 3. Estructura TUIO...................................................................................................61 ¿Qué es TUIO?..............................................................................................................61 Funcionamiento del protocolo TUIO...............................................................................61 Formato de los paquetes................................................................................................62 Formato de los paquetes................................................................................................62 Información y atributos de los objetos............................................................................62 Anexo 4. Tratamiento de la librería SDL.............................................................................71 ¿Qué es SDL?................................................................................................................71 Funcionamiento de SDL.................................................................................................71 Estructuras y funciones de la librería SDL.....................................................................72 Anexo 5. Desarrollo temporal.............................................................................................78 Anexo 6. Otros Tabletops existentes..................................................................................80 Bibliografía..........................................................................................................................84 4 Capítulo 1. Introducción En este primer capítulo se introduce el proyecto fin de carrera explicando las motivaciones iniciales, el contexto en el que se ha realizado, los objetivos que se persiguen, una breve descripción de las herramientas que se han usado y, en último lugar, la estructura que se sigue en la memoria. 1.1 Motivación inicial Actualmente el acceso a sistemas informáticos se ha extendido considerablemente y ha llegado a una gran variedad de usuarios. No obstante existe una franja de edad que, hasta el momento, no se ha tenido muy en cuenta a la hora de desarrollar software: la de los niños pequeños, de edades comprendidas entre los 3 y 6 años. El control de los dispositivos de interacción normales, tales como ratones, teclados o joystick, les resulta muy difícil a los niños pequeños, debido a que no tienen muy desarrolladas sus capacidades cognitivas y psicomotrices. Por estas dificultades el niño, normalmente, no se siente motivado a utilizar los sistemas informáticos. Por otra parte existen diversos estudios que dicen que en esta etapa de crecimiento el niño necesita relacionarse con otros niños de su misma edad y los dispositivos actuales no suelen dar posibilidades para una buena colaboración entre varios niños jugando de forma conjunta y cooperativa [ChiCI]. Una de las formas que se utilizan para que el niño se comunique de forma más fluida con los sistemas informáticos es utilizando interfaces tangibles. Una interfaz tangible es una forma de comunicar información digital con una computadora a través de objetos corrientes, usándolos de forma natural y por varias personas a la vez. En el caso del tabletop 1 donde se va a realizar el proyecto los objetos que se usan son juguetes, ya que les resultan agradables y están acostumbrados a usarlos, adquiriendo una predisposición a usar el sistema tangible, jugando con él, además de poder utilizar también sus propias manos. El uso de interfaces tangibles es bueno para los niños, ya que permite la manipulación física de objetos y la relación con otros niños, mejorando las capacidades antes citadas [HEBJ]. Una de las posibilidades es usar un tipo de interfaz tangible denominado tabletops en las que el niño interacciona con una mesa simulando el modo de juego que realizaría con juguetes normales. Los tabletops tienen desarrolladas técnicas multitouch para permitir la interacción con la mesa aunque, en la franja de edades que se analizan, estas técnicas son demasiado complejas para los niños (las formas de interaccionar con la mesa son poco intuitivas para ellos y necesitan de una motricidad más desarrollada). Es por eso que se procedió a usar tabletops tangibles que detectasen las acciones y movimientos, pero de manera más básica, centrándose en acciones más simples, como desplazamientos, golpes, es decir, motricidad gruesa. Como consecuencia de lo citado anteriormente se ha buscado el desarrollo de un dispositivo con el que los niños puedan jugar, interaccionando con él de la misma forma que lo harían normalmente: usando juguetes, dibujos y/o con las manos. Al no existir 1 Las palabras y términos en Itálica poseen una breve descripción de su significado en el Anexo 1, Glosario. 5 ningún framework que permitiera este tipo de interacción, se procedió a analizar la posibilidad de adaptar ReacTIVision 2 a nuestras necesidades para realizar mejoras que permitiesen la interacción de los niños con el tabletop NIKvision. Estas mejoras incluyen: el uso de juguetes para interactuar, el uso del tabletop por varios niños al mismo tiempo y la poca necesidad de realizar un manejo de movimientos precisos. 1.2 Contexto de desarrollo Este proyecto se ha realizado dentro del Grupo de Informática Gráfica Avanzada (GIGA) 3 del Departamento de Informática e Ingeniería de Sistemas de la Universidad de Zaragoza, en la línea de trabajo sobre las interfaces tangibles dentro de un proyecto denominado NIKvision 4 . NIKvision es un tabletop tangible que permite a los niños pequeños jugar con el ordenador manipulando juguetes, a los que están acostumbrados, sin necesidad de dispositivos específicos, como ratón o teclado. En la Figura 1.1 se observa la interacción de varios niños con una aplicación informática, a través de juguetes, en el tabletop de NIKVision. Figura 1.1 Niños interactuando con el tabletop de NIKvision Su funcionamiento está basado en la detección visual de objetos que se colocan sobre la mesa y se capturan a través de una cámara. La información obtenida de las imágenes capturadas se envía a un software de procesado que la trata para obtener nuevos datos que se necesiten para interactuar otras aplicaciones. Cuando toda la información de la imagen ha sido procesada, un proyector se encarga de representar la información gráfica del juego por debajo de la superficie de la mesa, para favorecer la interacción que se tenga que realizar en la aplicación. 2 Para más información sobre el funcionamiento de ReacTIVision ir al Anexo 2. 3 http://giga.cps.unizar.es/ 4 http://webdiis.unizar.es/~jmarco/ 6 Figura 1.2 Diagrama de componentes del tabletop NIKvision En la Figura 1.2 se observan las diferentes partes de las que se compone el tabletop de NIKvision (para otros tabletops pueden ser diferentes): – Los juguetes que se utilizan para interactuar (1). – Una cámara para leer los movimientos y posiciones de los objetos (2). Esta cámara puede ver en el espectro infrarrojo, apoyada por una dispositivo que emita luz de este mismo tipo. La razón por la que se utiliza este tipo de luz es la de conseguir una buena detección bajo cualquier tipo de iluminación exterior y que la luz de iluminación de la cámara no interfiera con la imagen proyectada sobre la superficie. – Un ordenador que se encarga de procesar la información leída a través de la cámara y ejecutar el software del juego (3). – Un proyector (4) que plasma una imagen sobre la superficie de la mesa para favorecer la interacción con el juego, ayudado por la reflexión sobre un espejo (5). – Una pantalla donde se visualiza el juego (6). Este PFC utiliza ReacTIVision, un framework de libre distribución para la interacción humana con el ordenador. ReacTIVision realiza un procesado de imágenes provenientes de una cámara para detectar objetos marcados con un identificador gráfico (denominado fiducial) y objetos de forma circular (denominados fingers). Después de realizar este procesado muestra por pantalla los datos obtenidos (tipo, identificador, posición, etc.) y los envía, mediante un protocolo de información denominado TUIO, a otras aplicaciones para que lo gestionen de la manera que lo necesiten. El tratamiento que ReacTIVision realiza sobre las imágenes utiliza la librería de tratamiento multimedia SDL. En los Anexos 2, 3 y 4 se encuentra detallada la forma de funcionamiento, características y funciones de ReacTIVision, el protocolo TUIO y la librería SDL, respectivamente. 1.3 Objetivos El objetivo principal del PFC consiste en lograr que los niños de entre 3 y 6 años pueda interactuar de forma natural con un sistema informático, a través de juegos, en los que se utilizan diferentes tipos de juguetes, las manos, etc. Como, actualmente, no existe ninguna opción software en el mercado que realice este tipo de detección, se ha decidido ampliar las funcionalidades existentes dentro del framework de ReacTIVision para favorecer esa interacción. 7 Para llevar a cabo el desarrollo del objetivo principal es necesario definir una serie de objetivos secundarios que permitirán ampliar el framework de la forma necesaria: •Personalización de identificadores gráficos para adaptarlos a las necesidades de juegos infantiles, basándose en la topología de los marcadores que usa ReacTIVision. •Captura de dibujos en papel a través de la superficie de la mesa para poder utilizarlos en otras aplicaciones. •Reconocimiento y detección de manos y objetos planos para que los niños sean capaces de interactuar con la mesa también con ellas, aportando también la orientación de éstos. Para comprobar el correcto funcionamiento de las mejoras llevadas a cabo en este PFC se procederá a su incorporación en varios juegos interactivos que las utilicen en el entorno de NIKvision. 1.4 Herramientas En este apartado mencionaremos las aplicaciones software y entornos de trabajo más importantes que se han usado para la realización del proyecto: ReacTIVision [REAC] Plataforma de visión por computador de código libre creado para el seguimiento e identificación de identificadores gráficos (fiduciales) añadidos a objetos, además de permitir acciones multitouch mediante el uso de los dedos. Además ReacTIVision es multiplataforma lo que permite que los cambios realizados se puedan ejecutar en varios sistemas operativos. Más información sobre ReacTIVision y su funcionamiento en el Anexo 2. Microsoft Visual Studio 2005. Service Pack 1. Gestor de proyectos y entorno de trabajo de Microsoft 5 que permite crear proyectos para aplicaciones de consola y de ventana. Posee opciones de depurar el código mientras se está ejecutando para observar los valores que tienen las variables y zonas de memoria. También se probó usar otras versiones del mismo gestor, produciendo errores de compilación que en la versión usada no se daban. Fidgen [FID] Aplicación software que genera fiduciales para ReacTIVision a partir de algoritmos genéticos, basándose en ciertos parámetros, como el color de fondo (blanco o negro), el número de elementos en su interior, etc. Esta aplicación se ha usado para deducir las reglas de generación de fiduciales por ReacTIVision y para obtener la composición de los ficheros para así poder crear fiduciales personalizados y adaptados a las necesidades del momento. 5 http://www.microsoft.com/spanish/msdn/vstudio/express/vb/default.mspx 8 1.5 Organización memoria La memoria se organiza de la siguiente forma: –Capítulo 1. Introducción : En este capítulo se incluye la motivación inicial del proyecto, contexto en el que se encuentra, los objetivos que se deben cumplir las herramientas usadas y la organización de la memoria. –Capítulo 2. Personalización de fiduciales : En este capítulo se incluye la explicación y el análisis de cómo se pueden crear fiduciales para simplificarlos y adaptarlos a necesidades estéticas y de forma. –Capítulo 3. Tratamiento de dibujos : En este capítulo se aborda el tema de la captura y del tratamiento de dibujos a través de la mesa de trabajo: análisis de requisitos, análisis del proceso de detección de fiduciales, proceso de captura de la imagen, tratamiento posterior del dibujo y configuración de los valores de tamaño. –Capítulo 4. Tratamiento de blobs : En este capítulo se incluye la explicación del proceso de detección de las interacciones de las manos sobre la mesa, y de otros objetos planos con orientación: análisis de requisitos, proceso de detección, calculo de la orientación de los objetos, envío de la información y configuración de los valores de tamaño. –Capítulo 5. Resultados : En este capítulo se incluyen los resultados de cada implementación, con imágenes de su funcionamiento y de su aplicación en diferentes juegos desarrollados para el tabletop NIKvision. –Capítulo 6. Conclusiones: En este capítulo se incluye la opinión personal sobre el proyecto, valoración y experiencia conseguida, demostración del cumplimiento de los objetivos iniciales e ideas para establecer una continuación o mejora de lo implementado. Además se incluyen los siguientes anexos que complementan el trabajo realizado: –Anexo 1. Glosario de términos: En este anexo se incluye la definición de los términos más relevantes usados en la memoria. –Anexo 2. Estructura de ReacTIVision: En este anexo se explica la estructura software del framework de ReacTIVision, su funcionamiento y su interfaz gráfico, explicando las modificaciones o mejoras que se han realizado con el proyecto en esta parte. –Anexo 3. Estructura TUIO: En este anexo se explica el funcionamiento del protocolo de comunicación que se utiliza en el proyecto, explicando las modificaciones o mejoras que se han realizado con el proyecto en esta parte. –Anexo 4. Tratamiento de la librería SDL: En este anexo se explica el funcionamiento de la librería SDL y la documentación de las funciones que se han usado. –Anexo 5. Desarrollo temporal: En este anexo se indica el tiempo empleado en el desarrollo del proyecto en cada una de las fases. –Anexo 6. Otros Tabletops existentes: En este anexo se comentan algunos tabletops existentes, las características que poseen y la comparación con el tabletop en el que se ha llevado a cabo el proyecto. 9 Figura 2.9 Juguete usado por el juego (izquierda) y fiducial personalizado aplicado a la base (derecha) Con una simplificación excesiva puede ocurrir que se lleguen a detectar fiduciales falsos en otras formas que no lo sean, sin embargo, añadiendo demasiados elementos sucede lo contrario: al incluir demasiados elementos en un mismo espacio, el tamaño de estos tiene que ser disminuido, pudiendo aparecer problemas en la detección. El fiducial debe ser lo suficientemente grande para detectar bien todos los elementos que lo componen, o bien, que la cámara tenga un resolución alta para llegar a captarlos todos. El hecho de simplificar el fiducial supone aumentar la robustez en la detección, ya que los elementos a analizar serán menores permitiendo que del fiducial sea reconocido independientemente del tamaño, evitando aumentar el tamaño de éste o del juguete. Una vez que se consiguió reconocer fiduciales personalizados se procedió a dotar a éstos de una forma que supusiese una identificación visual de su significado al niño. A partir de cualquier dibujo en blanco y negro y se puede crear un dibujo con significado que, a su vez, venga representado por un árbol topológico. En la Figura 2.10 se puede observar esto mismo: el dibujo representa un lápiz, proporcionando al niño una información de que debe realizar algo gráfico con ello, pero además proporciona a ReacTIVision una información de fiducial, concrétamente w012221, del que además se puede extraer la orientación, convirtiéndolo en un fiducial válido. Éste fiducial se usa concretamente colocándolo en un papel para que el niño dibujo sobre él y poder capturar el dibujo realizado a través de la superficie del tabletop, como se explica en detalle en el siguiente capítulo. Figura 2.10 Fiducial válido con representación gráfica. La orientación saldría del vector que va desde el centro de las partes blancas del lápiz al punto negro que está encima. 16 Capítulo 3. Tratamiento de dibujos Habitualmente los niños pueden jugar no sólo usando juguetes, sino también dibujando. Dado que el tabletop donde se trabaja posee una cámara que detecta lo que se coloca en la superficie, se consideró la opción de poder capturar dibujos de los niños mediante el tabletop. El niño dibujará sobre un papel que posee un fiducial determinado y al colocarlo sobre la superficie del tabletop será capturado para luego ser usado en otras aplicaciones. Esta idea surgió a partir del trabajo de Zach Lieberman [ZL] que permite la captura de dibujos realizados sobre la propia mesa a través de un botón para luego interactuar con los elementos de la imagen (ver Anexo 6 para más información sobre diferentes tabletops). La idea pareció interesante para aplicarla a los propios niños pero en vez de tener que dibujar sobre la mesa, hacerlo sobre el papel, forma que les resulta más cotidiana. Además permite que el niño no monopolice la mesa, permitiendo que los niños dibujen en sitios diferentes y luego carguen sus dibujos todos juntos. Para añadirle más sencillez al proceso de captura no hay que pulsar ningún botón como en la mesa de Lieberman, sino que se realizará automáticamente cuando se deposite el folio sobre la superficie. En este capítulo se trata el análisis del funcionamiento de la detección de fiduciales y la modificación de la librería existente para poder realizar una captura de pantalla y poder realizar el procesado de ésta y consta de los siguientes apartados: análisis de requisitos del sistema, análisis del proceso de detección de fiduciales, proceso de captura de la imagen, tratamiento posterior del dibujo capturado y la configuración de los valores de tamaño del papel de dibujo. 3.1 Análisis de requisitos En este apartado se incluyen los requisitos funcionales y no funcionales que deberá cumplir la implementación diseñada: •RF-1: El tabletop deberá capturar dibujos que le sean puestos sobre la pantalla. •RF-2: El framework de ReacTIVision debe poder parametrizarse decidiendo el tamaño y forma del papel de dibujo . •RF-3: El dibujo capturado debe ser enviado a otra aplicación juego para que ésta lo utilice . •RNF-1: El dibujo capturado por el tabletop debe de estar lo más limpio posible de zonas oscuras que se obtienen por el proceso de captura. •RNF-2: La imagen debe ser orientada para quedar totalmente horizontal sin depender de la posición en la que el niño la haya colocado. •RNF-3: La imagen debe se ser tomada cuando el folio lleve un tiempo suficiente sin moverse. 17 3.2 Análisis del proceso de detección de fiduciales Durante el funcionamiento del framework de ReacTIVision la cámara se encarga de enviar frames de lo que está viendo al sistema para que éste los procese. Cada frame que la cámara envía al sistema se analiza para buscar algún fiducial con información para detectar. Para tratar los frames que la cámara está enviando continuamente se opera mediante estructuras del tipo Simple DirectMedia Layer (ver Anexo 4), almacenando cada frame captado por la cámara en un estructura para tratarla. Cada vez que en un frame se encuentra un fiducial que está definido en el framework, se muestra la información del identificador por consola. En la Figura 3.1 se muestra una captura de pantalla del sistema de detección en el que se ven 2 fiduciales que son reconocidos por éste, mostrando la información de su identificador en el centro de cada uno de ellos. Figura 3.1 Pantalla de detección en información de fiduciales. Al fiducial de la izquierda le corresponde el identificador 2, al de la derecha el 1. Durante el proceso de detección se realiza también un proceso de comprobación para determinar si el fiducial se encontraba en el tabletop y si se había detectado con anterioridad. Cuando el framework ha localizado todos los fiduciales del frame envía la información de los datos correspondientes a cada fiducial mediante el protocolo TUIO (ver Anexo 3) a otras aplicaciones que necesiten esa información. 3.3 Proceso de captura de imagen El proceso de captura de la imagen se realiza durante el momento en que se detectan los fiduciales, ya que es cuando se procede a tratar el fiducial que indica la existencia de un papel con un dibujo sobre el tabletop. Por otra parte como la luz con la que se ilumina la parte inferior del tabletop es infrarroja, y la cámara está preparada para ver capturar ese espectro únicamente, los dibujos siempre se capturarán en color negro, aunque estén pintados con otro color. 18 3.3.1 Detección del papel Durante el proceso de captura se comprueba si alguno de los fiduciales detectados en el frame es el buscado, que indica que hay un papel con un dibujo colocado sobre la superficie del tabletop. Cuando el fiducial es detectado se procede a comprobar el tiempo de permanencia, para determinar cuanto tiempo permanece quieto el folio, sin moverse. De este modo se evita que, cuando el niño coloque el folio sobre el tabletop, se capture una imagen errónea por la existencia de movimiento y se asegura la correcta captura de la imagen. Para verificar el tiempo de espera se comprueban las posiciones del fiducial durante los siguientes frames. Para ello se almacena la posición en el frame anterior, en coordenadas x e y, y se comprueba con la posición en el frame actual si el folio se ha desplazado o por el contrario se ha quedado quieto. Si la variación respecto de las posiciones es menor que un valor umbral dado ese frame contará como válido, si no, no se contabilizará y se esperará al siguiente frame para comprobar. El tiempo mínimo de espera se ha establecido como el equivalente a 20 comprobaciones válidas, ya que menos número de comprobaciones apenas permite que el folio sea colocado correctamente; y por el otro lado, más ejecuciones genera un tiempo de espera demasiado alto para resultar aceptable por los usuarios. Una comprobación válida es aquella en que la posición del fiducial entre 2 frames consecutivos ha variado menos que el umbral indicado. Núm. Comprobaciones T. resp. mejor caso(s) T. resp. peor caso(s) T. Medio(s) 10 0,97 2,43 1,7 20 1,7 3,4 2,55 30 2,68 5,8 4,24 40 3,08 6,04 4,56 50 4,69 7,13 5,91 Tabla 3.1 Tabla con los tiempos de respuesta mejores y peores con diferente número de comprobaciones. En la tabla 3.1 se indican los tiempos calculados para diferente número de comprobaciones válidas. El tiempo de respuesta en el mejor caso es el tiempo medio de los mejores tiempos obtenido de los resultados dejando el papel fijo y sin tocarlo. El tiempo de respuesta en el peor caso es el tiempo medio de los peores tiempos obtenidos con el papel moviéndose, es decir, con el niño tocándolo sin poder dejarlo fijo. Con estos datos se calcula el tiempo medio como la suma de ambos tiempos divido entre 2. Una vez que que el folio se considera que está quieto, se almacena la última posición obtenida en el reconocimiento y se envía un mensaje TUIO a otras aplicaciones indicando que se ha detectado un papel y que la captura de la superficie de la mesa se ha realizado con éxito. 19 3.3.2 Rectificación de la imagen Una vez obtenidos los datos de la posición del fiducial en la superficie de la mesa y su orientación se establece el tamaño concreto de la zona del dibujo que se desea capturar. Debido a que en el proceso de captura sólo se ha basado en la posición del fiducial y la quietud del folio, y no en su orientación, éste puede haber sido colocado con cualquier orientación, provocando que la zona de la imagen que se va a capturar no sea la que contenga el dibujo o que salga cortado. Para mejorar el proceso de captura y para permitir que el niño pueda colocar el folio en la posición que el quiera, sin obligarle a que deba posicionarlo de un forma determinada, ya que le puede resultar molesto y quitar fluidez al proceso de captura, se procede a rotar la imagen para que la zona que corresponde al folio quede horizontal. La rotación de la imagen se realiza tomando todo el frame y aplicándole un algoritmo de giro, dado por la librería SDL_rotozoom.h 6 . Este algoritmo gira la imagen obtenida considerando el centro de coordenadas en el centro de ésta, tantos grados como se indican por la orientación del fiducial. Al aplicar este giro el fiducial queda con una orientación de 0º, apuntando su vector de orientación hacia arriba. En las Figuras 3.2 y 3.3 puede observar una imagen con el folio capturado en una posición no horizontal y otra imagen rectificada con el folio colocado en horizontal. Figura 3.2 Imagen capturada mediante la superficie del tabletop antes de ser rectificada para que el folio quede horizontal. Si no se realizase el giro separar el dibujo del resto de la imagen sería más complicado. 6 Para más información ver Anexo 4. 20 Figura 3.3 Imagen rectificada de la Figura 3.2 en la que el folio se encuentra en posición horizontal. Después de rotar el frame es necesario volver a calcular la posición del fiducial, ya que con el giro ésta habrá cambiado. El cálculo de la nueva posición se realiza usando algoritmos de transformación para imágenes, en este caso en concreto se utiliza el de rotación. A partir de la posición en la imagen sin rectificar y la orientación del fiducial se procede al cálculo de la nueva posición. El giro usado para la rectificación se realiza tomando como centro de coordenadas el centro de la imagen, por lo que se debe calcular la posición relativa a este centro, ya que la que el framework toma es con el centro en la esquina superior derecha. Para ello se toman la altura y anchura del frame y se procede al cambio de coordenadas mediante las siguientes fórmulas: x' = x – anchura/2 y' = altura/2 – y Una vez obtenida la posición relativa al nuevo centro se procede a calcular el punto en el que se encontrará ahora el fiducial. Para ello, usando como ángulo el que se ha obtenido para el giro, la orientación del fiducial, se aplican las siguientes fórmulas de transformación definidas en la Figura 3.4. Figura 3.4 Aplicación de la matriz de rotación a un punto de un eje de coordenadas. Una vez que se obtiene la nueva posición en la que se encuentra el fiducial después del giro, se vuelve a calcular la posición respecto al centro de coordenadas, esta vez establecido en la esquina superior izquierda. 21 Una vez obtenida la posición del fiducial se procede a seleccionar la región del frame que se necesita para obtener el dibujo. La imagen tratada hasta el momento contiene todo lo que la cámara ve, pero sólo se necesita la zona del folio que contiene el dibujo, desechando todo lo demás, por lo que se establece un recorte a la imagen para obtener esa región. La zona de recorte se establece a partir de la posición del fiducial tomando un anchura y una altura parametrizables mediante el framework. Hay que considerar también que la posición del fiducial da el centro de éste, por lo que hay que evitar que al recortar la imagen salga parte del fiducial. Para que no salga se establece que el punto origen del recorte no sea el centro exacto del fiducial, si no que esté alejado una distancia, también parametrizable. En la Figura 3.5 se observa la sección del frame que contiene el dibujo recortado. Figura 3.5 Imagen recortada en la que se ha separado el dibujo del resto. Gracias a la altura y a la anchura establecidas se puede determinar el tamaño del dibujo. Usando una distancia a partir del centro del fiducial se ha conseguido que no salga ninguna parte de éste. 3.3.3 Limpieza de la imagen Por mucho que se ajuste la posición de corte para evitar la captura de zonas que no tienen correspondencia con el dibujo, siempre quedan zonas negras, provocadas por las aberraciones en los extremos que posee la lente de la cámara que se usa. Cuando el folio se coloca en las zonas más alejadas del centro del tabletop sufre un abombamiento que hace que el folio no se vea rectangular, sino deformado. Como el recorte se realiza considerando una forma rectángular, si la imagen está deformada, surgirán manchas en negro correspondientes a la zona próxima al folio. Estas zonas en negro afectan al dibujo a capturar ya que, si no se eliminan, formarán parte de éste cuando se utilice en otras aplicaciones. Para eliminar estos errores en la captura se procede a realizar una limpieza de las zonas, que se sitúan siempre en los bordes de la imagen, mediante un algoritmo. El algoritmo de limpieza realiza un borrado de todos los bordes (superior, inferior, lateral izquierdo y lateral derecho) realizando 2 pasadas a la imagen: en la primera se limpian los laterales y en la segunda las zonas superior e inferior. Para realizar eficientemente las pasadas de borrado se trata la imagen como si fuera un matriz. En la primera pasada se recorre la matriz imagen por filas. El algoritmo se coloca en el primer píxel de la fila comprobando si éste es de color negro, si es así, le 22 cambia el color a blanco y avanza al siguiente para realizar la misma comprobación. Si el píxel que se encuentra es de color blanco, significa que ya se ha llegado a la zona del folio y se pasa al lateral opuesto para seguir con el borrado de esa parte. En el lateral opuesto el algoritmo se coloca en el último píxel de la fila y realiza las mismas acciones que en el otro lateral, pero en vez de hacerlo avanzando píxeles, lo hace retrocediendo. Cuando el algoritmo ha terminado de limpiar una fila, pasa a la siguiente, así hasta que se hayan recorrido todas las filas de la imagen. La segunda pasada realiza el mismo proceso que para los laterales, siendo en este caso el recorrido de la matriz por columnas, siendo el primer píxel que se evalúa el de la primera fila y los siguientes los de las filas sucesivas. Cuando se produce el salto al borde inferior del dibujo el píxel por el que se empieza a analizar es el de la última fila y los siguientes los de las filas anteriores. Una vez que se ha realizado el proceso de limpieza de bordes se obtiene la imagen lista para usarla en otras aplicaciones, como se puede ver en la Figura 3.6. Figura 3.6 Dibujo capturado con los bordes limpios de zonas negras por la aberración de la cámara. La implementación que se ha dado al algoritmo de limpieza de bordes no tiene en cuenta los pequeños píxeles de suciedad que puedan surgir en el dibujo, ya que no influyen, siendo lo único que interesa eliminar las amplias zonas en negro que quedan en los bordes. En un primer momento se pensó en aplicar algoritmos específicos para eliminar las zonas del dibujo que estuviesen manchadas para que quedase más limpio, pero al tratarse de de dibujos realizados por los niños y capturados por una cámara es difícil discriminar lo que es parte del dibujo y lo que es suciedad. Un algoritmo de limpieza más complejo podría haber eliminado bastantes partes importantes del dibujo, por lo que se llegó a la conclusión de que lo mejor era realizar un borrado más sencillo y dejar esas manchas, antes que eliminar partes del dibujo. 3.4Tratamiento posterior del dibujo Durante el proceso de detección, en el momento en que se considera que el folio está quieto, se envía un mensaje informando de que se ha detectado el folio con el fiducial. El mensaje envía un identificador de fiducial falso, 500, ya que no interesa que lo use otra aplicación para nada más que indicar la presencia del folio. Cuando el juego recibe este mensaje sabe que tiene que cargar un archivo de dibujo en la dirección específica y se queda esperando a que se cree el archivo, es decir, hasta que el procesado de la imagen haya acabado. Ésto se realiza en una sección crítica en la que el 23 juego no continua ejecutándose hasta que ha leído una imagen, para evitar así que mientras el juego está leyendo una imagen, ReacTIVision la modifique. Una vez que la imagen ha sido tratada y se da por buena es cuando pueden utilizarla otras aplicaciones. Después de que la imagen ha sido limpiada se procede al almacenamiento de ella en el ordenador, guardándola en formato BMP. 3.5Configuración de los valores de tamaño El folio que se usa para realizar y poder capturar el dibujo debe poder ser de cualquier tamaño, siendo el único requisito que posea el fiducial específico para detectarlo. Dejar que cualquier tipo de folio pueda ser usado para capturar los dibujos permite que los dibujos puedan ser de diferentes tamaños y adaptar a diferentes tamaños del tabletop, proporcionando una mayor flexibilidad pero impidiendo usar valores de corte fijos, ya que en algunos dibujos sobrarán partes y en otros faltarán elementos. Esto también sucede cuando se utiliza otra mesa de tamaño diferente, ya que la resolución de la imagen que la cámara obtiene es la misma, 640x480, quedando el dibujo más pequeño si la superficie del tabletop es mayor, o más grande, si su superficie es menor. Por las razones expuestas anteriormente se ha establecido que los valores de altura y anchura de recorte, y el desplazamiento respecto al centro del fiducial sean configurables a partir del framework. La configuración y visualización de las opciones se desarrolló de forma similar al resto de configuraciones de valores en ReacTIVision. La activación del menú de configuración de tamaños se realiza cuando se pulsa la letra 'b' del teclado. Esto permite modificar el tamaño de la zona que se va a recortar por anchura (máximo 600 píxeles) y altura (máximo 400 píxeles). Los valores máximos se decidieron ya que la configuración de pantalla que se usa es 640x480. Para la configuración del desplazamiento se establece como máximo 50 píxeles de anchura, ya que proporcionalmente nunca ocupará más de ese tamaño en el folio. En la Figura 3.6 se puede observar el menú de configuración para los parámetros de configuración de altura, anchura y desplazamiento. Figura 3.7 Parametrización de los valores de configuración: altura (arriba), anchura (centro) y desplazamiento (abajo). 24 Capítulo 4. Tratamiento de blobs Los niños muy pequeños suelen utilizar sus manos para intentar interaccionar con las cosas de su alrededor, antes incluso que utilizando juguetes, para tocar, golpear, etc. Para favorecer que el niño pueda interaccionar sin necesidad de juguetes especiales, se requiere una funcionalidad para detectar los movimientos de las manos de los niños que se encuentren interaccionando con el tabletop. Por otra parte también era necesario permitir el reconocimiento de juguetes que no estuviesen marcados con un fiducial. Este tipo de juguetes son detectados por la forma de su base, como por ejemplo su área o geometría, siendo denominados juguetes “planos”. Además de detectar las manos y los juguetes planos, también se puede obtener la orientación de estos mediante los cálculos de los descriptores. En este capítulo se describe el proceso de detección de manos y objetos planos (denominados blobs), el calculo de la orientación, el envío de la información y la parametrización de las opciones. 4.1 Análisis de requisitos En este apartado se incluyen los requisitos funcionales que deberá cumplir la implementación diseñada: •RF-1: El framework deberá ser capaz de capturar las manos y objetos planos. •RF-2: El framework deberá ser capaz de calcular la orientación de los elementos anteriores. •RF-3: Se podrá parametrizar el tamaño de los blobs en ReacTIVision. 4.2 Proceso de detección de blobs El proceso de detección de blobs se realiza, al igual que la detección de fiduciales, en la zona de procesado de las imágenes (ver Anexo 2 para más información sobre las acciones que realiza ReacTIVision). El propio ReacTIVision realiza una detección de blobs específicos denominados fingers, que poseen forma circular y que pueden ser de varios tamaños, ya que la propia estructura del framework permite configurar el tamaño de detección. Cuando un finger es detectado por el framework, si se encuentra dentro del rango dado, se indica mediante una marca en la pantalla. En la Figura 4.1 se pueden observar varios fingers y los indicadores de detección. . Figura 4.1 Varios fingers detectados y sus indicadores. 25 Capítulo 5. Resultados Al finalizar cada una de las implementaciones del proyecto se ha llevado a cabo el desarrollo de un juego para comprobar el correcto funcionamiento de lo desarrollado y ver si cumplía la función de mejora de la interacción para la que se había diseñado. En este capítulo se presentan los juegos realizados a raíz de las mejoras explicadas en los capítulos anteriores: personalización de fiduciales, a través de un juego de asteroides; captura de dibujos, por medio de un juego de pintar dibujos; y detección de blobs, mediante un juego de movimiento de imágenes y otro juego de golpear dibujos. Además al final del capítulo también se incluyen unas conclusiones. 5.1Juego de asteroides (Personalización de fiduciales) Para realizar este juego se personalizaron 2 fiduciales para colocar debajo de 2 juguetes que actúan como naves, colocándose en la base, en su parte delantera. Las naves poseen un pulsador con un blob finger en su base, que al ser apretado por el niño se posa sobre la pantalla. Cuando se realiza una pulsación, el juego detecta el finger y calcula la distancia al fiducial más cercano para saber de cual es el disparo. En la Figura 5.1 se observa una foto del juguete usado a modo de nave y de su base con el fiducial. Figura 5.1 Forma del juguete nave (izquierda) y parte de abajo de ésta dónde se observa el fiducial añadido. Debido a la forma de la nave y a la situación del pulsador colocar un fiducial con forma totalmente cuadrada hubiese hecho que la nave fuese más grande o que el pulsador se hubiese tenido que colocar en otra parte, haciendo el juguete más grande y su uso más pesado. Para poder incluir el fiducial a la base se decidió que no fuese totalmente cuadrado si no que tuviese forma trapezoidal para adaptarse al morro de la nave, de esta forma se aprovecha que el espacio que queda en la nave para colocarlo. Para obtener la información sobre la orientación del disparo, se calcula el vector entre el centro del fiducial y el finger. El tabletop detecta la posición de las naves y, cuando se acciona el pulsador de la nave, se calcula la orientación, permitiendo que el disparo se efectúe en la dirección en la que se encuentra mirando la nave. 32 En la Figura 5.2 se observa el escenario y modo de funcionamiento del juego. En la superficie del tabletop se dibuja un campo de asteroides y se mueven por la pantalla. Cuando un disparo realizado por alguna nave, alcanza uno de los asteroides, éste se subdivide en más pequeños para que tengan que ser destruidos también. Figura 5.2 Capturas del Juego de asteroides en el que se observa su funcionamiento. 5.2Juego de pintar dibujos (Tratamiento de dibujos) Este juego ha sido desarrollado para trabajar en la captura y tratamiento de dibujos. El juego consiste en realizar un dibujo sobre un folio que tiene impreso un fiducial, concretamente uno personalizado con forma de lápiz. Que el fiducial tenga esta forma indica al niño que debe de realizar un dibujo o algo gráfico en la zona del papel. En la Figura 5.3 se puede observar el folio con un fiducial y un dibujo realizado. Figura 5.3 Folio con fiducial y dibujo. 33 Una vez que el framework ha capturado el dibujo, el juego se encarga de leerlo y proyectarlo sobre la superficie del tabletop. El juego permite cargar hasta 10 dibujos, iguales o diferentes. Cuando se realiza la carga de la imagen en el juego, se le realizan modificaciones: aplicación de transparencias a todas las zonas en blanco para poder visualizar los dibujos o el fondo que haya detrás, y la inversión del color del contorno para volverlo blanco para que haya contraste con el fondo negro del juego. Una vez que el dibujo es proyectado en la superficie va desplazándose aleatoriamente por ésta. En la Figura 5.4 se observa un dibujo capturado por la mesa y cargado en la aplicación del juego. Figura 5.4 Imagen de la aplicación. El mismo dibujo ha sido cargado 2 veces en el juego y se han aplicado las transformaciones de color y transparencia. También se ve que se han distribuido de forma aleatoria por la pantalla. Una vez se tengan cargadas todas las imágenes que se deseen se procede a interactuar con ella mediante el uso de juguetes de colores con fiduciales. Cada vez que un fiducial se coloque encima de una imagen en el tabletop, ésta se pintará de un color u otro, dependiendo del color de juguete al que esté asociado. En la Figura 5.5 se observa la misma imagen coloreada de distintas formas y los fiduciales que activan los colores. 34 Figura 5.5 Imagen coloreada y fiduciales que activan los colores. Rojo (fiducial de la izquierda), verde (fiducial del centro) y azul (fiducial de la derecha). 5.3Juegos de desplazamiento y golpeo con las manos (detección de blobs) Para demostrar el funcionamiento de la detección de los blobs se han creado 2 juegos. El primer juego consiste en una ampliación del juego de captura y tratamiento de dibujos. Además de lo que realizaba anteriormente se le ha incluido la posibilidad de desplazar por la pantalla los dibujos capturados o los que vienen incluidos (árbol y niña). Gráficamente el juego posee un cursor que se posiciona en la zona dónde se coloca la mano. Una vez que se toca un dibujo o cualquiera de los elementos movibles la imagen se desplazará hacia dónde vaya el blob. Si mientras se está desplazando un dibujo se pasa cerca de otro, este también comenzará a seguir al blob. En el momento en que se retira la mano de la superficie las imágenes que se encontraban siendo movidas se quedarán quietas en el último sitio y el cursor se desplazará al lugar dónde de detecte otro blob. En la Figura 5.6 se observan 2 imágenes: en la primera se selecciona el dibujo mediante el cursor y en la segunda se observa el desplazamiento de los objetos. 35 Figura 5.6 Captura del juego de desplazar imágenes. En la imagen de arriba se observa como el cursor se coloca sobre uno de los dibujos. En la imagen de abajo se observa como se ha movido el dibujo, además del árbol. El segundo juego es una aplicación que muestra de manera aleatoria, tanto en posición como en el tipo, las imágenes capturadas para que el niño las golpee y se eliminen, teniendo que hacerlo en un tiempo aleatorio antes de que desaparezca. Primero se debe introducir un dibujo para que la aplicación empiece a mostrar imágenes. Cuando se golpea una imagen ésta se marca como tocada, dibujando un efecto de golpe y desaparece, teniendo que esperar a que vuelva a surgir en otra posición de la pantalla. Durante el desarrollo del juego se pueden introducir más imágenes provocando que, cuando se detecte el folio, el juego se pare hasta que se capture el nuevo, pidiendo al usuario después que quite el papel. Una vez completado la captura del dibujo se vuelven a mostrar otra vez los dibujos, incluyendo los nuevos que se hayan introducido. En la Figura 5.7 se muestran imágenes de el proceso de captura de imágenes durante el desarrollo del juego y en la Figura 5.8 se muestra la interacción de los usuarios con la mesa para jugar. 36 Figura 5.7 Proceso de escaneo de una nueva imagen. Cuando el dibujo se ha terminado de capturar muestra por pantalla un mensaje indicando que ya se puede quitar el folio del tabletop. Figura 5.8 Captura del juego. En esta imagen se muestra el proceso de juego, observándose que cuando se golpea una imagen dentro del tiempo límite se dibujan efectos de golpe. 5.4 Conclusiones Con la creación de estos juegos se ha demostrado que todos los objetivos que se perseguían en el proyecto se han cumplido. Además del objetivo que se quería demostrar con cada juego también se incluyen los anteriores: en cada juego se incluye la personalización de los dibujos y en los juegos de interacción mediante las manos se incluyen también la captura de dibujos. Sin embargo no es necesario para otros juegos que se puedan realizar que se utilicen todas las opciones. 37 Capítulo 6. Conclusiones Una vez finalizado el proyecto y obtenidos los resultados se procede a realizar un breve análisis del trabajo realizado en el que se incluye: el cumplimiento de los objetivos principales, valoración, opinión y experiencias conseguidas y posibles mejoras o partes que incrementar del proyecto. 6.1Cumplimiento de los objetivos principales En los requisitos del proyecto se especificaban los objetivos principales que se debían cumplir para considerarlo acabado. Como se ve en el desarrollo y en los resultados los objetivos se han cumplido : •Se han creado fiduciales personalizados a los que es posible dar forma, con limitaciones, para que se adapten a los objetos o que posean un significado para el usuario. •Se ha logrado capturar un dibujo en papel colocado sobre la pantalla pudiéndose además configurar el tamaño de la zona a capturar, rotar la imagen para que sea lo más horizontal posible y limpiar el dibujo para eliminar zonas muy grandes de color negro. •Se ha conseguido reconocer y detectar manos y objetos planos para interactuar con la mesa, obteniendo su orientación y pudiendo configurar los tamaños que debe detectar. Además de cumplir los objetivos, todo lo que se ha desarrollado se ha incorporado en diferentes juegos para demostrar su correcto funcionamiento. 6.2Valoración, opinión y experiencia conseguidas Desde mi punto de vista personal, este proyecto me ha dado la posibilidad de estudiar y trabajar con la visión por computador y la posibilidad de trabajar con elementos de interacción diferentes a los que existen habitualmente en las aplicaciones. El trabajar con un framework que ya tenía numerosas opciones implementadas, tener que estudiarlo e implementar opciones que se acoplasen a las que ya habían ha resultado costoso, pero práctico porque he aprendido cosas interesantes relacionadas con el tratamiento de las imágenes y además he visto que mi capacidad de interpretar y entender código ajeno ha mejorado. También el hecho de haberlo realizado en C++ me ha dado más soltura en el dominio de este lenguaje, aprendiendo cosas que antes no sabía, como la existencia de elementos lista, así como librerías existentes para el tratamiento del vídeo. Poder probar las mejoras manualmente, interaccionando, como lo harían los propios niños, considero que aporta conocimiento más amplio de lo que se está ejecutando y permite descubrir con más facilidad los errores que puedan surgir y tener idea sobre lo que se puede mejorar con el uso. El hecho de no tener que realizar simplemente un algoritmo que resuelva un problema, si no tener en cuenta que es lo que el usuario va a 38 realizar, supone también un reto. El niño quiere interactuar y jugar de la forma en la que lo hace cotidianamente, por lo que ha habido que adaptarse a su capacidad de manipulación, y no imponerle como debía hacer las cosas, ya que eso hubiese provocado rechazo a usarlo. Algunos de los casos han sido: cálculo del tiempo que había que dejar quieto el folio; ajustarse a lo rápido que mueve las manos y a su respuesta ante los eventos, etc. El valor que tiene el proyecto es interesante, ya que se han incluido opciones que antes no estaban implementadas en el framework para facilitar el acceso a los niños a los sistemas informáticos y para que les resulte atractivo su uso desde pequeños. Estas mejoras pese a que hayan sido desarrolladas para su uso por niños, también pueden ser utilizadas para crear aplicaciones para ser usadas por cualquier tipo de usuario, como por ejemplo interacción con elementos del ordenador a través del tabletop. Por otra parte, hay señalar que algunas de las ideas que se intentaron probar para lograr alguna solución acabaron no siendo posibles. Una fue personalizar fiduciales muy alargados ya que por la forma de detección de fiduciales en regiones cuadradas provocaba que la proximidad entre ellos no los hiciese reconocibles. También hubo ideas que se tuvieron que enfocar de otra manera como la limpieza de los dibujos: al principio se probó a eliminar los grupos muy pequeños de píxeles que provocan sensación de suciedad en la imagen, pero se vio que algunas partes importantes del dibujo también se eliminaban, ya que la captura que se realiza pierde calidad por la aberración de la lente. Por esto se optó por dejar esas manchas, ya que al cargar la imagen en las aplicaciones no interfiere. 6.3Trabajo futuro Como trabajo futuro o mejoras que se podrían incorporar a este proyecto han surgido varias ideas que se comentan a continuación: •Aumentar las opciones de la estructura de información para poder enviar más información de la que se permite (posición e identificador en la mayoría de los casos). Esta mejora es bastante simple ya que consiste en ampliar la librería de envío de información TUIO para que trate los nuevos datos que se quieran enviar. •Modificar el algoritmo de cálculo de orientación de blobs para que pueda detectar orientaciones de 360º y no sólo de 180º. Esto tendrá sentido para objetos que no posean simetría de eje, ya que, en el caso contrario, no hay forma de distinguir ángulos de orientación de más de 180º. •Ampliar el sistema de detección de fiduciales, para que las regiones de búsqueda no sean cuadradas, sino que se puedan adaptar a formas rectangulares. •Ampliar el algoritmo de limpieza de suciedad de las imágenes para limpiar de suciedad el dibujo sin afectar al propio dibujo. Sería necesario un algoritmo más complejo para poder eliminar las zonas de suciedad y distinguirlas de las zonas del dibujo, sin eliminar estas últimas. 39 Anexo 1. Glosario de términos En este apartado se incluye una lista de conceptos básicos necesarios para la correcta interpretación de algunos de los aspectos del proyecto: •Fiducial : imagen usada para identificar un objeto mediante un sistema de detección visual. Esta imagen puede dar información, sobre el tipo de objeto que es, la orientación y la posición del objeto. La imagen consiste en un conjunto de elementos blancos y negros. •Blob : elemento de una imagen que viene determinado por ser un conjunto de píxeles de un color en una región discreta, rodeada por píxeles de otros colores. En el caso de este proyecto los blobs son binarios, o blancos, o negros. •Finger: blob con forma circular que representa un dedo apoyado verticalmente sobre la superficie de la mesa. •Tabletop: mesa usada para la interacción persona – ordenador. La mesa consiste en una superficie transparente en la que se depositan los objetos para ser identificados, un proyector para mostrar una imagen con la que interactuar a través de los objetos y una cámara (vídeo, web, …) para detectar los fiduciales, fingers y blobs que se pongan encima de la superficie. La imagen capturada por la cámara se procesa mediante un software, ReacTIVision en este caso, y la información obtenida se envía, mediante un protocolo de comunicación, TUIO en este caso, a una aplicación que la trate. Esa información se procesa y se envía al proyector para que la plasme sobre la superficie de la mesa. Figura A1.1 Esquema de un Tabletop •Framework: Estructura software de soporte en la que otro proyecto de software puede ser organizado y desarrollado. Esta estructura permite facilitar el desarrollo del software, evitando los detalles de bajo nivel para poder destinar tiempo y esfuerzo a identificar los requerimientos que tendrá lo desarrollado. 40 • Multitouch :Técnica de interacción persona-computador. Esta tecnología consiste en una pantalla táctil que reconoce simultáneamente múltiples puntos de contacto y en un software asociado a ésta que permite interpretar dichas interacciones simultáneas. •Frame: imagen particular que se encuentra dentro de una sucesión de imágenes que componen una animación o video. La sucesión continua de estas imágenes producen sensación de movimiento, provocado por las pequeñas diferencias que hay entre cada una de estas. •Umbralización: acción que consiste en separar, en una imagen en escala de grises, el fondo del objeto, siempre y cuando el fondo y los objetos tengan sus niveles de gris agrupados en 2 niveles dominantes, estableciendo un umbral de separación que puede ser variable. •BMP: Bit Mapped Pictured (mapa de bits). Formato de imágenes que permite guardar imágenes de 24 bits (16,7 millones de colores), 8 bits (256 colores) o menos, sin compresión. Los archivos de mapas de bits se componen de direcciones asociadas a códigos de color, uno para cada cuadro en una matriz de píxeles. •Momento: Parámetros de una imagen que están relacionados con el tamaño, la posición, la orientación y la forma de ésta. Los momentos de denominan de orden p+q, siendo su fórmula: M p,q = ∑ 1 n ∑ 1 m x p y q Ix ,y Donde I(x,y) es el valor de la intensidad del píxel en la posición x,y. •XML: Extensible Markup Language (Lenguaje de marcas extensible). Formato usado para expresar información estructurada a través de etiquetas de la manera más abstracta y reutilizable posible. Una etiqueta consiste en una marca hecha en el documento, que señala una porción de éste como un elemento. •Buffer: Espacio de memoria en el que se almacenan datos para evitar que el programa o recurso que los requiere, ya sea hardware o software, se quede en algún momento sin datos. •Display: Ventana del sistema de detección visual donde se muestra la información de lo que está sucediendo en el framework para que el desarrollador o usuario puedan verla. •OpenGL : Siglas de Open Graphics Library, una especificación estándar que define una interfaz de programación de aplicaciones que se puede integrar en muchos lenguajes de programación y multiplataforma para crear programas que produzcan gráficos en 2D y 3D. La interfaz consiste en más de 250 funciones diferentes que pueden usarse para dibujar escenas tridimensionales complejas a partir de primitivas geométricas simples, tales como puntos, líneas y triángulos. 41 2.2.3 Flujo de datos de ReacTIVision Figura A2.7 Flujo de datos entre los elementos de ReacTIVision. En la Figura A2.7 se observa el flujo de datos que circula entre los diferentes procesadores y elementos de ReacTIVision. Los elementos que se encuentran coloreados en rojo son los que se han modificado para el desarrollo del proyecto: el detector de blobs y fiduciales para realizar la captura de dibujos y la detección de blobs, y el servidor TUIO para el envío de la nueva información. 48 Cámara ReacTIVision Imagen Original Ecualizador de frames Imagen Original Imagen Ecualizada Umbralizador de frames Imagen Ecualizada Imagen Umbralizada Calibrador Ficheros Fichero de árboles y opciones Fichero de configuración de calibrado Imagen Umbralizada Ficheros Imagen Calibrada Detector de blobs y fiduciales Imagen Calibrada Servidor TUIO Información obtenida Figura A2.8 Flujo de información entre los elementos de ReacTIVision y el display gráfico de información. En la Figura A2.8 se muestra el flujo de información entre el framework y display. Los elementos que se encuentran en rojo son los que se han modificado para mostrar nueva información debido a las modificaciones. El detector de fiduciales y de blobs se ha modificado para que muestre por el display los identificadores de los blobs detectados, así como las opciones de configuración del tamaño del folio para la captura de dibujos, como las opciones de configuración del rango de detección de blobs. 49 Cámara Display Imagen Original Umbralizador de frames Calibrador Detector de blobs y fiduciales Rejilla de calibración Configuración gráfica gradiente Identificador Fiduciales Identificador Blobs Opciones de configuración de parámetros 2.3Diagrama de relación entre clases Figura A2.8 Relación entre clases El la Figura A2.8 se muestra la relación entre las clases de ReacTIVision siendo el origen de la flecha la clase que proporciona información a la clase a la que le llega la punta de la flecha. Las clases que tienen el fondo de color rojo son las que se han modificado en el desarrollo del proyecto. En apartado siguiente se especificarán en cada clase los elementos modificados. 50 FrameProcessor PortVideoSDL FrameEqualizer FrameThresholder FidtrackFinder CalibrationEngine CameraTool RingBuffer FontTool FiducialFinder FingerObject FidudcialObject CalibrationGrid RegionProcessor ObjectAnalyzer 2.4Diagrama de relación entre clases En este apartado se incluyen todas las clases que se usan en ReacTIVision, así como sus métodos asociados, sus descriptores y si son clases extendidas de otra. Además se incluyen recuadrados todos los métodos y descriptores modificados o añadidos a cada clase durante el desarrollo del PFC. FrameProcesor Clase genérica que contiene los elementos comunes de los procesadores de frames. Descriptores: Width : Anchura del frame. Height: Altura del frame. SrcBytes: Bytes por píxel en la imagen origen. DestBytes: Bytes por píxel en la imagen destino. SrcSize: Tamaño en bytes de la imagen origen. DestSize: Tamaño en bytes de la imagen destino. DispSize: Tamaño en bytes del display. Msg_listener: Proceso que gestiona a la clase. Métodos: Init(int w, int h, int sb, int db): inicializa sus descriptores con los valores que se le pasan por paramétros: anchura(w), altura(h), bytes por píxel en la imagen origen(sb) y bytes por píxel en la imagen umbralizada(db). Process(unsigned char *src, unsigned char *dest, SDL_Surface *display): realiza un procesado de una imagen dando como resultado una imagen destino e información en pantalla. AddMessageListener(MessageListener *listener): establece el proceso gestor. RemoveMessageListener(MessageListener *listener): eliminar el proceso gestor. Finish(): hace terminar el procesador de frames. SetFlag(int flag, bool value): realiza una activación de pulsación de tecla. ToggleFlag(int flag): realiza la gestión de teclas. GetOptions(): devuelve las opciones del procesador. PortVideoSDL Clase que actúa como el motor de tratamiento de la información de todo el framework. Descriptores: Camera_: Dirección de memoria de la cámara. CameraBuffer_: Buffer donde se almacena lo leido por la cámara. Camera_config: Nombre del fichero de configuración de la cámara. Running_, error_, pause_, calibrate_, help_: Booleanos que inidican si el framework se encuentra corriendo, si ha habido un error, si está pausado, calibrando o mostrando la ayuda. 51 Framenumber_: Número de frame se que está tratando. RingBuffer: Buffer que alamacena hasta 3 frames indicando cual es el siguiente que debe ser leído. Current_fps: Frames por segundo a los que está trabajando la cámara Display_lock: Booleano que indica si el acceso al display está siendo usado por algún procesador o si se encuentra libre. Métodos: PortVideoSDL(const char* name, bool background, const char* camera_config): Constructor de la clase. Run(): Activa el funcionamiento del framework ReacTIVision Stop(): Desactiva del funcionamiento del framework AddFrameProcessor(FrameProcessor *fp): Añade un procesador de frames al motor. RemoveFrameProcessor(FrameProcessor *fp): Eliminar un procesador de frames del motor. SetMessage(std::string message): Escribe el mensaje pasado para ser mostrado por la consola de comandos. DisplayMessage(const char *message): Escribe el mensaje pasado en el display del framework. SetDisplayMode(DisplayMode mode): Establece que está mostrando el display: la imagen original, la imagen umbralizada o nada. GetDisplayMode(): Devuelve el modo en el que se está mostrando el display. CurrentTime(): Devuelve el tiempo que lleva funcionando el framework. SetupWindow(): Inicializa la ventana del display en la que se mostrará la información de la cámara y de la detección. TeardownWindow(): Elimina la ventana del display. SetupCamera(): Inicializa la cámara para que proceda a la captura de imágenes. TeardownCamera(): Deja de usar la cámara. InitFrameProcessors(): Inicializa todos los procesadores de frames que tiene añadidos. Si alguno no se puede inicializar, lo elimina. AllocateBuffers(): Establece el tamaño de los buffers de origen, destino y display y los reserva en memoria. FreeBuffers(): Elimina de memoria el espacio reservado para los buffers. EndLoop(): Finaliza la ejecución de los procesadores de información, mostrando por pantalla un mensaje de error si han finalizado por esa razón. Process_events(): Gestiona el manejo de eventos, que en este caso son las acciones que activan la pulsación de las teclas de opciones. 52 MainLoop(): Ejecuta el bucle principal en el que se realizan todas las acciones de tratamiento de la información de las imágenes. En este método se ha añadido el todo el proceso de tratamiento del dibujo que se va a acaptura: rectificación de la imagen, recorte, limpieza y guardado . Además de los métodos anteriores se han incluido otras funciones para el tratamiento de la imagen obtenida que permiten obtener el dibujo: FrameEqualizer Clase que representa el ecualizador de frames. Esta clase es heredera de la clase FrameProcessor, por lo que hay procedimientos, funciones y descriptores que también son los mismos para él. Métodos: FrameEqualizer(): Constructor de la clase que inicializa el procesador. Process(unsigned char *src, unsigned char *dest, SDL_Surface *display): Procedimiento que realiza la ecualización de la imagen original (src) si se ha pedido que se haga. Init(int w ,int h, int sb, int db): Inicializa el ecualizador de frames. ToggleFlag(int flag): Realiza la gestión de teclas para la configuración del ecualizador. GetState(): Devuelve si se está ecualizando la imagen original. FrameThresholder Clase que representa el umbralizador de frames. Esta clase es heredera de la clase FrameProcessor, por lo que hay procedimientos, funciones y descriptores que también son los mismos para él. Métodos: FrameThresholder(short g): Constructor de la clase que da valor al gradiente con el que se trabajará. Process(unsigned char *src, unsigned char *dest, SDL_Surface *display): Procedimiento que realiza la umbralización de la imagen original(src) y la almacena ya umbralizada (dest). Init(int w ,int h, int sb, int db): Inicializa el umbralizador de frames. DrawGUI(SDL_Surface *display): Dibuja en el display la información sobre el gradiente actual para que se pueda modificar. SetFlag(int flag, bool value): Si flag es la tecla 'g', se activa o desactiva la modificación del gradiente dependiendo del valor de value. 53 To_degrees(float rad): Transforma a grados los radianes pasados por parámetro. Calcular_nueva_pos(SDL_Rect *r, float rad, int w, int h, int w2, int h2, int af): Calcula la nueva posición de un punto de la imagen después de realizar un giro a partir de los radianes girados, el tamaño anterior de la imagen (w, h) y el tamaño actual (w2, h2). Limpia_bordes(SDL_Surface *s): A partir de una imagen dada, s, limpiamos los bordes de la imagen para que no haya zonas en negro muy grandes. ToggleFlag(int flag): Realiza la gestión de teclas para la configuración del umbralizador. GetGradientGate(): Devuelve el valor del gradiente. FidtrackFinder Clase que se encarga de buscar fiduciales y blobs finger en los frames. Esta clase es heredera de la clase FrameProcessor, por lo que hay procedimientos, funciones y descriptores que también son los mismos para él. Métodos: FidtrackFinder(MessageServer *server, const char* tree_cfg, const char* grid_cfg, int finger_size, int finger_sens): Constructor de la clase que da valor al servidor que envía los mensajes con lo detectado (server), al fichero de configuración de los árboles de los fiduciales (tree_cfg), a la superfice calibrada (grid_cfg), al tamaño de los fingers que se van a detectar (finger_size) y a la variación de tamaño que se establece para detectar un finger (finger_sens). Init(int w ,int h, int sb, int db): Inicializa el procesador de detección. GetFingerSize(): Devuelve el valor del tamaño de los fingers que se quieren detectar. GetFingerSensitivity(): Devuelve la variación de tamaño que puede tener un finger para que, aunque no sea del tamaño exacto, se pueda detectar. 54 Process(unsigned char *src, unsigned char *dest, SDL_Surface *display): Realiza la segmentación y procesado de la imagen umbralizada para detectar fiduciales y fingers y muestra los datos por el display. En este método se han realizado modificaciones para realizar la detección del fiducial de captura de dibujo, contabilizar el tiempo que está quiero y enviar la información para que la use la aplicación juego. También se ha realizado la detección de blobs realizando la discriminación por rango de tamaño, el cálculo de los momentos para obtener la orientación y la obtención del punto de interacción. Una vez calculado todo se procede al envío de la información en el que se añade el campo orientación para los blobs. DrawGUI(SDL_Surface *display): Dibuja en el display la información sobre el tamaño de los fingers que se van a detectar para que se pueda modificar, mostrando el tamaño que deben tener para ser reconocidos. Aquí se han realizado modificaciones para poder mostrar las opciones de configuración del tamaño de la zona de captura (con sus máximos y mínimos) y las opciones del rango máximo y mínimo de la detección de blob. Las opciones son mostradas como una barra horizontal en la que se aumenta o disminuye su valor. ToggleFlag(int flag): Realiza la gestión de teclas para la configuración del detector. En la gestión se han incluido también las teclas para lanzar la configuración (m y b). Cuando se están modificando los valores de configuración no se puede llamar a ninguna de las otras opciones de modificación de ReacTIVision hasta que no se termine de darles valores. GetCalibrationMarkers(): Devuelve la lista con todos los fiduciales detectados en el último frame tratado. GetCalibrationPoints(): Devuelve la lista con todos los fingers detectados en el último frame tratado. Reset(): Borra las listas de fiduciales y fingers encontrados. CalibrationEngine Clase que se encarga de la calibración de la imagen obtenida por la cámara. Esta clase es heredera de la clase FrameProcessor, por lo que hay procedimientos, funciones y descriptores que también son los mismos para él. Métodos: CalibrationEngine(const char* out): Constructor de la clase dónde se pasa por parámetro el nombre del fichero donde se almacena la información de calibración de ReacTIVision. Process(unsigned char *src, unsigned char *dest, SDL_Surface *display): Dibuja la rejilla de calibración si se encuentra la opción activada. DrawDisplay(unsigned char* display): Dibuja la rejilla de calibración. Init(int w ,int h, int sb, int db): Inicializa el procesador de calibración. SetFlag(int flag, bool value): Si flag es la tecla 'c', se activa o desactiva la modificación de la rejilla dependiendo del valor de value. ToggleFlag(int flag): Realiza la gestión de teclas para la configuración de calibración. CameraTool Clase que representa la gestión de búsqueda de la cámara. Sólo contiene un método que representa la búsqueda de todos los dispositivos de cámara que se encuentren disponibles en el sistema para cargar el indicado en el fichero de configuración (config_file). findCamera(const char* config_file) RingBuffer Clase que representa el buffer donde se almacenan los siguientes 3 frames que le quedan por trata al framework. Métodos: RingBuffer(int size): Constructor de la clase que reserva espacio en memoria para los 3 bufferes de lectura a partir del tamaño de un frame (size). Size(): Devuelve el tamaño de un frame en bytes: altura * anchura * bytes por pixel. GetNextBufferToWrite(): Devuelve la dirección en memoria del siguiente buffer donde se guardará el siguiente frame a tratar. Si el buffer en donde se ha de escribir está pendiente de leerse, no devuelve ninguna dirección. WriteFinished(): El frame ha sido almacenado correctamente para ser leído y avanza al siguiente índice en el que se va a escribir. GetNextBufferToRead(): Devuelve la dirección en memoria del siguiente buffer donde está almacenado frame para tratarlo en ese momento. Si el buffer en donde 55 se ha de leer está pendiente de escribir, no devuelve nada. ReadFinished(): El frame ha sido leído correctamente para ser leído y avanza al siguiente índice en el que está el siguiente frame a tratar. FontTool Clase que gestiona la escritura de texto por el display gráfico de la pantalla. Métodos: Init(): Inicializa en memoria la fuente que se va a utilizar para escribir por pantalla, ésta viene por defecto. Close(): Libera de memoria la fuente. DrawText(int xpos, int ypos, const char* text, SDL_Surface *display): Escribe el texto dado por text en la posición indicada (xpos, y pos) en el display gráfico. GetFontHeight(): Devuelve el tamaño de letra que se está usando para escribir. GetTextWidth(const char *text): Devuelve la anchura en píxeles del texto (text). FiducialFinder Clase que gestiona el buscador de fiduciales en un frame. Esta clase es heredera de la clase FrameProcessor, por lo que hay procedimientos, funciones y descriptores que también son los mismos para él. Descriptores: FiducialList: Lista dónde se almacenan los fiduciales que se han detectado en el último frame tratado. Session_id: Identificador de sesión que indica en que frame ha sido detectado un fiducial. Totalframes: Número total de frames analizados. Grid_config: Nombre del fichero de configuración en donde se almacenan los datos de la rejilla de calibración. Calibration, show_grid, empty_grid: Booleanos que indican si el framework está claibrado, si hay que dibujar la rejilla y si esta está modificada o no. Tuio_server: Servidor de mensajes TUIO por el cual se enviará la información detectada. Show_settings: Booleano que indica si se han de mostrar por el display las opciones de configuración. Métodos: FiducialFinder(MessageServer *server, const char* grid_cfg): Constructor de la clase que recibe por parámetros el servidor de mensajes (server) y el fichero de configuración de la rejilla (grid_cfg). DrawObject(int id, int xpos, int ypos, SDL_Surface *display, int state): Escribe en el display el identificador de un fiducial detectado en la posición indicado (xpos, ypos) en el color indicado por el estado (state). Este color puede ser verde si el fiducial está bien detectado o rojo si el framework no está seguro debido a una mala calidad de la imagen. 56 DrawGrid(unsigned char *src, unsigned char *dest, SDL_Surface *display): Dibuja en el display gráfico la rejilla y distorsiona la imagen original para que los puntos coincidan con la deformación aplicada sobre la rejilla. DrawGUI(SDL_Surface *display): Dibuja en el display la información sobre la inversión en la detección en el eje x y en el eje y además de en el ángulo. ComputeGrid(): Calcula la matriz de distorsión para aplicar a los puntos de la imagen a partir de los valores de la rejilla modificados. SendTuioMessages(): Se encarga de enviar los mensajes de detección, actualización o borrado de fiduciales mediante el protocolo de comunicación TUIO. FingerObject: Clase que representa un blob finger con sus propiedades. Con la nueva implementación realizad además también representa a los blobs mano y objetos planos. Descriptores: Alive: Indica si el blob finger se encuentra activo en el último frame analizado. Unsent: Indica si el blob está siendo detectado, pero todavía no se ha enviado información sobre él. Session_id: Identificador de sesión del blob. State: Estado del blob: añadido, borrado, expirado o vivo. Smallest_area: mínima área que el blob tiene que tener para ser detectado. Xpos, ypos: posición en pantalla del blob. Además se ha incluido un campo que contiene la información sobre la orientación. Métodos: FingerObject(int width, int height): Constructor de la clase usando como parámetros su altura y anchura (width, height). Update(float xpos, float ypos, float area): Actualiza la información del blob en pantalla: su nueva posición y su nueva área. RedundantSetMessage(TuioServer *server): Crea un mensaje para enviarlo mediante protocolo TUIO cuando no se ha modificado ninguno de sus parámetros. GetStatistics(): Devuelve una cadena con toda la información del blob. CheckStatus(int s_id): Devuelve el estado del blob indicado (s_id). Este estado puede ser: añadido, borrado, expirado o vivo. 57 Update(float xpos, float ypos, float area, float orientacion): Actualiza la información del blob, en la que también se incluye la orientación. AddSetMessage(TuioServer *tserver): Crea un mensaje para enviarlo mediante el protocolo TUIO a otra aplicación cada vez que el blob se actualiza. En el mensaje también se añade la información sobre la orientación del blob. GetTotalMilliseconds(): Devuelve el número de milisegundos operando con los segundos y los microsegundos almacenados. InitSession(): Inicializa el tiempo de la sesión poniendo a 0 sus valores. GetSessionTime(): Devuelve el tiempo que ha pasado desde el inciio de la sesión. GetStartTime(): Devuelve el tiempo absoluto que lleva la aplicación corriendo desde anters de inicializar la sesión. GetSystemTime(): Devuelve el la hora del sistema en segundos y microsegundos. TuioPoint Clase que maneja las posiciones de los objetos, heredando de ella las clases TuioCursor y TuioObject, que representan los blobs y los fiduciales. Descriptores: Xpos, ypos: Coordenadas X e Y representadas en el rango de 0 a 1, para que sea aplicable a cualquier tamaño de superficie. CurrentTime, startTime: Descriptores TuioTime que representan la última actualización del objeto y el momento en el que se ha inicializado el objeto. Métodos: TuioPoint(float xp, float yp): Constructor de la clase que inicializa el objeto en la posición indicada y establece el tiempo actual en los descriptores de tiempo (la última actualización y el tiempo de creación son el mismo). TuioPoint(TuioPoint *tpoint): Constructor de la clase que inicializa el objeto a partir de los valores de posición de tpoint y establece el tiempo actual en los descriptores de tiempo. Update(TuioPoint *tpoint): Actualiza la posición con los valores de tpoint. Update(float xp, float yp): Actualiza la posición con las posiciones pasadas por parámetro. Update(TuioTime ttime, float xp, float yp): Actualiza la clase mediante la nueva posición y el tiempo pasado por parámetro, modificando currentTime. GetX(): Devuelve la posición en el eje X. GetY(): Devuelve la posición en el eje Y. GetDistance(float xp, float yp): Calcula la distancia entre la posición pasada y la del objeto. GetDistance(TuioPoint *tpoint): Calcula la distancia entre el objeto actual y el objeto pasado por parámetro. GetAngle(float xp, float yp): Calcula el ángulo formado entre la posición del objeto y la posición pasada por parámetro. Expresado en radianes. GetAngle(TuioPoint *tpoint): Calcula el ángulo formado entre la posición del objeto actual y la del tpoint pasado por parámetro. Expresado en radianes. GetAngleDegrees(float xp, float yp): Calcula el ángulo formado entre la posición del objeto y la posición pasada por parámetro. Expresado en grados. GetAngleDegrees(TuioPoint *tpoint): Calcula el ángulo formado entre la posición del objeto actual y la del tpoint pasado por parámetro. Expresado en grados. 64 GetScreenX(int width): Devuelve la coordenada X relativa a la anchura de pantalla proporcionada. GetScreenY(int height): Devuelve la coordenada Y relativa a la anchura de pantalla proporcionada. GetTuioTime(): Devuelve el tiempo de la última actualización del objeto. GetStartTime(): Devuelve el tiempo de la creación del objeto. TuioContainer Clase que maneja los atributos de los objetos TuioCursor y TuioObject. Es heredera de la clase TuioPoint por lo que hay funciones y descriptores que son utilizados y definidos. Descriptores: Session_id: Identificador de sesión asignado a cada objeto TUIO creado. X_speed, y_speed: Velocidad en los ejes X e Y. Motion_speed, motion_accel: Valores del valor de la velocidad y de la acelaración de los objetos. Cálculados a partir de las posiciones anteriores. Path: Lista de TuioPoints que alamacena todas las posiciones previas del objeto TUIO. State: Refleja el estado del objeto. Puede ser: TUIO_ADDED, TUIO_ACCELERATING, TUIO_DECELERATING, TUIO_STOPPED, TUIO_REMOVED . Métodos: TuioContainer(TuioTime ttime, long si, float xp, float yp): Constructor de la clase a partir del tiempo actual ttime, el ID indicado si, y la posición en pantalla. El estado en el que se encuentra es el de TUIO_ADDED . TuioContainer(long si, float xp, float yp): Constructor de la clase a partir del ID indicado si, y la posición en pantalla. El estado en el que se encuentra es el de TUIO_ADDED. TuioContainer(TuioContainer *tcon): Constructor de la clase a partir de otro TuioContainer. El estado en el que se encuentra es el de TUIO_ADDED . Update(TuioTime ttime, float xp, float yp): Actualiza la posición del objeto. Mete la nueva posición en la lista y calcula las velocidades y la aceleración. Si motion_accel es positiva el estado pasa a ser TUIO_ACCELERATING , si es negativa pasa a ser TUIO_DECELERATING . Si es igual a 0, TUIO_STOPPED . Update(TuioTime ttime, float xp, float xd, float xs, float ys, float ma): Actualiza los campos del objeto con los parámetros pasados. Además de pasar los datos de anteriores, también se pasan la velocidad en X e Y, además de la aceleración. Update(float xp, float xd, float xs, float ys, float ma): Ídem anterior, pero sin incluir el campo del tiempo. Update(TuioContainer *tcon): Actualiza los datos del TuioContainer a partir de los datos del parámetro pasado. Stop(): Calcula los valores de velocidad y aceleración sin cambiar las posiciones. Remove(TuioTime ttime): Modifica el estado a TUIO_REMOVED y actualizamos el tiempo. 65 GetSessionID(): Devuelve el ID de sesión del objeto. GetXSpeed(): Devuelve la velocidad en el eje X del objeto. GetYSpeed(): Devuelve la velocidad en el eje Y del objeto. GetPosition(): Devuelve la posicion absoluta del objeto en formato TuioPosition. GetPath(): Devuelve la lista con las posiciones previas del objeto. GetMotionSpeed(): Devuelve la velocidad que lleva el objeto. GetMotionAccel(): Devuelve la aceleración que lleva el objeto GetTuipState(): Devuelve el estado en el que se encuentra el objeto., IsMoving(): Comprueba si el objeto se está moviendo. Si su estado es TUIO_ACCELERATING o TUIO_DECELERATING devuelve cierto, si no, falso. TuioObject Clase que representa a los objetos marcadores del sistema de reconocimiento, es decir, los fiduciales. Es una clase heredera de TuioContainer, por lo que comparte descriptores y métodos de ella. Se añade un estado adicional al TuioContainer que simboliza la rotación del objeto, TUIO_ROTATING . Descriptores: Symbol_id: Número identificador de cada fiducial que lo distinge de los demás. Angle: Ángulo que representa la orientación que posee el objeto. Rotation_speed, rotation_accel: Valores de la velocidad y la aceleración de la rotación. Métodos: TuioObject(TuioTime ttime, long si, int sym, float xp, float yp, float a): Constructor de la clase que le da valor a los campos número de identificador, sym y ángulo, a. La velocidad y la aceleración de rotación son nulas. TuioObject(long si, int sym, float xp, float yp, float a): Constructor de la clase que le da valor a los campos número de identificador, sym y ángulo, a. La velocidad y la aceleración de rotación son nulas. TuioObject(TuioObject *tobj): Constructor de la clase que copia los valores del objeto pasado por parámetro. La velocidad y la aceleración de rotación son nulas. Update(TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra): Actualiza los campos del objeto con los parámetros pasados. Si el objeto no se encuentra moviendose y existe una aceleración de rotación, el estado cambia a TUIO_ROTATING . Update(float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra): Ídem anterior. Update(TuioTime ttime, float xp, float yp, float a): Ídem anterior. Update(TuioObject *tobj): Actualiza los datos del TuioObject a partir de los datos del TuioObject pasado. Stop(TuioTime ttime): Calcula los valores de velocidad y rotación sin modificar la posición y la orientación. 66 GetSymbolID(): Devuelve el número identificador del objeto GetAngle(): Devuelve el ángulo de rotación del objeto. GetAngleDegrees(): Devuelve el ángulo de rotación del objeto en radianes. GetRotationSpeed(): Devuelve la velocidad de rotación del objeto. GetRotationAccel(): Devuelve la aceleración de rotación del objeto. GetPosition(): Devuelve la posicion absoluta del objeto en formato TuioPosition. GetPath(): Devuelve la lista con las posiciones previas del objeto. GetMotionSpeed(): Devuelve la velocidad que lleva el objeto. GetMotionAccel(): Devuelve la aceleración que lleva el objeto GetTuipState(): Devuelve el estado en el que se encuentra el objeto., IsMoving(): Comprueba si el objeto se está moviendo. Si su estado es TUIO_ACCELERATING , TUIO_DECELERATING o TUIO_ROTATING , devuelve cierto, si no, falso. TuioCursor Clase que representa a los detectores de seguimiento de fingers. Es una clase heredera de TuioContainer, por lo que comparte descriptores y métodos de ella. Esta clase se modificó para almacenar también la orientación de los blobs, ya que los fingers no tienen orientación. Descriptores: Cursor_id: Identificador del cursor individual que se asigna a todos los marcadores. Orientacion: Orientación del blob. Métodos: TuioCursor(TuioTime ttime, long si, int ci, float xp, float yp, float o): Constructor de la clase a partir de los parámetros pasados. El ID del cursor viende dado por el parámetro ci. También se incluye la orientación dada por o. TuioCursor(long si, int ci, float xp, float yp, float o): Constructor de la clase a partir de los parámetros pasados. TuioCursor(TuioCursor *tcur): Constructor de la clase a partir de los valores del TuioCursor pasado como parámetro. GetCursorID(): Devuelve el identificador del cursor. TuioListener Clase que proporciona a la clase TuioClient una infraestrecutura para tratar los eventos que le llegan sobre lo detectado en el tabletop. La clase es genérica y permite definir clases herederas para implementar las acciones que se realizarán cuando les llega un evento. 67 GetOrientacion(): Devuelve la orientación del cursor. AddTuioObject(TuioObject *tobj): Método invocado cuando se añade un nuevo TuioObject a la sesión. UpdateTuioObject(TuioObject *tobj): Método invocado cuando se actualiza la información de un TuioObject presente en la sesión. RemoveTuioObject(TuioObject *tobj): Método invocado cuando se elimina un TuioObject de la sesión. AddTuioCursor(TuioCursor *tcur): Método invocado cuando se añade un nuevo TuioCursor a la sesión. UpdateTuioCursor(TuioCursor *tcur): Método invocado cuando se actualiza la información de un TuioCursor presente en la sesión. RemoveTuioCursor(TuioCursor *tcur): Método invocado cuando se elimina un TuioCursor de la sesión. Refresf(TuioTime ftime): Invocado por el TuioClient para indicar que ha termiando de recibir un paquete de información. En las aplicaciones desarrolladas para probar las mejoras implementadas se realizan acciones para comprobar el correcto envío y detección de los elementos. Estas acciones consisten en la ejecución de cógio que se realiza cuando se envía información sobre una detección, actualización o eliminación de un fiducial o blob.c En el siguiente ejemplo se peude ver que cada vez que se detecta un nuevo fiducial la aplicación ejecuta un algoritmo para tratar el objeto según sea su identificador: TuioServer Clase que representa el servidor de mensajes que el framework utiliza para enviar la información sobre los fiduciales y los blobs detectados en el tabletop. En esta clase se ha modificado la función de añadir un cursor para poder enviar la información de la orientación de los blobs. Métodos: TuioServer(const char* address, int port): Crea la conexión UDP a partir de la dirección de comunicación y el puerto. FreeObjSpace(): Comprueba si hay sitio en el paquete que se va a enviar para añadir más información sobre fiduciales. Si es así devuelve cierto, si no, devuelve falso. AddObjSeq(int fseq): Crea la cabecera de envío de paquete, incluyendo el identificador de paquete indicado por fseq. AddObjSet(int s_id, int f_id, float x, float y, float a, float X, float Y, float A, float m, float r): Crea un mensaje SET a partir de los datos necesarios para enviar un fiducal: su identificador de sesión, s_id; su identificador de fiducial, f_id; la posición absoluta en pantalla (rango 0..1); el ángulo, a; la velocidad de desplazamiento en los ejes; la velocidad de rotación, A; la aceleración, m; y la velocidad de rotación, r. 68 void TuioListener::addTuioObject(TuioObject *tobj) { mesa->tratar_fiducial(tobj->getSymbolID()); } AddObjalive(int *id, int size): Crea un mensaje ALIVE a partir de un vector en el que se almacenan los fiduciales que se encuentran activos en pantalla y el tamaño del vector. SendObjMessages(): Transmite la información del paquete de objetos, fiduciales, a través del socket de transmisión, permitiendo el nuevo envío de otro paquete. FreeCurSpace(): Comprueba si hay sitio en el paquete que se va a enviar para añadir más información sobre blobs. Si es así devuelve cierto, si no, falso. AddCurSeq(int fseq): Crea la cabecera de envío de paquete, incluyendo el identificador de paquete indicado por fseq. AddCuralive(int *id, int size): Crea un mensaje ALIVE a partir de un vector en el que se almacenan los blobs que se encuentran activos en pantalla y el tamaño del vector. SendCurMessages(): Transmite la información del paquete de objetos, blobs, a través del socket de transmisión, permitiendo el nuevo envío de otro paquete. TuioClient Clase que representa el cliente de mensajes que se encarga de leer la información enviada por el framework para ser usada por la aplicación de la forma necesaria. Cada objeto y cursor que recibe son almacenados en una lista para poder acceder a ellos en otro momento. Descriptores: Socket: Variable donde se almacena la dirección de conexión y por donde se intercambia la información. Métodos: TuioClient(int port=3333): Intenta realizar una conexión con el puerto especificado. Si no se especifica ninguno, se toma por defecto el puerto 3333. Si no logra realizar la conexión informa por la consola de comandos que no se ha podido. Connect(bool lock = false): El cliente empieza a escuchar por el puerto UDP para recibir los mensajes. La variable lock indica si el cliente escuchará únicamente ese puerto, o creará un hilo de ejecución paralelo por donde escuchará, pudiendo realizar otras tareas. Disconnect(): El cliente deja de escuchar por el puerto UDP para dejar de recibir información. IsConnected(): Comprueba e informa de si existe una conexión activa en el momento o no. 69 AddCurSet(int s_id, float x, float y, float X, float Y, float m, float o): Crea un mensaje SET a partir de los datos para enviar un blob: su identificador de sesión, s_id; su posición absoluta en pantalla (rango 0..1); la velocidad de desplazamiento en los ejes y la aceleración, m. En esta función se añadió también la información sobre la orientación de los blobs, o, ya que al estar pensada para tratar fingers, que no tienen orientación, esa información no se incluía. AddTuioListener(TuioListener *listener): Añade un TuioListener a la lista de infraestructuras de mensajes que posee. Al añadirla el cliente es capaz de capturar los eventos relacionados con los tipos de datos a recibir. RemoveTuioListener(TuioListener *listener): Elimina el TuioListener indicado por listener de la lista dónde los tiene almacenados. RemoveAllTuioListeners(): Eliminar todos los TuioListener registrados en la lista dejándola vacía. GetTuioObjects(): Devuelve la lista entera de TuioObjects que tiene el cliente almacenados. Antes de acceder bloquea el acceso a ésta para que no se añadan objetos mientras se están leyendo los datos, desbloqueandolo después. GetTuioObject(long s_id): Devuelve el TuioObject que coincide con el ID de sesión indicado, s_id. Al acceder bloquea la lista para que no sucedan errores. LockObjectList(): Bloquea la lista para evitar actualizaciones durante el acceso a la lista. UnlockObjectList(): Desbloquea la lista para poder realizar actualizaciones. GetTuioCursors(): Devuelve la lista entera de TuioCursor que tiene el cliente almacenados. Antes de acceder bloquea el acceso a ésta para que no se añadan objetos mientras se están leyendo los datos, desbloqueandolo después. GetTuioCursor(long s_id): Devuelve el TuioCursor que coincide con el ID de sesión indicado, s_id. Al acceder bloquea la lista para que no sucedan errores. LockCursorList(): Bloquea la lista para evitar actualizaciones durante el acceso a la lista. UnlockCursorList(): Desbloquea la lista para poder realizar actualizaciones. ProcessPacket(const char *data, int size): Procesa un paquete, obeteniendo los menajes a partir del tamaño de este, size y la ristra de datos, data. 70 ProcessMessage(): A partir de los datos de los mensajes que llegan se realiza su procesado. Primero se comprueba que tipos de datos se han enviado para actualizar la lista de objetos o la de cursores. Luego se hace una comprobación sobre el tipo de mensaje enviado: si es de tipo SET se comprueba si está en la lista, si no está se crea una nueva clase con la información enviada; si se encuentra en la lista, se actualiza con la nueva información. Si es de tipo ALIVE se actualiza la lista de elementos activos con los ID pasados como información. Por último si el mensaje es de tipo FSEQ se recorre la lista de objetos existente y se actualizan todos los objetos que se encuentran a partir de la información del estado de éstos. Para la tratar la información de la orientación de los blobs no circulares se ha modificado la parte en la que trata los paquetes SET para poder incluir la información en su campo. En el caso de que el blob sea circular el valor de la orientación será un número que no representa nigún valor (NaN). Anexo 4. Tratamiento de la librería SDL En este anexo se analizará la librería gráfica SDL que se utiliza para el tratamiento de la información gráfica. ReacTIVision usa esta librería para realizar el tratamiento de las imágenes que llegan de la cámara web, utilizando sus funciones para recorrer la información de la imagen y poder modificarla. 4.1 ¿Qué es SDL? SDL son las siglas de Simple DirectMedia Layer, una biblioteca multimedia y multiplataforma diseñada para facilitar el acceso de bajo nivel a elementos tales como el audio, teclado, ratón, joystick; además de proporcionar soporte al hardware 3D mediante OpenGL y al buffer 2D de vídeo. La biblioteca se encuentra desarrollada en lenguaje C, aunque existen librerías para hacerla funcionar en otros lenguajes, como C++, Ada, etc. Esta biblioteca normalmente es usada para la interfaz gráfica de los reproductores de MPEG , emuladores y videojuegos [VSDL]. 4.2 Funcionamiento de SDL La librería SDL se encarga de proporcionar funciones al programa para realizar las diferentes tareas para la gestión de los elementos multimedia de éste. Las funciones que proporciona se encuentran separadas según la funcionalidad que aporten al sistema: vídeo, tratamiento de eventos, audio, accesos a CD-ROM, tratamiento de hilos paralelos y temporizadores de ejecución. Para acceder a la funciones que se necesiten, es necesario que se inicialicen en algún momento las funcionalidades que se vayan a necesitar, pudiéndose quitar en el momento que se quiera cuando no sea necesario. A continuación se van a comentar las distintas funcionalidades que aporta SDL. Vídeo La gestión de vídeo permite la escritura en la dirección de memoria de la pantalla de la imágenes generadas en el proceso. Una de las funcionalidades básicas es el establecimiento de un modo de vídeo para cualquier resolución y profundad de bits, pudiendo realizar un cambio si el hardware no soporta el modo empleado. Con el modo de vídeo establecido se permite la escritura en un buffer gráfico para poder ser mostrado por pantalla, permitiendo la creación de superficies con atributos como transparencia, colores de los píxeles, etc. Eventos El tratamiento de eventos permite la captura de eventos generados por dispositivos de entrada tales como el ratón, teclado, joystick para realizar unas acciones que afecten al programa o para generar salidas solicitadas por el usuario. SDL permite que el tratamiento de eventos pueda habilitarse o deshabilitarse durante el funcionamiento de la aplicación, permitiendo que cuando no sea necesario capturar determinados eventos no lo realice y volver a activarlo cuando se pueda. Los eventos que se han capturado, se envían a una cola de eventos interna para mantener el orden en que se capturan. 71 Audio La gestión de audio permite la reproducción de audio durante el programa, pudiendo ser el sonido de 8 bits o 16, mono o estéreo y permitiendo la conversión si el formato seleccionado no lo soporta el propio hardware. La reproducción del audio se realiza independientemente, en un hilo de ejecución diferente al principal, por lo que no es necesario que sea creado o eliminado por el programador. CD-ROM El tratamiento del CD-ROM permite la reproducción de pistas de audio almacenadas en un CD-ROM. Las funciones nos permiten saber el número de dispositivos lectores que hay en el ordenador y realizar las tareas de pausa, parada y activación para cada una de las unidades existentes. Hilos paralelos SDL permite la creación de hilos de ejecución paralelos, la posibilidad de implementar semáforos binarios simples para sincronizar los procesos y la creación de barreras de paso. Para la creación de hilos de ejecución paralelos es necesario especificar que función realizará y los datos que necesitará para ejecutarse. A cada hilo de ejecución se le asigna un identificador para tener constancia de su existencia y funcionamiento. A partir de la dirección de ejecución del hilo se pueden eliminar los hilos, obtener sus identificadores, etc. La creación y destrucción de semáforos y barreras se realiza mediante funciones simples. Temporizadores de ejecución Estas funcionalidades permiten realizar operaciones temporizadas en la ejecución del programa. Entre las más importantes de sus operaciones se encuentran las opciones de obtener el número de milisegundos transcurridos desde la inicialización de la librería SDL, la posibilidad parar la ejecución durante un tiempo especificado y la posibilidad de lanzar la ejecución de un hilo cuando hayan pasado un tiempo especificado. 4.3 Estructuras y funciones de la librería SDL En este apartado se analizan las estructuras y las funciones que proporciona la librería SDL, comentando únicamente los elementos que se han usado durante el desarrollo del proyecto. Los elementos que se han usado en el proyecto son: las funcionalidades de vídeo, la gestión de eventos y las operaciones generales. Operaciones Generales SDL_Init(Uint32 flags): inicializa la librería SDL y los subsistemas indicados por parámetros. Estos subsistemas pueden ser: SDL_INIT_TIMER (temporizador), SDL_INIT_AUDIO (audio), SDL_INIT_VIDEO (vídeo), SDL_INIT_CDROM (CD-ROM), SDL_INIT_JOYSTICK (joystick), SDL_INIT_EVERYTHING (inicialización de todo lo anterior), SDL_INIT_NOPARACHUTE (ejecuta el sistema sin que reaccione a elementos fatales) y SDL_INIT_EVENTTHREAD (inicializa el gestor de eventos en un hilo a parte). 72 SDL_InitSubSystem(Uint32 flags): inicializa los subsistemas anteriores después de haber inicializado la librería. Se usa para cargar funciones en algún momento determinado. SDL_QuitSubSystem(Uint32 flags): elimina los subsistemas que han sido cargados cuando no sean necesarios. SDL_Quit(): elimina todos los subsistemas cargados, descarga la librería de la memoria y libera los recursos usados. SDL_WasInit(): proporciona la información sobre que subsistemas se encuentran inicializados. SDL_GetError(): devuelve una cadena con el último error interno de SDL detectado. SDL_SetError(const char *fmt, ...): establece una cadena como un error interno de SDL. SDL_Error(SDL_errorcode code): establece un error según un código interno: SDL_ENOMEM (desbordamiento de memoria), SDL_EFREAD (error de lectura en memoria), SDL_EFWRITE (error de escritura en memoria), SDL_EFSEEK (error de búsqueda en memoria). SDL_ClearError(): elimina toda la información sobre el último error detectado. Útil si el error ha sido capturado por un gestor de eventos. Vídeo En el tratamiento del vídeo se usan superficies denominadas SDL_Surfaces que son las que almacenan la información del contenido gráfico de las imágenes. Una de las superficies tendrá que ser en la que se pinte toda la información que corresponde a la pantalla. Estructuras: SDL_Surface: estructura que representa una zona gráfica en memoria que se puede ser modificada. flags: opciones aplicables a la superficie. *format: formato de los píxeles de la estructura. w, h: altura y anchura de la superficie. pitch: tamaño de la superficie en bytes. *pixels: dirección donde se encuentran los píxeles que forman la superficie. clip_rect: área rectángular asociada a la superficie. La dirección de los píxeles recorre la imágen por filas dándo la información sobre el valor de cada uno de los píxeles. Cada píxel tiene un valor que va asociado a su vez a una paleta de colores, pudiendo ser el mismo valor un color diferente dependiendo de la paleta que se use y los colores que se quieran usar. SDL_Rect: área rectangular de una superficie que contiene la posición respecto a la SDL_Surface asociada y su tamaño dentro de ella. x, y: posición de la esquina superior del rectángulo en la superficie. w, h: anchura y altura de la superficie. 73 Anexo 6. Otros Tabletops existentes En este anexo se analizarán algunos de los proyectos sobre tabletops existentes más relevantes que existen en el mundo, comentado sus características y comparando sus funcionalidades con respecto a las del tabletop usado. 6.1 Zach Lieberman – Drawn Este tabletop permite al usuario dibujar sobre un folio con tinta para ser capturado y poder interactuar con las partes de este. Para realizar la captura del folio es necesario pulsar un botón incluido en la estructura de la mesa. Cuando el dibujo es capturado, el programa separa los elementos independientes del dibujo y permite la interacción del usuario con ellos [ZL]. En la Figura A6.1 se observan el proceso de dibujo y de manipulación del dibujo. Figura A6.1 Tabletop Zach Lieberman – Drawn. A la izquierda se observa el proceso de dibujo. En la imagen de la derecha se observa la interacción con las partes del dibujo una vez capturado. Existen varias diferencias con respecto a lo implementado en el proyecto. En el caso del proyecto realizado al incluir un fiducial al folio y permitir que la imagen sea capturada sin tener que pulsar ningún botón permite que sea más automático que de la otra forma. Como la necesidad era la de capturar el dibujo más que interaccionar con sus elementos se prosiguió con la implementación, si bien, se tomó la idea de incluir la interacción con los elementos de los dibujos una vez que el proceso de captura se finalizase. También existe la diferencia en el proyecto de que durante la interacción con el dibujo se pueden incluir más dibujos, mientras que en el desarrollado por Zach Lieberman no se puede. 6.2 Colaborative Tabletop Tabletop colaborativo que permite la interacción de varios niños de edades superiores a los 6 años mediante un juego de construcción de un hilo de una historia colaborando entre ellos para construirla. El tabletop presenta una zona intermedia donde se depositan diapositivas para que el niño interactúe con ellas, arrastrándolas hacia su zona de juego mediante las manos o mediante el uso del ratón. Este tabletop permite la interacción mediante el uso de manos con las imágenes que se imprimen sobre la superficie al igual que lo desarrollado en el proyecto además de incluir la opción de poder usar el ratón. La opción de incluir ratón en el proyecto que se ha realizado no se 80 contempló ya que lo que se pretende es que los niños usen los elementos de juego con los que están más familiarizados y que estos niños sean de edades inferiores a los 6 años [IRI]. En la Figura A6.2 se muestra la interacción de los niños con el tabletop y la forma de éste. Figura A6.2 Interface del Colaborative Tabletop. Muestra el centro del tabletop en el que se dibujan las diapositivas para ordenarlas luego en los extremos. 6.3 Flux Digital Tabletop Tabletop de tratamiento gráfico que permite el dibujo sobre la superficie mediante el uso de lápices de diferentes tamaños de trazo. Diseñado para realizar dibujos precisos permite también la interacción de varias personas con él, además de incluir la posibilidad de ampliar las zonas de la imagen. Cuando se posiciona la punta de uno de los lápices sobre la superficie del tabletop este la reconoce y va dibujando, siguiendo el recorrido que se haga, un línea. Usando el movimiento con los dedos se puede hacer zoom a las diferentes partes del dibujo para añadir detalles con más precisión, o guardar y cargar otros dibujos diferentes realizados con anterioridad [Flux]. Este tabletop está diseñado para el dibujo preciso en la realización de planos de estructuras, como se puede observar en la Figura A6.3. En el tabletop usado durante el proyecto no se permite el dibujo sobre la superficie, ya que para el niño es más normal dibujar sobre un papel de folio normal. La opción de ampliar las zonas de la imagen tampoco son necesarias ya que lo importante es que el niño pueda interaccionar con lo dibujado y mostrado y no que realice un dibujo preciso. En la Figura A6.4 se puede observar el movimiento de las manos para realizar el zoom al dibujo, haciendo el movimiento de dentro hacia fuera para aumentarlo, o al revés, para disminuirlo. 81 Figura A6.3 Flux Digital Tabletop. En la imagen se observa la superficie de la mesa y como se va dibujando precisamente sobre ella. Figura A6.4 Imagen de la acción para aumentar el zoom del dibujo que se está tratando. 6.4 U-Touch 103'' Multitouch Air Hockey Tabletop que simula el juego de una mesa de Hockey Aéreo. La mesa detecta la posición del dedo de los usuarios, dibujando el mando centrado en el punto de interacción siguiendo la trayectoria de este cuando se desplaza y calculando la dirección que tomará el disco cuando se le golpee. La detección se realiza mediante la detección de fingers que ya viene implementada en el propio programa de ReacTIVision, realizando un cálculo de trayectoria y de rebotes para mostrar el movimiento del disco como si fuese real, aparte de permitir la interacción de más de un usuario [UTAH]. En la Figura A6.4 se muestra una imagen de la aplicación siendo usada por 2 personas. En referencia al trabajo desarrollado en el proyecto se observa que se realiza interacción con elementos digitales además de detectar el movimiento que realizan los jugadores con el dedo. En este caso el dedo interacciona con el disco, mientras que en el que se ha desarrollado el proyecto se interacción con los dibujos capturados. 82 Figura A6.4 Mesa de juego U-Touch 103'' Multitouch Air Hockey 6.5 Reactable Este tabletop permite la creación musical mediante un ordenador. Sus desarrolladores implementaron el framework de ReacTIVision para poder detectar la colocación de diferentes elementos sobre la superficie del tabletop. Mediante la colocación de cubos con fiduciales aplicados bajo una de sus caras se generan los elementos sonoros y a través de la orientación de éstos y la distancia entre los elementos se puede elegir la frecuencia con la que son generados los sonidos. Una vez que la aplicación recibe los valores de la posición de los elementos y su orientación se encarga de generar el audio respecto a estos valores [RT]. Se ha considerado que incluir una descripción de este tabletop era necesaria, ya que el framework usado durante el proyecto es el que se desarrolló para realizar Reactable. En la Figura A6.5 se muestra el funcionamiento y la variación de frecuencia mediante la orientación y distancia. Figura A6.5 Parte superior del tabletop Reactable. En la imagen se puede observar que dependiendo de la distancia donde se coloquen los elementos, la posición y que fiducial se generan diferentes sonidos y formas de onda. 83 Bibliografía [ChiCI]Child Computer Interaction Group http://www.chici.org/janet_read.php [FID] Flexible fiducial generator for reacTIVision based projects http://code.google.com/p/fidgen/ [REAC]ReacTIVision http://reactivision.sourceforge.net/ [CH09]Designable Visual Markers Enrico Costanza, Jeffrey Huang [GS09]Recognition, Tracking and Association of Hands, Fingers, and Blobs: A Tbeta Upgrade. hiago de Freitas Oliveira Araújo [HaDt] Detecting Hands, Fingers and Blobs for Multi-Touch Display Applications Thiago de Freitas Oliveira Araújo, Alexsandro J. V. dos Santos. [TuIts] reacTIVision and TUIO: A Tangible Tabletop Toolkit Martin Kaltenbrunner [DIMG]Descriptores de Imagen Marcos Martín http://poseidon.tel.uva.es/~carlos/ltif10001/descriptores.pdf [MV] Machine Vision Ramesh Jain, Rangachar Kasturi, Brian G. Schunck McGraw-Hill, Inc., ISBN 0-07-032018-7, 1995 http://www.cse.usf.edu/~r1k/MachineVisionBook/MachineVision.pdf [ZL] Thesystemis. The works of Zach Lieberman & Collaborators http://thesystemis.com/ [RT] Reactable http://www.reactable.com [TUIO] TUIO http://www.tuio.org/ [VSDL]Programación de Videojuegos con SDL. Alberto García Serrano. 2003 Ediversitas Multimedia SL [IRI] Informatics Research Institute http://irgen.ncl.ac.uk/wiki/bin/view/Undergrad/RichardWhite [Flux] Flux - Fully Liberating User eXperience http://mi-lab.org/projects/flux/ [UTAH]U-Touch 103'' Multitouch Air Hockey http://wn.com/U-Touch_103_Multitouch_Air_Hockey [HEBJ]Getting a grip on tangible interaction: a framework on physical space and social interaction. Hornecker E., Buur J. (2006) Proc. Of CHI'06, ACM Press. 84