[#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

   

About these ads

7 pensamientos en “[#KINECT] HowTo: Pintar un skeleton en WPF

  1. Pingback: [#KINECT] HowTo: Pintar 2 skeletons en un Canvas WPF | El Bruno

  2. Pingback: [#KINECT] HowTo: Pintar 2 skeletons en un Canvas WPF - El Bruno

  3. Pingback: [#KINECT] HowTo: Mostrar el contenido de la cámara en WPF | El Bruno

  4. Pingback: [#KINECT] Recopilatorio de enlaces con #KinectSDK (I) | El Bruno

  5. 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

    • 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

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Conectando a %s