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
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
Referencias: El Bruno Innovation Craftsman
No hay comentarios:
Publicar un comentario