[#KINECTONE] HowTo: Mostrar el feed del Depth Sensor con #KinectSdk V2

Hola!

Hoy voy a mostrar como se puede utilizar el nuevo KinectSDK v2 para consumir y mostrar los datos del sensor de profundidad. Para este ejempo, trabajaremos en una aplicación WPF con una vista con una imagen, y la misma tiene asociada una propiedad ImageSensor que es la muestra el feed del sensor.

El siguiente ejemplo de código muestra la inicializacion de la Window. En la misma podemos ver que como en los ejemplos de Body y Camara, inicializamos un objeto READER para el feed del Depth, también inicializamos un Frame con la información del sensor de profundidad, y finalmente el bitmap que utilizaremos para mostrar la información.

   1: public ImageSource ImageSource

   2: {

   3:     get

   4:     {

   5:         return _bitmap;

   6:     }

   7: }

   8:  

   9: public MainWindow()

  10: {

  11:     _kinectSensor = KinectSensor.Default;

  12:  

  13:     if (_kinectSensor != null)

  14:     {

  15:         _kinectSensor.Open();

  16:  

  17:          var frameDescription = _kinectSensor.DepthFrameSource.FrameDescription;

  18:         _reader = _kinectSensor.DepthFrameSource.OpenReader();

  19:         _frameData = new ushort[frameDescription.Width * frameDescription.Height];

  20:         _pixels = new byte[frameDescription.Width * frameDescription.Height * _cbytesPerPixel];

  21:         _bitmap = new WriteableBitmap(frameDescription.Width, frameDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null);

  22:         StatusText = "Kinect Started";

  23:     }

  24:     else

  25:     {

  26:         StatusText = "error initializing the kinect sensor";

  27:     }

  28:  

  29:     DataContext = this;

  30:     InitializeComponent();

  31:     Loaded += MainWindow_Loaded;

  32:     Closing += MainWindow_Closing;

  33: }

En el Load de la Window, nos suscribimos al evento FrameArrived del reader. Y ahora veamos un poco lo que hacemos cuando procesamos un frame del DepthSensor.
  • Como en los demás ejemplos, un par de validaciones para no trabajar con objetos nulos
  • Validamos además que el tamaño de la información que nos retorna el sensor sea el mismo del frame que inicializamos al principio de la app
  • Obtenemos los valores mínimos y máximos de profundidad (esto es muy cool!)
  • En un ciclo ForEach recorremos los bytes y calculamos la intensidad de los mismos en base a las distancias mínimas y máximas
  • Luego creamos el array RGB y finalmente creamos el Bitmap con toda esta información
 
   1: void MainWindow_Loaded(object sender, RoutedEventArgs e)

   2: {

   3:     if (_reader != null)

   4:     {

   5:         _reader.FrameArrived += DepthReaderFrameArrived;

   6:     }

   7: }

   8:  

   9: void DepthReaderFrameArrived(object sender, DepthFrameArrivedEventArgs e)

  10: {

  11:                 var frameReference = e.FrameReference;

  12:     try

  13:     {

  14:         var frame = frameReference.AcquireFrame();

  15:  

  16:         if (frame != null)

  17:         {

  18:             using (frame)

  19:             {

  20:                 var frameDescription = frame.FrameDescription;

  21:                 if (((frameDescription.Width*frameDescription.Height) != _frameData.Length) ||

  22:                     (frameDescription.Width != _bitmap.PixelWidth) ||

  23:                     (frameDescription.Height != _bitmap.PixelHeight)) return;

  24:                 frame.CopyFrameDataToArray(_frameData);

  25:  

  26:                 var minDepth = frame.DepthMinReliableDistance;

  27:                 var maxDepth = frame.DepthMaxReliableDistance;

  28:                 var colorPixelIndex = 0;

  29:                 foreach (var depth in _frameData)

  30:                 {

  31:                     var intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0);

  32:  

  33:                     // Write out blue byte

  34:                     _pixels[colorPixelIndex++] = intensity;

  35:                     // Write out green byte

  36:                     _pixels[colorPixelIndex++] = intensity;

  37:                     // Write out red byte                        

  38:                     _pixels[colorPixelIndex++] = intensity;

  39:                     ++colorPixelIndex;

  40:                 }

  41:  

  42:                 _bitmap.WritePixels(

  43:                     new Int32Rect(0, 0, frameDescription.Width, frameDescription.Height),

  44:                     _pixels, frameDescription.Width * _cbytesPerPixel,

  45:                     0);

  46:             }

  47:         }

  48:     }

  49:     catch (Exception)

  50:     {

  51:         // ignore if the frame is no longer available

  52:     }

  53: }

 
Personalmente pienso que esta forma de trabajar con el DepthSensor es MUCHO MAS SIMPLE que la que teníamos en la versión V1.X. Además de ser coherente con el resto de orígenes de datos (body y camara) es bastante de comprender Winking smile

Disclaimer:

“This is preliminary software and/or hardware and APIs are preliminary and subject to change

Saludos @ Córdoba

El Bruno

image image image Google
 
 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.