使用 Kinect 的物体高度

发布于 2024-12-19 01:51:54 字数 285 浏览 1 评论 0 原文

例如,我站在 Kinect 前面。 Kinect 可以识别关节,并将它们作为数据结构公开。到现在为止我已经很清楚了。

那么,我们是否可以将高度定义为头关节 - ((LeftAnkle + RightAnkle)/2) 之间的差值?

我尝试过三角公式,但我面临两个问题。一是识别视图中的人。第二个是确定头顶和脚底的确切位置。

我尝试过点云,但迷失在如何生成特定于人的点云上。我的意思是不包括背景物体。

请提出一些关于如何使用 Kinect 计算人的身高的想法?

For example, I am standing in-front of my Kinect. The Kinect can identify the joints, and it will expose them as a data structure. Till this point I am clear.

So, can we define the height as the difference between Head joint - ((LeftAnkle + RightAnkle)/2)?

I have tried trigonometric formulas, but there are two problems I am facing. One is identifying the person in the view. The second one is identifying the exact positions of Top of head and bottom of foot.

I have tried the point cloud, but got lost in how to generate the point cloud specific to a person. I mean without including the background objects.

Please suggest some ideas about how I can calculate the height of a person using the Kinect?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏有森光若流苏 2024-12-26 01:51:54

您可以将头部关节转换为全局坐标系。无需做任何数学计算。全局坐标中的y坐标将是他的高度。

您所需要做的就是检查头部关节是什么像素,并将像素+深度信息转换为以mm为单位的单词坐标空间。

我不知道你使用的是什么 API,但如果它能够分割人类并返回他的关节,那么你可能正在使用 OpenNI/NITE 或 Microsoft SDK。它们都有一个将像素+深度坐标转换为以mm为单位的ax,y,z的函数。我不确切知道这些函数是什么,但它们的名称类似于:深度_到_毫米或视差_到_毫米。您需要检查两个文档才能找到它,或者您可以自己完成。
此站点提供有关如何将深度转换为毫米的信息:http://nicolas.burrus.name /index.php/Research/KinectCalibration

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

还给你自由 2024-12-26 01:51:54

我提取了两个点 - 头和左脚(或右脚),然后我发现这些点之间的欧几里德距离给出了 4 英寸变化的距离。我的测试结果令人满意,因此我们使用此方法作为临时解决方法。

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.

倾城月光淡如水﹏ 2024-12-26 01:51:54

一个老问题,但我找到了一个非常好的解释和示例此处
它还解释了高度不仅仅是头部和脚踝点的函数,而是以下线段的函数:

  • Head - ShoulderCenter
  • ShoulderCenter - Spine
  • Spine - HipCenter
  • HipCenter - KneeLeft 或 KneeRight
  • KneeLeft / KneeRight - AnkleLeft /
    右脚踝
  • 左脚踝/右脚踝 - 左脚/右脚

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
葮薆情 2024-12-26 01:51:54

以下是 Kinect SDK 2.0 的公式。完整项目位于 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;
}

}

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;
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文