Click here to Skip to main content
15,861,172 members
Articles / Desktop Programming / WPF
Tip/Trick

Kinect for Windows: Find User Height Accurately

Rate me:
Please Sign up or sign in to vote.
4.68/5 (21 votes)
23 Jan 2014CPOL2 min read 56K   23   13
Kinect for Windows - find user height accurately
View original article

Introduction

Some people ask me if there is a way to determine the height of a user standing in front of a Kinect device. The answer is definitely positive: We can detect the user's height regardless of her distance from the sensor! We only need some very basic math knowledge. Let's find out more...

Prerequisites

The algorithm of finding the user's height

Kinect provides you with the coordinates (X, Y and Z) of 20 skeleton joints. Someone might think that a person's height is the distance from the head joint to a foot joint, right? Wrong! Your users might stand in bended knees, they might lean a bit to the left or to the right. If you try to calculate the distance defined from the head joint to one of the foot joints, you'll get a far from accurate result.

Another point of interest is that Kinect gives you the center of the head joint. This means that you'll need to add 9 - 12 centimetres to the calculated height. You won't be able to calculate the total height with 100% accuracy. If you need more accuracy, you'll need to detect the end of the head using the depth stream. Not that difficult, but let's focus on the skeleton stream right now.

If you examine the human skeleton joints a little more carefully, you'll notice that the height is the sum of the lengths of the following line segments:

  • Head - ShoulderCenter
  • ShoulderCenter - Spine
  • Spine - HipCenter
  • HipCenter - KneeLeft or KneeRight
  • KneeLeft / KneeRight - AnkleLeft / AnkleRight
  • AnkleLeft / AnkleRight - FootLeft / FootRight

Here is a comprehensive picture illustrating the above segments:

First of all, we need to calculate the length of the line defined by two joints in the 3D space. This is quite easy Mathematics. Simply find the square root of the sum of squared differences of the coordinates:

C#
public static double Length(Joint p1, Joint p2)
{
    return Math.Sqrt(
        Math.Pow(p1.Position.X - p2.Position.X, 2) +
        Math.Pow(p1.Position.Y - p2.Position.Y, 2) +
        Math.Pow(p1.Position.Z - p2.Position.Z, 2));
}

And here is a way to find the length of more than two joints:

C#
public static double Length(params Joint[] joints)
{
    double length = 0;

    for (int index = 0; index < joints.Length - 1; index++)
    {
        length += Length(joints[index], joints[index + 1]);
    }


    return length;
}

Pretty straightforward till here. But, wait a second! How will you determine which leg corresponds to the most accurate user height? Since we suppose that both of the user's legs have the same length, we need to choose the one that is tracked better! This means that no joint position is hypothesized. Here is how to find out the number of tracked joints within a joint collection:

C#
public static int NumberOfTrackedJoints(params Joint[] joints)
{
    int trackedJoints = 0;

    foreach (var joint in joints)
    {
        if (joint.TrackingState == JointTrackingState.Tracked)
        {
            trackedJoints++;
        }
    }


    return trackedJoints;
}

We can now safely decide on which leg to use:

C#
int legLeftTrackedJoints = 
	NumberOfTrackedJoints(hipLeft, kneeLeft, ankleLeft, footLeft);
int legRightTrackedJoints = 
	NumberOfTrackedJoints(hipRight, kneeRight, ankleRight, footRight);

double legLength = legLeftTrackedJoints > legRightTrackedJoints ? Length(hipLeft, 
  kneeLeft, ankleLeft, footLeft) : Length(hipRight, kneeRight, ankleRight, footRight);

And here is the final method:

