[# KINECT] Let’s look a little information about how the depth sensor works

image

Good,

After the small post I wrote 2 days ago [# KINECT] HowTo: display the contents of the depth sensor in our applications, today we will see a little more detail or the guts of this mechanism. As well as the camera viewfinder is simply map of RGB values that convert to an image and then we show with an IMAGE of WPF, the information that gives us the depth sensor is a collection of distances that then "we paint" in our application.

The distances that handles Kinect ranges from 0.85 m to 4 m; and the information that we provide the depth sensor in millimeters. If we look at the code from the example of the post, we see that during the processing of the event DepthFrameReady() of the sensor, we work with an object of type PlanarImage (line 3). In this case the array of pixels that we return the sensor contains 2 bytes for every pixel. Each of these bytes determined us the distance to each of the cameras used the sensor.

   1: void KinectDepthFrameReady(object sender, ImageFrameReadyEventArgs e)
   2: {
   3:     var planarImage = e.ImageFrame.Image;
   4:     var depthImageHelper = new DepthImageHelper();
   5:     byte[] convertedDepthBits = 
   6:            depthImageHelper.ConvertDepthFrame(planarImage.Bits, RuntimeOptions);
   7:     if (this.imageHelper == null)
   8:     {
   9:         this.imageHelper = new InteropBitmapHelper(planarImage.Width, 
  10:                                                    planarImage.Height, 
  11:                                                    convertedDepthBits);
  12:         this.DepthSensorViewer.Source = this.imageHelper.InteropBitmap;
  13:     }
  14:     else
  15:     {
  16:         this.imageHelper.UpdateBits(convertedDepthBits);
  17:     }
  18: }

In addition, if we initialized the sensor with the option [DepthAndPlayerIndex], the array of information will contain 3 bytes where the 3rd byte corresponds to a specific player recognized by the sensor.

To identify the real value of the depth of each element of the array, we need to check if the sensor has been initialized with the option to [Depth] or [DepthAndPlayerIndex]. In the example of the post, we do from a simple calculation taking into account if we work with 3 or 2 bytes. In this case depthFrame is an array of bytes that we then convert to an image using the InteropBitmapHelper class we saw in the previous post.

   1: var hasPlayerData = runtimeOptions.HasFlag(RuntimeOptions.UseDepthAndPlayerIndex);
   2: for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
   3: {
   4:     var player = hasPlayerData ? depthFrame16[i16] & 0x07 : -1;
   5:     int realDepth;
   6:  
   7:     if (hasPlayerData)
   8:     {
   9:         realDepth = (depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
  10:     }
  11:     else
  12:     {
  13:         realDepth = (depthFrame16[i16 + 1] << 8) | (depthFrame16[i16]);
  14:     }
  15:  
  16:     // transform 13-bit depth information into an 8-bit intensity appropriate
  17:     // for display (we disregard information in most significant bit)
  18:     var intensity = (byte)(255 - (255 * realDepth / 0x0fff));
  19:  
  20:     depthFrame32[i32 + RedIndex] = 0;
  21:     depthFrame32[i32 + GreenIndex] = 0;
  22:     depthFrame32[i32 + BlueIndex] = 0;

The great lack at this point, is to know the depth of a Joint or an element of the Skeleton in order to have access to gesturas as a Push or Pull.

Unfortunately that doesn’t come from factory in Kinect Beta 2 SDK , but…. isn’t so complicated no?

In the next post about Kinect solve it with 4 lines of code (that if the Victor returns me the Kinect!)

Greetings @ Home

The Bruno

PS: I have finished writing the post, but I see that on the challenges of MSDN they explain very, very well!http://blogs.msdn.com/b/esmsdn/archive/2011/07/20/Reto-kinect-Usar-Las-c-225-maras-del-sensor.aspx

[#KINECT] Veamos un poco de información sobre como funciona el sensor de profundidad

image

Buenas,

después del pequeño post que escribí hace 2 días [#KINECT] HowTo: Mostrar el contenido del depth sensor en nuestras aplicaciones, hoy veremos un poco más el detalle o las tripas de este mecanismo. Así como el visor de la cámara simplemente es mapa de valores RGB que convertimos a una imagen y luego mostramos con un IMAGE de WPF, la información que nos da el sensor de profundidad es una colección de distancias que luego "pintamos” en nuestra aplicación.

El rango de distancias que maneja Kinect va desde los 0,85 metros hasta los 4 metros; y la información que nos provee el sensor de profundidad es en milímetros. Si analizamos el código del ejemplo del post, veremos que durante el procesamiento del evento DepthFrameReady() del sensor, trabajamos con un objeto del tipo PlanarImage (línea 3). En este caso el array de pixels que nos retorna el sensor contiene 2 bytes por cada pixels. Cada uno de estos bytes nos determina la distancia a cada una de las cámaras que utiliza el sensor.

   1: void KinectDepthFrameReady(object sender, ImageFrameReadyEventArgs e)

   2: {

   3:     var planarImage = e.ImageFrame.Image;

   4:     var depthImageHelper = new DepthImageHelper();

   5:     byte[] convertedDepthBits = 

   6:            depthImageHelper.ConvertDepthFrame(planarImage.Bits, RuntimeOptions);

   7:     if (this.imageHelper == null)

   8:     {

   9:         this.imageHelper = new InteropBitmapHelper(planarImage.Width, 

  10:                                                    planarImage.Height, 

  11:                                                    convertedDepthBits);

  12:         this.DepthSensorViewer.Source = this.imageHelper.InteropBitmap;

  13:     }

  14:     else

  15:     {

  16:         this.imageHelper.UpdateBits(convertedDepthBits);

  17:     }

  18: }

Adicionalmente, si inicializamos el sensor con la opción [DepthAndPlayerIndex], el array de información contendrá 3 bytes donde el 3er byte corresponde a un player específico reconocido por el sensor.

Para identificar el valor real de la profundidad de cada elemento del array, tenemos que verificar si el sensor se inicializó con la opción [Depth], o con [DepthAndPlayerIndex]. En el ejemplo del post, lo hacemos a partir de un simple cálculo teniendo en cuenta si trabajamos con 3 o 2 bytes. En este caso depthFrame es un array de bytes que luego convertimos a una imagen utilizando la clase InteropBitmapHelper que vimos en el post anterior.

   1: var hasPlayerData = runtimeOptions.HasFlag(RuntimeOptions.UseDepthAndPlayerIndex);

   2: for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)

   3: {

   4:     var player = hasPlayerData ? depthFrame16[i16] & 0x07 : -1;

   5:     int realDepth;

   6:  

   7:     if (hasPlayerData)

   8:     {

   9:         realDepth = (depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);

  10:     }

  11:     else

  12:     {

  13:         realDepth = (depthFrame16[i16 + 1] << 8) | (depthFrame16[i16]);

  14:     }

  15:  

  16:     // transform 13-bit depth information into an 8-bit intensity appropriate

  17:     // for display (we disregard information in most significant bit)

  18:     var intensity = (byte)(255 - (255 * realDepth / 0x0fff));

  19:  

  20:     depthFrame32[i32 + RedIndex] = 0;

  21:     depthFrame32[i32 + GreenIndex] = 0;

  22:     depthFrame32[i32 + BlueIndex] = 0;

La gran carencia en este punto, es poder lograr conocer la profundidad de un Joint o de un elemento del Skeleton para poder tener acceso a gesturas como Push o Pull.

Lamentablemente eso no viene de fábrica en la Beta 2 del SDK de Kinect, pero …. tampoco es tan complicado no?

En el próximo post de Kinect lo solucionamos con 4 líneas de código (eso si el Victor me devuelve el Kinect!!!!)

 

Saludos @ Home

El Bruno

   

PD: he terminado de escribir el post, pero veo que en los retos de MSDN lo explican muy pero muy bien !!! http://blogs.msdn.com/b/esmsdn/archive/2011/07/20/reto-kinect-usar-las-c-225-maras-del-sensor.aspx