Question

Par exemple, je suis debout en face de mon Kinect. Le Kinect peut identifier les articulations, et il les expose comme une structure de données. Jusqu'à ce point, je suis clair.

Alors, peut-on définir la hauteur comme la différence entre coresponsable - ((+ LeftAnkle RightAnkle) / 2)

J'ai essayé des formules trigonométriques, mais il y a deux problèmes que je fais face. L'un est d'identifier la personne dans la vue. La seconde consiste à identifier la position exacte du sommet de la tête et le bas du pied.

J'ai essayé le nuage de points, mais se sont perdus dans la façon de générer le spécifique nuage de points à une personne. Je veux dire sans inclure les objets d'arrière-plan.

S'il vous plaît suggérer quelques idées sur la façon dont je peux calculer la hauteur d'une personne utilisant le Kinect?

Était-ce utile?

La solution

You can convert the Head Joint into global coordinate system. There is no need to do any math. The y coordinate in global coordinate will be his height.

All you need to do is check what pixel the head joint is and convert the pixel + depth informations into word coordinate space in mm.

I don't know what API you are using, but if it's being capable to segment a human and return his joint's, probably you are using OpenNI/NITE or Microsoft SDK. Both of them have a function that converts a pixel + depth coordinate into a x,y,z in mm. I don't know exactly what are the functions but their names would be something like : depth_to_mm, or disparity_to_mm. You need to check both documentations to find it, or you can do it by yourself. This site have informations on how to convert depth to mm: http://nicolas.burrus.name/index.php/Research/KinectCalibration

Autres conseils

I have extracted the two points - Head and Left foot (or Right Foot), then i found the euclidean distance between these points gave the distance with 4 inch variation. My test results are satisfactory, so we are using this approach as temporary work around.

An old question but i found a very nice explanation and example here. It also explains that height isnt mearly a function of the head and ankle points, but instead a function 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 formula for Kinect SDK 2.0. Full project available at https://github.com/jhealy/kinect2/tree/master/020-FaceNSkin_HowTallAmI ....

using System;
using Microsoft.Kinect;

// Skeleton is now Bones
public enum BodyHeightMeasurementSystem
{
    Meters = 0, Imperial = 1
}

public static class BodyHeightExtension
{
// change this to change the way values are returned, by default everything is meters
public static BodyHeightMeasurementSystem MeasurementSystem = BodyHeightMeasurementSystem.Meters;

/// <summary>
/// Get Height of a body in CM
/// </summary>
/// <param name="TargetBody">used for extension method purposes - uses should not see</param>
/// <returns>
/// positive value: height in meters
/// -1.0 : null body passed in
/// -2.0 : body not tracked, no height available
/// </returns>
public static double Height( this Body TargetBody )
{
    if ( TargetBody == null ) return -1.0;
    if (TargetBody.IsTracked == false) return -2.0;

    const double HEAD_DIVERGENCE = 0.1;

    Joint _head = TargetBody.Joints[JointType.Head];
    Joint _neck = TargetBody.Joints[JointType.Neck];

    // var spine = skeleton.Joints[JointType.Spine]; // ?
    Joint _spine = TargetBody.Joints[JointType.SpineShoulder];
    // var waist = skeleton.Joints[JointType.HipCenter];  // ?
    // jeh: spinemid is ignored
    Joint _waist = TargetBody.Joints[JointType.SpineBase];
    Joint _hipLeft = TargetBody.Joints[JointType.HipLeft];
    Joint _hipRight = TargetBody.Joints[JointType.HipRight];
    Joint _kneeLeft = TargetBody.Joints[JointType.KneeLeft];
    Joint _kneeRight = TargetBody.Joints[JointType.KneeRight];
    Joint _ankleLeft = TargetBody.Joints[JointType.AnkleLeft];
    Joint _ankleRight = TargetBody.Joints[JointType.AnkleRight];
    Joint _footLeft = TargetBody.Joints[JointType.FootLeft];
    Joint _footRight = TargetBody.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);

