The Hands On Labs to complete a sample application for Windows 8.1 and the Kinect 2 for Windows
Lab 14: Tracking StrategiesEstimated Time to Complete: 40min
This lab is part of a series which teach you how to build a Windows 8.1 Store Application which uses almost every available feature of the Kinect 2. This is the 14th and last lab in the series, and it explains some common and effective strategies for tracking users and players in your Kinect 2 applications.
This lab does not include much code, but instead offers insight into the design of applications with NUIs(Natural User Interfaces) such as you might create for a Kinect 2 solutions. This lab includes a discussion of the limitations and advantages of each tracking method.
This lab will explain the following:
Since the invention of physical buttons, interfaces have had one thing that gets taken for granted: Deliberation.
Pressing a physical button is a deliberate action because it is attached to something which is (hopefully) obviously an interface with some kind of feedback, and you know you are pressing it because you use your muscles to depress a button in a single direction. You must physically connect with the button so it's a fair assumption that the button getting pressed was a deliberate action.
Touch screens only require a touch, not a press. So they have had issues with non-deliberate touches in their own way, which is why standard gestures like swipe to confirm or double-tap have come into existence. There is less effort to interact with a touch screen (no force is required, only a fingertip or stylus touch is needed) so with less effort to interact, it's more likely to get a false interaction.
So we come to today and the rise of the Natural User Interface using body tracking, where your software has an option to record every movement of every joint, with no deliberation from the user. You must decide how to handle this in your application. There are no existing standards of interfaces or tracking methods using NUI, which is exciting for developers! You could be the one to create a new gesture which is so good and foolproof that it becomes a standard.
When you are designing your Kinect 2 app, you must ask yourself:
private int activeBodyIndex = -1; // Default to impossible value.
private void Reader_MultiSourceFrameArrived(
MultiSourceFrameReader sender,
MultiSourceFrameArrivedEventArgs e)
{
MultiSourceFrame multiSourceFrame = e.FrameReference.AcquireFrame();
// If the Frame has expired by the time we process this event, return.
if (multiSourceFrame == null)
{
return;
}
using (bodyFrame =
multiSourceFrame.BodyFrameReference.AcquireFrame())
{
Body[] bodiesArray =
new Body[this.kinectSensor.BodyFrameSource.BodyCount];
if (bodyFrame != null)
{
bodyFrame.GetAndRefreshBodyData(bodies);
// Check activeBodyIndex is still active
if (activeBodyIndex != -1)
{
Body body = bodiesArray[activeBodyIndex];
if (!body.IsTracked)
{
activeBodyIndex = -1;
}
}
// Get new activeBodyIndex if it's not currently tracked
if (activeBodyIndex == -1)
{
for (int i = 0; i < bodiesArray.Length; i++)
{
body = bodiesArray[i];
if (body.IsTracked)
{
activeBodyIndex = i;
// No need to continue loop
break;
}
}
}
// If active body is still active after checking and
// updating, use it
if (activeBodyIndex != -1)
{
Body body = bodiesArray[activeBodyIndex];
// Do stuff with known active body.
}
}
}
}
Pros:
private void Reader_MultiSourceFrameArrived(
MultiSourceFrameReader sender,
MultiSourceFrameArrivedEventArgs e)
{
MultiSourceFrame multiSourceFrame = e.FrameReference.AcquireFrame();
// If the Frame has expired by the time we process this event, return.
if (multiSourceFrame == null)
{
return;
}
using (bodyFrame =
multiSourceFrame.BodyFrameReference.AcquireFrame())
{
int activeBodyIndex = -1; // Default to impossible value.
Body[] bodiesArray = new Body[
this.kinectSensor.BodyFrameSource.BodyCount];
if (bodyFrame != null)
{
bodyFrame.GetAndRefreshBodyData(bodies);
// Iterate through all bodies,
// no point persisting activeBodyIndex because must
// compare with depth of all bodies so no gain in efficiency.
float minZPoint = float.MaxValue; // Default to impossible value
for (int i = 0; i < bodiesArray.Length; i++)
{
body = bodiesArray[i];
if (body.IsTracked)
{
float zMeters =
body.Joints[JointType.SpineBase].Position.Z;
if (zMeters < minZPoint)
{
minZPoint = zMeters;
activeBodyIndex = i;
}
}
}
// If active body is still active after checking and
// updating, use it
if (activeBodyIndex != -1)
{
Body body = bodiesArray[activeBodyIndex];
// Do stuff with known active body.
}
}
}
}
Pros:
Pros:
Developing interactions for Kinect 2 apps is very exciting because it's mostly uncharted territory. Your designs have freedom because the possibilities for interaction are any movement of any body, or joint, or even movements of in the face, and any combination of them!
The best strategy for tracking users in your own application will probably be a combination of those discussed here. You will definitely have to experiment heavily with interactions as you develop your own unique NUI.
The effort to get the interactions working well will pay off. Users become excited about new interfaces and using your body to interact with a machine without touching any physical device is a sci-fi dream. NUI's using the Kinect are hugely impressive when done right.