Outlaw Lemur described in detail most of the problems that you may encounter in real-world scenarios.
Using Kinect for Windows version 2, you do not need to configure the engine, since there is no engine, and the sensor has more field of view. It will make your life easier.
I would like to add the following tips and tricks:
1) Avoid direct light (physical or internal lighting)
Kinect has an infrared sensor that can be confusing. This sensor should not be in direct contact with any light sources. You can emulate such an environment in your home / office by playing with a regular laser pointer and torches.
2) If you are tracking only one person, select the closest tracked user
If your application needs only one player, that player must be a) fully tracked and b) closer to the sensor than the others. This is an easy way to get participants to understand who is being tracked without making your interface more complex.
public static Body Default(this IEnumerable<Body> bodies) { Body result = null; double closestBodyDistance = double.MaxValue; foreach (var body in bodies) { if (body.IsTracked) { var position = body.Joints[JointType.SpineBase].Position; var distance = position.Length(); if (result == null || distance < closestBodyDistance) { result = body; closestBodyDistance = distance; } } } return result; }
3) Use tracking identifiers to distinguish between different players
Each player has a TrackingID property. Use this property when players intervene or move in random positions. Do not use this property as an alternative to face recognition.
ulong _trackinfID1 = 0; ulong _trackingID2 = 0; void BodyReader_FrameArrived(object sender, BodyFrameArrivedEventArgs e) { using (var frame = e.FrameReference.AcquireFrame()) { if (frame != null) { frame.GetAndRefreshBodyData(_bodies); var bodies = _bodies.Where(b => b.IsTracked).ToList(); if (bodies != null && bodies.Count >= 2 && _trackinfID1 == 0 && _trackingID2 == 0) { _trackinfID1 = bodies[0].TrackingId; _trackingID2 = bodies[1].TrackingId;
4) Display alerts when the player is too far away or too close to the sensor.
To achieve greater accuracy, players need to stand at a certain distance: not too far or too close to the sensor. Here's how to check it out:
const double MIN_DISTANCE = 1.0; // in meters const double MAX_DISTANCE = 4.0; // in meters double distance = body.Joints[JointType.SpineBase].Position.Z; // in meters, too if (distance > MAX_DISTANCE) { // Prompt the player to move closer. } else if (distance < MIN_DISTANCE) { // Prompt the player to move farther. } else { // Player is in the right distance. }
5) Always know when a player has entered or left the scene.
Vitruvius provides an easy way to understand when someone has entered or left the stage.
Here is the source code , and here is how to use it in your application:
UsersController userReporter = new UsersController(); userReporter.BodyEntered += UserReporter_BodyEntered; userReporter.BodyLeft += UserReporter_BodyLeft; userReporter.Start(); void UserReporter_BodyEntered(object sender, UsersControllerEventArgs e) {
6) Have a visual clue about which player is being tracked
If there are a lot of people around the player, you may need to show on the screen who is being tracked. You can select a depth frame bitmap or use Microsoft Kinect Interactions.
This is an example of removing the background and saving the player’s pixels .
7) Avoid glossy floors
Some floors (bright, glossy) can reflect people, and Kinect can confuse some of their joints (for example, Kinect can stretch its legs to a reflected body). If you cannot avoid glossy floors, use the FloorClipPlane property of your BodyFrame. However, the best solution would be to have a simple rug where you expect people to stand. The carpet will also act as an indicator of the correct distance, so you will provide a better user interface.