    // default is meters.  adjust if imperial to feet
    double _retval = Length(_head, _neck, _spine, _waist) + legLength + HEAD_DIVERGENCE;
    if (MeasurementSystem == BodyHeightMeasurementSystem.Imperial) _retval = MetricHelpers.MetersToFeet(_retval);

    return _retval;
}

/// <summary>
/// Returns the upper height of the specified skeleton (head to waist). Useful whenever Kinect provides a way to track seated users.
/// </summary>
/// <param name="skeleton">The specified user skeleton.</param>
/// <returns>The upper height of the skeleton in meters.</returns>
public static double UpperHeight( this Body TargetBody )
{
    Joint _head = TargetBody.Joints[JointType.Head];
    // used to be ShoulderCenter. Think its SpineMid now
    Joint _neck = TargetBody.Joints[JointType.SpineMid];
    // .Spine is now .SpineShoulder
    Joint _spine = TargetBody.Joints[JointType.SpineShoulder];
    // HipCenter is now SpineBase
    Joint _waist = TargetBody.Joints[JointType.SpineBase];

    return Length(_head, _neck, _spine, _waist);
}

/// <summary>
/// Returns the length of the segment defined by the specified joints.
/// </summary>
/// <param name="p1">The first joint (start of the segment).</param>
/// <param name="p2">The second joint (end of the segment).</param>
/// <returns>The length of the segment in meters.</returns>
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));
}

/// <summary>
/// Returns the length of the segments defined by the specified joints.
/// </summary>
/// <param name="joints">A collection of two or more joints.</param>
/// <returns>The length of all the segments in meters.</returns>
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;
}

/// <summary>
/// Given a collection of joints, calculates the number of the joints that are tracked accurately.
/// </summary>
/// <param name="joints">A collection of joints.</param>
/// <returns>The number of the accurately tracked joints.</returns>
public static int NumberOfTrackedJoints(params Joint[] joints)
{
    int trackedJoints = 0;
    foreach (var joint in joints)
    {
        // if (joint.TrackingState == JointTrackingState.Tracked)
        if ( joint.TrackingState== TrackingState.Tracked )
        {
            trackedJoints++;
        }
    }
    return trackedJoints;
}

/// <summary>
/// Scales the specified joint according to the specified dimensions.
/// </summary>
/// <param name="joint">The joint to scale.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
/// <param name="MaxX">Maximum X.</param>
/// <param name="MaxY">Maximum Y.</param>
/// <returns>The scaled version of the joint.</returns>
public static Joint ScaleTo(Joint joint, int width, int height, float MaxX, float MaxY)
{
    // SkeletonPoint position = new SkeletonPoint()
    Microsoft.Kinect.CameraSpacePoint position = new Microsoft.Kinect.CameraSpacePoint()
    {
        X = Scale(width, MaxX, joint.Position.X),
        Y = Scale(height, MaxY, -joint.Position.Y),
        Z = joint.Position.Z
    };
    joint.Position = position;
    return joint;
}

/// <summary>
/// Scales the specified joint according to the specified dimensions.
/// </summary>
/// <param name="joint">The joint to scale.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
/// <returns>The scaled version of the joint.</returns>
public static Joint ScaleTo(Joint joint, int width, int height)
{
    return ScaleTo(joint, width, height, 1.0f, 1.0f);
}

/// <summary>
/// Returns the scaled value of the specified position.
/// </summary>
/// <param name="maxPixel">Width or height.</param>
/// <param name="maxBody">Border (X or Y).</param>
/// <param name="position">Original position (X or Y).</param>
/// <returns>The scaled value of the specified position.</returns>
private static float Scale(int maxPixel, float maxBody, float position)
{
    float value = ((((maxPixel / maxBody ) / 2) * position) + (maxPixel / 2));

    if (value > maxPixel)
    {
        return maxPixel;
    }

    if (value < 0)
    {
        return 0;
    }

    return value;
}

}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top