[#KINECT] HowTo: Pintar un skeleton en WPF

image

Buenas,

Hoy toca cerrar el viernes con un tutorial de los interesantes > como pintar un skeleton en WPF utilizando la Beta 2 del Kinect for Windows SDK. La base de un skeleton en Kinect es una colección de Joints con los que luego podemos “armar el skeleton”. Además es posible armar y pintar más de un skeleton, para este ejemplo, pues solo pintamos el skeleton[0] en amarillo.

 

Tutorial

1. Crear un nuevo proyecto de tipo WPF Application en Visual Studio 2010.

2. Agregamos las siguientes referencias

  • Microsoft.Research.Kinect
    <%Program Files%>\Microsoft SDKs\Kinect\v1.0 Beta2\Assemblies\Microsoft.Research.Kinect.dll

3. Modificamos la MainWindow para mostrar un título y un Canvas donde mostraremos el skeleton

   1: <Window x:Class="ElBruno.KinectSkeleton01.MainWindow"

   2:         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:         Title="MainWindow" Height="480" Width="360">

   5:     <Grid>

   6:         <TextBlock Text="El Bruno - Skeleton Viewer" 

   7:                    FontSize="20" HorizontalAlignment="Center" />

   8:         <Canvas x:Name="Skeleton" Margin="10,40,10,10" 

   9:                 Background="Black" />

  10:     </Grid>

  11: </Window>

La ventana queda similar a la siguiente

image

4. Agregamos un manejador para el evento Load() de la Window. Además agregamos un runtime para trabajar contra el Kinect e inicializamos el mismo con las opciones básicas de trabajo.

   1: private Runtime _kinect;

   2:  

   3: public MainWindow()

   4: {

   5:     InitializeComponent();

   6:     Loaded += MainWindowLoaded;

   7: }

   8:  

   9: void MainWindowLoaded(object sender, RoutedEventArgs e)

  10: {

  11:     InitKinect();

  12: }

  13:  

  14: void InitKinect()

  15: {

  16:     if (Runtime.Kinects.Count == 0)

  17:         return;

  18:  

  19:     _kinect = Runtime.Kinects[0];

  20:     _kinect.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | 

  21:       RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);

  22:  

  23:         _kinect.VideoStream.Open(ImageStreamType.Video, 2, 

  24:                 ImageResolution.Resolution640x480, ImageType.Color);

  25:         _kinect.DepthStream.Open(ImageStreamType.Depth, 2, 

  26:                 ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);

  27:     _kinect.SkeletonFrameReady += KinectSkeletonFrameReady;

  28: }

En este ejemplo no he puesto ningún tipo de gestión de excepciones, trabajando con una Beta deberíamos agregar algo después.

5. A continuación sólo nos queda pintar nuestro esqueleto en Kinect. Para esto utilizaremos la colección de Joints que nos retorna el Runtime y en el evento KinectSkeletonFrameReady pintaremos los Joints y los Bones que unen los mismos.

   1: void KinectSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)

   2: {

   3:     foreach (var skeleton in 

   4:              e.SkeletonFrame.Skeletons.Where

   5:             (skeleton => 

   6:                       SkeletonTrackingState.Tracked == skeleton.TrackingState))

   7:     {

   8:         Skeleton.Children.Clear();

   9:         PaintBones(skeleton);

  10:         PaintJoints(skeleton);

  11:     }

  12: }

6. Obviamente para que funcione la rutina anterior hace falta la implementación de PaintJoins y de PaintBones. Como pueden ver en el siguiente fragmento de código, es bastante simple ya que solo se recorren las colecciones y se pinta a partir de las mismas.

   1: private void PaintJoints(SkeletonData skeleton)

   2: {

   3:     foreach (Joint joint in skeleton.Joints)

   4:     {

   5:         var jointPos = _kinectCanvas.GetDisplayPosition(joint);

   6:         var jointLine = new Line

   7:                             {

   8:                                 X1 = jointPos.X - 3

   9:                             };

  10:         jointLine.X2 = jointLine.X1 + 6;

  11:         jointLine.Y1 = jointLine.Y2 = jointPos.Y;

  12:         jointLine.Stroke = KinectCanvas.JointColors[joint.ID];

  13:         jointLine.StrokeThickness = 6;

  14:         Skeleton.Children.Add(jointLine);

  15:     }

  16: }

  17:  

  18: private void PaintBones(SkeletonData skeleton)

  19: {

  20:     var brush = new SolidColorBrush(Colors.Yellow);

  21:     Skeleton.Children.Add(_kinectCanvas.GetBodySegment

  22:         (skeleton.Joints, brush, JointID.HipCenter, 

  23:         JointID.Spine, JointID.ShoulderCenter, JointID.Head));

  24:     Skeleton.Children.Add(_kinectCanvas.GetBodySegment

  25:         (skeleton.Joints, brush, JointID.ShoulderCenter, 

  26:         JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));

  27:     Skeleton.Children.Add(_kinectCanvas.GetBodySegment

  28:         (skeleton.Joints, brush, JointID.ShoulderCenter,

  29:         JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));

  30:     Skeleton.Children.Add(_kinectCanvas.GetBodySegment

  31:         (skeleton.Joints, brush, JointID.HipCenter, JointID.HipLeft,

  32:         JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));

  33:     Skeleton.Children.Add(_kinectCanvas.GetBodySegment

  34:         (skeleton.Joints, brush, JointID.HipCenter, JointID.HipRight,

  35:         JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));

  36: }

En el ejemplo completo pueden ver la clase KinectCanvas() que es la que posee las definiciones para convertir joints en points y bones en lineas.

7. Si ejecutamos la aplicación y somos rápidos para sacar un screenshot podremos algo similar a

image

El ejemplo completo se puede descargar desde

https://skydrive.live.com/embedicon.aspx/Code%20Samples/2011%2011%2011%20-%20Kinect%20Skeleton%2001.zip?cid=bef06dffdb192125&sc=documents

 

Saludos @ Here

El Bruno

   

  1. #1 por David el 12 marzo, 2012 - 19:09

    Hola
    Me gustaria hacer lo mismo pero no necesito dibujar los puntos, solo saber cuales són. Como puedo copiar estos puntos que aparecen en pantalla a un fichero xml para cada frame y parte del cuerpo?
    El sample players es el que da todos los puntos de la parte del cuerpo y necessito extraer esos puntos y guardarlos para cada frame en un fichero
    Muchas gracias

    • #2 por elbruno el 12 marzo, 2012 - 21:03

      David buenas,

      pues si interceptas el skeleton en cada refresco de un frame, dentro del mismo tienes toda la informacion de los puntos. Ahora si los quieres guardar en un fichero, solo deberias serializar los mismos.

      Saludos
      El BRuno

      • #3 por David el 14 marzo, 2012 - 16:02

        Hola,
        Primero gracias y segundo, a qué te refieres con serializar los mismos?

  1. [#KINECT] HowTo: Pintar 2 skeletons en un Canvas WPF | El Bruno
  2. [#KINECT] HowTo: Pintar 2 skeletons en un Canvas WPF - El Bruno
  3. [#KINECT] HowTo: Mostrar el contenido de la cámara en WPF | El Bruno
  4. [#KINECT] Recopilatorio de enlaces con #KinectSDK (I) | El Bruno

Deja un comentario

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

Logo de WordPress.com

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

Twitter picture

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

Facebook photo

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

Connecting to %s

Seguir

Get every new post delivered to your Inbox.

Únete a otros 898 seguidores