Leap Motion (III): analizamos la API

Con esta entrada cerramos el análisis de Leap Motion que hemos estado haciendo en este blog. Primero te explicamos las características técnicas del dispositivo y, después, su principio de funcionamiento. Hoy vamos a hablar de la parte que más información nos dan en la página oficial, la SDK (versión 2.2.5.26752). Para ello vamos a ver sus partes fundamentales e intentaremos analizarlas ayudándonos de figuras.

Nosotros vamos a analizar la API desde el punto de vista del lenguaje de programación Java, pero debes saber que Leap Motion se puede programar en los siguientes lenguajes de programación y plataformas de desarrollo:

IMG1

Desde la API se puede obtener todo tipo de información tridimensional referente a antebrazos, manos, herramientas, dedos e incluso a los “huesos” de los dedos que se tratan como objetos. Además, desde la versión 2.1. se puede acceder a la información de las imágenes en formato RAW que recoge el dispositivo.

Visión general

El dispositivo utiliza el sistema de coordenadas cartesianas, en donde, desde la posición del usuario, el eje Y tiene valores positivos hacia arriba, el X hacia la derecha y el Z hacia el usuario.

IMG2

La API mide magnitudes físicas con las siguientes unidades:

IMG3

A continuación, vamos a analizar los componentes principales de esta versión. Para ello iremos viendo los objetos principales que el dispositivo puede rastrear, junto con el modelo anatómico que se usa para identificar cada uno, y también analizaremos las clases principales que se describen en la API.

Componentes principales

El principal objeto es Controller(), que se encarga de hacer de interfaz entre la aplicación que desarrollemos y el dispositivo. A continuación podemos ver los métodos que contiene:

IMG4

El que más nos interesa de esta clase es el método frame(), a través del cual podemos acceder al objeto Frame que deseemos; por defecto, al último que ha llegado desde el dispositivo. Además, como se puede observar en uno de los métodos constructores, se puede asociar un objeto de tipo Listener al objeto Controller para poder estar pendientes de los eventos que se produzcan en dicho Controller.

En la siguiente imagen vemos cuáles son los eventos que se producen en el Controller y pueden ser atendidos por el objeto Listener:

IMG5

Como podemos ver, hay diferentes eventos asociados al estado del objeto Controller que al final se traducen en eventos asociados al dispositivo hardware.

Otro método interesante —al igual que en el caso de Controller— es el onFrame(), evento que se produce cada vez que el dispositivo captura una imagen. Este es el evento principal, ya que dentro de este se pueden implementar todas las acciones que queremos hacer sobre los objetos que más adelante veremos (manos, dedos, gestos, etc.).

Así pues, hay dos modos de acceder a un objeto Frame:

  1. Desde el objeto Controller, a través del metodo frame()
  2. Desde el objeto Listener, a través de los eventos que se van disparando

Usar un modo u otro dependerá de si queremos analizar o no todos los frames que lleguen desde Controller. Si queremos analizarlos todos, accederemos a la información del objeto Frame a través de Listener; pero si, por el contrario, queremos analizar un objeto Frame cada cierto tiempo, se accederíamos desde el objeto Controller.

A continuación, podemos ver un diagrama de la relación entre el objeto Frame y los que se puede acceder a través de él:

IMG6

Como vemos, el objeto Frame es la raíz de todos los datos de los objetos que analiza Leap Motion. Frame nos da la posibilidad de acceder a todas las clases List, a partir de las cuales se puede acceder a una lista de objetos del mismo tipo y que aparecen en cada Frame.

La parte que nos interesa en ShowLeap es la que depende de HandList. Esta clase es una lista de objetos de tipo Hand que, a su vez, contiene objetos de tipo Arm, Finger, Pointable y Tool para cada objeto Hand.

Dentro del objeto Hand, podemos acceder a una lista de objetos Finger para cada Hand, en la que podemos acceder a información de cada objeto Finger que aparece en el frame y que forma parte del objeto Hand. A su vez, cada objeto de tipo Finger contiene objetos de tipo Bone. Además, como podemos observar, los objetos Finger y Bone son de tipo Pointable.

