Holaaaa.
Mi idea es contar mi experiencia desarrollando con Kinect.
Nació como otro proyecto de I+D acá en Kinetica y después encontró una área de aplicación como prototipo para una exposición en CasaFOA (http://www.casafoa.com/ ). Esta historia es para otro post, ahora prefiero contar cómo comenzar.
Cuando arrancamos, en plural porque trabajé con Fernando Kahan, no había salido aun el SDK. En ese entonces hacer funcionar las cosas era muy difícil. Configurar todo para ejecutar una aplicación simple llevaba horas, días o semanas. Por suerte no tardó en salir el SDK y ahí cambió la cosa.
Bien, la Kinect es un dispositivo con varios sensores. Tiene varias cámaras de video y un micrófono. Usando las diferentes cámaras interpreta la profundidad. Algo así como hacemos nosotros con nuestros ojos. Así nos informa sobre la posición en 3D de las cosas. También tiene la capacidad de decir de dónde viene el sonido (izquierda, derecha). Alguien me dijo alguna vez que también tiene un sensor infrarrojo pero de esto ya no estoy seguro.
Demasiada introducción, ¿cómo arrancamos?
Bueno, te comprás una Kinect (XD), te bajás el SDK: http://www.microsoft.com/en-us/kinectforwindows/develop/overview.aspx y lo instalás. ¡Fantástico!
Ahora veamos un ejemplo sencillo (C#).
Primero nos creamos nuestro objetito Runtime y hacemos algunas magias para configurarlo:
using Microsoft.Research.Kinect.Nui; (...) Runtime runtime = new Runtime(); runtime.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking); runtime.DepthStream.Open( ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
Las magias son para informarle a la Kinect que vamos a usar y que no. Es importante solo inicializar lo que realmente vamos a usar para no afectar la performance. En mi ejemplo digo que voy a usar el índice de jugador (ver 1) y sus posiciones.
¿Sus posiciones? ¿En plural?
Sí, en plural. La Kinect reconoce Skeletons con Joints. Cada Joint representa una parte del cuerpo. Por ejemplo: la cadera, la cabeza o la muñeca izquierda.
Hay 2 formas de obtener esta información. Pidiéndola expresamente en un instante de tiempo; o bien, registrándose al evento que nos brindará la información cuando está disponible. En el siguiente ejemplo voy a tratar de ilustrar la segunda forma:
// Nos registramos al evento runtime.SkeletonFrameReady += SkeletonFrameReadyHandler; (...) // Mi handler del evento. Se llamará cada vez que haya nueva información public void SkeletonFrameReadyHandler(object sender, SkeletonFrameReadyEventArgs eventArgs) { SkeletonFrame skeletonFrame = eventArgs.SkeletonFrame; SkeletonData data = skeletonFrame.Skeletons.First(sk => sk.TrackingState == SkeletonTrackingState.Tracked); if (data == null) { return; } foreach (Joint joint in data.Joints) { Console.WriteLine("Joint:{0} X:{1} Y:{2} Z:{3}", joint.ID, joint.Position.X, joint.Position.Y, joint.Position.Z); } }
Este ejemplo imprimirá, cada vez que llegue información, las coordenadas de cada Joint que detecte. Esto nos brinda la posibilidad de buscar relaciones entre las posiciones de los Joints y descubrir distintas posiciones del jugador. Incluso podemos tener las posiciones históricas y encontrar gestos, como un swing de golf.
Creo que con esto ya tienen para divertirse un rato.
¡Saludos!
PD: Esto fue desarrollado con la primera versión de la SDK, en febrero de este año (2012) ya salió una nueva. Tengo entendido que algunas cosas pueden cambiar pero el ejemplo, en esencia, es similar.
1. Si los jugadores se cruzan se tiene un registro de quien es quien a través de un ID. Muy útil para no confundir jugadores durante un juego.