I've been having some serious trouble getting skeleton tracking working properly for Kinect For Windows, using SDK v1.5 and VS2012. I'm building on the source code from https://github.com/EvilClosetMonkey/Fizbin.Kinect.Gestures , but the tracking goes completely astray when there's multiple people on the screen. I've then gone on to look at the code here ( http://social.msdn.microsoft.com/Forums/en-US/kinectsdknuiapi/thread/459012d7-d51e-460d-aa6a-a1b80c27626c/ ), and I've attempted to integrate the "AppChoosesSkeletons" functionality (code below):
using System.Windows;
using System.Windows.Data;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Samples.Kinect.WpfViewers;
using System.Diagnostics;
using System.ComponentModel;
using System.Linq;
using System;
namespace Fizbin.Kinect.Gestures.Demo
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private readonly KinectSensorChooser sensorChooser = new KinectSensorChooser();
private Skeleton[] skeletons = new Skeleton[0];
// skeleton gesture recognizer
private GestureController gestureController;
public MainWindow()
{
DataContext = this;
InitializeComponent();
// initialize the Kinect sensor manager
KinectSensorManager = new KinectSensorManager();
KinectSensorManager.KinectSensorChanged += this.KinectSensorChanged;
// locate an available sensor
sensorChooser.Start();
// bind chooser's sensor value to the local sensor manager
var kinectSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
BindingOperations.SetBinding(this.KinectSensorManager, KinectSensorManager.KinectSensorProperty, kinectSensorBinding);
}
#region Kinect Discovery & Setup
private void KinectSensorChanged(object sender, KinectSensorManagerEventArgs<KinectSensor> args)
{
if (null != args.OldValue)
UninitializeKinectServices(args.OldValue);
if (null != args.NewValue)
InitializeKinectServices(KinectSensorManager, args.NewValue);
}
/// <summary>
/// Kinect enabled apps should customize which Kinect services it initializes here.
/// </summary>
/// <param name="kinectSensorManager"></param>
/// <param name="sensor"></param>
private void InitializeKinectServices(KinectSensorManager kinectSensorManager, KinectSensor sensor)
{
// Application should enable all streams first.
// configure the color stream
kinectSensorManager.ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
kinectSensorManager.ColorStreamEnabled = true;
// configure the depth stream
kinectSensorManager.DepthStreamEnabled = true;
kinectSensorManager.TransformSmoothParameters =
new TransformSmoothParameters
{
Smoothing = 0.5f,
Correction = 0.5f,
Prediction = 0.5f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.04f
};
// configure the skeleton stream
sensor.SkeletonFrameReady += FramesReady;
kinectSensorManager.SkeletonStreamEnabled = true;
sensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
// initialize the gesture recognizer
gestureController = new GestureController();
gestureController.GestureRecognized += OnGestureRecognized;
kinectSensorManager.KinectSensorEnabled = true;
if (!kinectSensorManager.KinectSensorAppConflict)
{
// addition configuration, as needed
}
}
/// <summary>
/// Kinect enabled apps should uninitialize all Kinect services that were initialized in InitializeKinectServices() here.
/// </summary>
/// <param name="sensor"></param>
private void UninitializeKinectServices(KinectSensor sensor)
{
}
#endregion Kinect Discovery & Setup
#region Properties
public static readonly DependencyProperty KinectSensorManagerProperty =
DependencyProperty.Register(
"KinectSensorManager",
typeof(KinectSensorManager),
typeof(MainWindow),
new PropertyMetadata(null));
public KinectSensorManager KinectSensorManager
{
get { return (KinectSensorManager)GetValue(KinectSensorManagerProperty); }
set { SetValue(KinectSensorManagerProperty, value); }
}
/// <summary>
/// Gets or sets the last recognized gesture.
/// </summary>
private string _gesture;
public String Gesture
{
get { return _gesture; }
private set
{
if (_gesture == value)
return;
_gesture = value;
Debug.WriteLine("Gesture = " + _gesture);
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Gesture"));
}
}
#endregion Properties
#region Events
/// <summary>
/// Event implementing INotifyPropertyChanged interface.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region Event Handlers
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e">Gesture event arguments.</param>
private void OnGestureRecognized(object sender, GestureEventArgs e)
{
Debug.WriteLine(e.GestureType);
switch (e.GestureType)
{
case GestureType.Menu:
Gesture = "Menu";
break;
case GestureType.WaveRight:
Gesture = "Wave Right";
break;
case GestureType.WaveLeft:
Gesture = "Wave Left";
break;
case GestureType.JoinedHands:
Gesture = "Joined Hands";
break;
case GestureType.SwipeLeft:
Gesture = "Swipe Left";
break;
case GestureType.SwipeRight:
Gesture = "Swipe Right";
break;
case GestureType.ZoomIn:
Gesture = "Zoom In";
break;
case GestureType.ZoomOut:
Gesture = "Zoom Out";
break;
default:
break;
}
}
void FramesReady(object sender, AllFramesReadyEventArgs e, KinectSensor sensor)
{
Skeleton skeleton = FindSkeleton(e);
if (skeleton != null)
{
gestureController.UpdateAllGestures(skeleton);
}
}
private int CurrentTrackingId = 0;
Skeleton FindSkeleton(AllFramesReadyEventArgs e)
{
Skeleton skeleton = null;
using (SkeletonFrame SFrame = e.OpenSkeletonFrame())
{
if (SFrame == null)
{
return null;
}
if (skeletons == null)
{
skeletons = new Skeleton[SFrame.SkeletonArrayLength];
}
SFrame.CopySkeletonDataTo(skeletons);
if (CurrentTrackingId != 0)
{
// We've been tracking someone; see if they're still here
skeleton =
(from s in skeletons
where s.TrackingState == SkeletonTrackingState.Tracked &&
s.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked &&
s.TrackingId == CurrentTrackingId
select s).FirstOrDefault();
if (skeleton == null)
{
CurrentTrackingId = 0;
sensor.SkeletonStream.AppChoosesSkeletons = false;
}
}
else
{
// Try to find someone new
skeleton =
(from s in skeletons
where s.TrackingState == SkeletonTrackingState.Tracked &&
s.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked
select s).FirstOrDefault();
if (skeleton != null)
{
CurrentTrackingId = skeleton.TrackingId;
sensor.SkeletonStream.AppChoosesSkeletons = true;
sensor.SkeletonStream.ChooseSkeletons(CurrentTrackingId);
}
}
}
return skeleton;
}
#endregion Event Handlers
}
}
However, I'm getting errors from VS2012 about:
1) No overload for 'FramesReady' matches delegate 'System.EventHandler'
2) 'sensor' not existing (most likely due to it not being imported, but from what I've tried, passing the sensor across methods causes more errors)
If anyone can help with this, or even point me in the right direction towards solving this, that would be great! To reiterate, the main goal is to have the Kinect lock onto the first person it finds, and maintain that lock with multiple people moving around in the line of sight.