例如,我站在我的Kinect前面。 Kinect可以识别关节,并将它们作为数据结构公开。直到这一点我很清楚。
那么,我们可以将高度定义为头部关节 - ((LeftAnkle + RightAnkle)/ 2)之间的差异吗?
我尝试过三角公式,但我面临两个问题。一个是识别视图中的人。第二个是确定头顶和脚底的确切位置。
我尝试过点云,但是在如何生成特定于某人的点云方面却迷失了方向。我的意思是不包括背景对象。
请提出一些有关如何使用Kinect计算人物身高的建议?
答案 0 :(得分:4)
您可以将头部关节转换为全局坐标系。没有必要做任何数学运算。全局坐标中的y坐标将是他的身高。
您需要做的就是检查头部关节的像素,并将像素+深度信息转换为以mm为单位的字坐标空间。
我不知道你正在使用什么API,但是如果它能够分割人类并返回他的关节,那么你可能正在使用OpenNI / NITE或Microsoft SDK。它们都具有将像素+深度坐标转换为mm,y,z的函数。我不确切知道它们的功能是什么,但它们的名称类似于:depth_to_mm或disparity_to_mm。您需要检查两个文档才能找到它,或者您可以自己完成。 该网站提供了有关如何将深度转换为mm的信息:http://nicolas.burrus.name/index.php/Research/KinectCalibration
答案 1 :(得分:3)
我已经提取了两个点 - 头部和左脚(或右脚),然后我发现这些点之间的欧氏距离给出了4英寸变化的距离。我的测试结果令人满意,因此我们使用这种方法作为临时工作。
答案 2 :(得分:1)
一个老问题,但我找到了一个非常好的解释和例子here。 它还解释了身高不是头部和脚踝点的函数,而是以下线段的函数:
答案 3 :(得分:0)
以下是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;
}
}