A continuación podemos ver un esquema de las partes que componen el objeto Hand con su representación anatómica:

IMG7

A continuación podemos ver la información principal que se puede extraer de cada objeto que depende de Hand:

Información principal incluida en el objeto Hand

  • posición y velocidad de la palma
  • dirección y vectores normales
  • base ortonormal

Información incluida en el objeto Finger

  • posición y velocidad de la punta
  • vector de dirección
  • base ortonormal
  • anchura y longitud

Información incluida en el objeto Bone

  • posición de la articulación
  • base ortonormal
  • anchura y longitud

Información incluida en el objeto Arm

  • posiciones de muñeca y codo
  • vector de dirección
  • base ortonormal
  • anchura y longitud

Información incluida en el objeto Pointable Tool

  • posición y velocidad de la punta
  • vector de dirección
  • base ortonormal
  • anchura y longitud

La siguiente clase a analizar es HandList, que es la encargada de almacenar los objetos Hand:

IMG8

Como se puede observar, a través de esta clase se puede extraer un objeto de tipo Hand mediante el método get(). Además, se puede saber cual es el objeto Hand que está más cerca del dispositivo, más a la izquierda o más a la derecha.

Como ya se ha dicho, HandList provee una lista de objetos Hand que aparecen en el Frame que se está analizando. Vamos a ver el objeto Hand:

IMG9

Como podemos ver, a través de esta clase se puede extraer muchísima información referente al objeto Hand. También se puede acceder a los objetos Finger y Arm que dependen de cada objeto Hand en concreto. Es decir, podemos extraer objetos de tipo dedo y antebrazo de cada mano que aparece en la imagen.

Este objeto puede extraer información basándose en el modelo anatómico de la mano, que fue mejorado en la versión 2.0 y ahora se basa en el esqueleto:

IMG10

Como podemos ver, ahora el modelo de la mano se basa en una estructura de puntos y líneas que describen mejor a un objeto de tipo mano. Con este nuevo modelo aparece el objeto Bones, que ha ayudado a que el dispositivo tenga mejor precisión a la hora de determinar la posición y el gesto de la mano, ya que gracias a la definición de estos puntos si el dispositivo no ve alguno de ellos puede determinar por ejemplo donde está el dedo que no ve o en qué posición está la mano.

En la API también se puede acceder a la información de cada dedo. Para ello se hace uso del objeto Finger, objeto que hay que extraer de la clase FingerList:

IMG11

Como vemos, esta clase es muy parecida a HandList, ya que es una clase que contiene objetos de tipo Finger. Además, también se puede extraer información del objeto Finger más cercano al dispositivo, ya sea a la derecha o a la izquierda. Por lo tanto, dentro de la clase FingerList aparecen los objetos Finger:

IMG12

Este objeto, en el modelo, equivaldría a la siguiente figura:

IMG9 IMG13

Como se puede ver, también se pueden extraer de cada objeto Finger diferentes objetos Bone. Estos objetos representan los puntos que definen al dedo en el modelo y que, en la anatomía definida en la API, estarían representados de la siguiente manera:

IMG14

Como vemos, cada objeto Bone puede ser de un tipo que será el que determine su identificador.

A continuación podemos ver mejor como es interpretado esto por la API:

IMG15

A continuación, podemos ver el objeto Bone:

IMG16

Como se puede observar en el diagrama de la clase, se puede extraer bastante información de cada objeto de tipo Bone. Gracias a este nuevo modelo matemático, se puede determinar mejor la posición de cada objeto y las direcciones, y esto dio lugar a la aparición de un nuevo objeto, el objeto Arm:

IMG17

Además, la API también nos provee de una serie de objetos que ayudan a poder extraer los datos que necesitemos, como por ejemplo el objeto Vector.

Conclusión

Como vemos, el dispositivo Leap Motion cuenta con una API muy extensa y optimizada para la extracción de datos característicos de las partes que forman una mano. Por lo tanto, es un dispositivo óptimo para nuestro proyecto, en el que vamos a analizar el comportamiento de las manos al realizar diferentes signos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *