September 12, 2012

Punto mas cercano con Kinect y Processing

Este es el segundo de los programas que hemos hecho en Processing, para el Kinect, con el objetivo de rastrear los movimientos corporales y en base a ello controlar la interfaz gráfica de la computadora.

El siguiente programa logra encontrar el punto más cercano a la pantalla, y lo rastrea mediante un circulo rojo . El programa es sencillo. Obviamos las partes que ya habían sido usadas y explicadas por Jonathan : donde se hace el setup  del objeto kinect y el tamaño de la ventana, así como hacer disponible la cámara de profundidad.

Lo importante de este código es lo siguiente:



Explicando línea por línea:


closestValue = 8000;
En el rango de los valores de profundidad que pueden tomar los pixeles en la cámara de profundidad del kinect ,podemos ver valores desde 0 hasta 8,000, tomando el valor de 8,000 las partes más lejanas.

Este Valor se toma como el más cercano, para así después compararlo con el valor de otro de los pixeles, el cual, en caso de tener un valor menor a 8,000 (es decir, están más cerca de la cámara) , será el nuevo closestValue. Para así seguir comparando con el resto de pixeles de la imagen.

kinect.update()
Se actualizan los datos que están siendo recibidos por el Kinect.

int[] depthValues = kinect.depthMap();
El método depthMap nos regresa un arreglo de pixeles, los que conforman la imagen recibida por el kinect, los cuales se toman como enteros, por lo que se almacenan en el arreglo de enteros depthValues.

Si te pones a pensar: la imagen está conformada de pixeles distribuidos en ejes X, y Y , es decir, en 2 dimensiones. Entonces, cómo guardar los pixeles en un arreglo unidimensional? 

Esto se hace de la siguiente manera: 
  1. Al iniciar, se lee la primer fila, avanzando columna por columna.
  2. Al terminar el ultimo pixel de la fila 1, pasamos a la fila 2, en el primer pixel.
  3. Y así sucesivamente hasta leer la imagen completa.


Visto de otra manera:
El kinect toma una imagen de 640 x 480 pixeles (este espacio fue declarado en el código al hacer el setup de la pantalla). Por así decirlo: tenemos 480 filas, y 640 columnas. Al leer los pixeles, comenzamos por la primer fila, y leemos hasta el pixel 639 en el eje X (desde 0 hasta 639). Al comenzar en la segunda fila, estamos tomando el pixel numero 640. El primer pixel de la tercera fila será el 1280. Y así sucesivamente, los pixeles iniciales serán múltiplos de 640. De aquí que en el código verás que las coordenadas se multiplican por 640. Esto se usa para leer cualquier posición del arreglo unidimensional de pixeles.

for(int y=0; y<480; y++){
for (int x =0;x<640;x++){
Se recorren los pixeles de la imagen.

int i = x+y*640;
i será la posición de la coordenada x,y en el arreglo de pixeles.

int currentDepthValue = depthValues[i];

El valor que se esté leyendo actualmente es el valor de profundidad actual.

 if(currentDepthValue > 0 && currentDepthValue < closestValue){
 Se compara dicho valor de profundidad actual con el valor más cercano (al incio será 8,000).

closestValue = currentDepthValue;
Como mencionamos antes, si el valor actual es menor a 8,000 (si está mas cerca), el pixel actual sera el más cercano.

closestX = x , closestY = y
Guardamos las coordenadas de dicho valor más cercano, para usarlas al pintar el circulo rojo.

image(kinect.depthImage(), 0,0);
Pintamos la imagen a partir de las coordenadas 0,0.

fill(255,0,0);
ellipse(closestX, closestY, 25, 25);
Pintamos el circulo rojo en la pantalla.


Estas son algunas imagenes de lo que resulta al correr este codigo:






1 comment:

  1. Está bien horrible intentar a acceder su calendarización y no está muy coherente. Según la tabla, han tenido cuatro entregables de 2 + 3 + 10 + 10, pero han presentado solamente tres veces...

    ReplyDelete