C#
public static double Height(this Skeleton skeleton)
{
    const double HEAD_DIVERGENCE = 0.1;

    var head = skeleton.Joints[JointType.Head];
    var neck = skeleton.Joints[JointType.ShoulderCenter];
    var spine = skeleton.Joints[JointType.Spine];
    var waist = skeleton.Joints[JointType.HipCenter];
    var hipLeft = skeleton.Joints[JointType.HipLeft];
    var hipRight = skeleton.Joints[JointType.HipRight];
    var kneeLeft = skeleton.Joints[JointType.KneeLeft];
    var kneeRight = skeleton.Joints[JointType.KneeRight];
    var ankleLeft = skeleton.Joints[JointType.AnkleLeft];
    var ankleRight = skeleton.Joints[JointType.AnkleRight];
    var footLeft = skeleton.Joints[JointType.FootLeft];
    var footRight = skeleton.Joints[JointType.FootRight];


    // Find which leg is tracked more accurately.
    int legLeftTrackedJoints = 
    NumberOfTrackedJoints(hipLeft, kneeLeft, ankleLeft, footLeft);
    int legRightTrackedJoints = 
    NumberOfTrackedJoints(hipRight, kneeRight, ankleRight, footRight);


    double legLength = legLeftTrackedJoints > legRightTrackedJoints ? 
      Length(hipLeft, kneeLeft, ankleLeft, 
      footLeft) : Length(hipRight, kneeRight, ankleRight, footRight);


    return Length(head, neck, spine, waist) + legLength + HEAD_DIVERGENCE;
}

Finally, you can use this extension method within a custom application easily:

C#
void Sensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
    using (var frame = e.OpenSkeletonFrame())
    {
        if (frame != null)
        {
            Skeleton[] skeletons = new Skeleton[frame.SkeletonArrayLength];
            frame.CopySkeletonDataTo(skeletons);

            var skeleton = skeletons.Where(s => s.TrackingState == 
                  SkeletonTrackingState.Tracked).FirstOrDefault();

            if (skeleton != null)
            {
                double height = skeleton.Height();
            }
        }
    }
}

You can now integrate this code to your own applications and find out the user's height! Consider downloading Vitruvius for the complete source code and examples.

Enjoy kinecting!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionIs there a way to offline skeleton acquisition? Pin
Member 1135296918-Nov-15 19:33
Member 1135296918-Nov-15 19:33 
QuestionAbout the accuracy of the height? Pin
Member 118811672-Aug-15 21:09
Member 118811672-Aug-15 21:09 
QuestionCan u help me if I want to write code to show X Y Z axis of every joints , when I use kinect ? Pin
Member 1140506717-Mar-15 1:10
Member 1140506717-Mar-15 1:10 
AnswerRe: Can u help me if I want to write code to show X Y Z axis of every joints , when I use kinect ? Pin
Vangos Pterneas17-Mar-15 3:11
professionalVangos Pterneas17-Mar-15 3:11 
QuestionCan you help me ,I have a problem during writing code for my project ? Pin
Member 1140506716-Mar-15 6:49
Member 1140506716-Mar-15 6:49 
AnswerRe: Can you help me ,I have a problem during writing code for my project ? Pin
Vangos Pterneas16-Mar-15 6:55
professionalVangos Pterneas16-Mar-15 6:55 
Questioncant download Pin
Member 1053961321-Jan-14 12:56
Member 1053961321-Jan-14 12:56 
AnswerRe: cant download Pin
Vangos Pterneas23-Jan-14 9:00
professionalVangos Pterneas23-Jan-14 9:00 
QuestionSource code link is dead? Pin
descartes8-Dec-13 23:58
descartes8-Dec-13 23:58 
AnswerRe: Source code link is dead? Pin
Vangos Pterneas10-Dec-13 10:11
professionalVangos Pterneas10-Dec-13 10:11 
GeneralRe: Source code link is dead? Pin
descartes10-Dec-13 10:41
descartes10-Dec-13 10:41 
GeneralMy vote of 3 Pin
codeprojectvien21-Sep-12 15:20
codeprojectvien21-Sep-12 15:20 
GeneralMy vote of 5 Pin
Sergio Andrés Gutiérrez Rojas10-May-12 19:13
Sergio Andrés Gutiérrez Rojas10-May-12 19:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.