使用Kinect测量人的身高

时间:2015-05-26 15:09:04

标签: c# kinect euclidean-distance

我正在尝试使用Kinect计算一个人的身高。以下是我计算高度的方法(此代码不是非常复杂,仅用于测试目的):

double h2s =  Math.Sqrt(Math.Pow(headX - shoulderCenterX, 2) + Math.Pow(headY - shoulderCenterY, 2)+ Math.Pow(headZ - shoulderCenterZ, 2));
double s2hip =  Math.Sqrt(Math.Pow(shoulderCenterX - hipX, 2) + Math.Pow(shoulderCenterY - hipY, 2) + Math.Pow(shoulderCenterZ - hipZ, 2));
double hip2Lhip =  Math.Sqrt(Math.Pow(hipX - hipLeftX, 2) + Math.Pow(hipY - hipLeftY, 2) + Math.Pow(hipZ - hipLeftZ, 2));
double Lhip2kneeL =  Math.Sqrt(Math.Pow(hipLeftX - kneeLeftX, 2) + Math.Pow(hipLeftY - kneeLeftY, 2) + Math.Pow(hipLeftZ - kneeLeftZ, 2));
double kneeL2ankle = Math.Sqrt(Math.Pow(kneeLeftX - ankleLeftX, 2) + Math.Pow(kneeLeftY - ankleLeftY, 2) + Math.Pow(kneeLeftZ - ankleLeftZ, 2));

double heigth = h2s + s2hip + hip2Lhip + Lhip2kneeL + kneeL2ankle;

vyskatextbox.Text = heigth.ToString();

我没有得到任何错误,但事实是它正在计算我的身高错误。我的数字在3到11之间,取决于我与Kinect的距离。可能有什么不对?数字是否可以改变,或者无论如何都保持不变?另外,为什么我得到像11(m)这样的数字?

2 个答案:

答案 0 :(得分:4)

我在您的代码中看到shoulderCenter,因此您可能正在使用Microsoft Kinect SDK v1.x.在这种情况下,骨骼关节是以下几种:

Kinect SDK v1.x Skeletal Joints

Microsoft Kinect SDK v1.x中的高度估计

假设我们有一个可以计算两个关节之间距离的函数。我们将此函数命名为d(joint1, joint2)

还假设我们已经定义了一个可以计算两个关节之间平均点的函数(注意以下只是伪代码):

function avg(joint1, joint2) {
    avg_joint.x = (joint1.x + joint2.x) / 2.0;
    avg_joint.y = (joint1.y + joint2.y) / 2.0;
    avg_joint.z = (joint1.z + joint2.z) / 2.0;
    return avg_joint;
}

估算用户身高的一个好算法可以是以下一个(注意它只是一个伪代码):

torso_height = d(HEAD, SHOULDER_CENTER) +
               d(SHOULDER_CENTER, SPINE) +
               d(SPINE, HIP_CENTER) +
               d(HIP_CENTER, avg(HIP_RIGHT, HIP_LEFT));

left_leg_height = d(HIP_LEFT, KNEE_LEFT) +
                  d(KNEE_LEFT, ANKLE_LEFT) +
                  d(ANKLE_LEFT, FOOT_LEFT);

right_leg_height = d(HIP_RIGHT, KNEE_RIGHT) +
                   d(KNEE_RIGHT, ANKLE_RIGHT) +
                   d(ANKLE_RIGHT, FOOT_RIGHT);

tot_height = torso_height +
             (left_leg_height + right_leg_height) / 2.0;

如果所有关节都得到良好跟踪,此算法运行良好。但是,某些关节推断是可能的(并且实际上经常发生)。在this page from the documentation on MSDN中,您可以看到如何测试是否在C#中推断出关节。

如果推断出一个关节,那么它的位置错误的可能性就会增加。因此,高度估计失败的可能性也会增加。

以下方法可用于测试是否跟踪了所有关节。如果没有很好地跟踪至少一个关节,则返回false;否则返回true

function areJointsWellTracked(JointCollection joints)
{
    foreach (Joint joint in joints)
        if(joint.TrackingState != JointTrackingState.Tracked)
            return false;

    return true;
}

因此,如果能够很好地跟踪所有关节,那么改善用户身高估计的方法就是计算它。

此外,考虑始终提供最后一个高度值的平均值的可能性。例如,您可以记住数组中的最后十个高度值,然后每次提供这些值的平均值。这有助于减少措施中噪音的影响。

您的问题

您的代码似乎是我刚才描述的算法的简化版本。因此,您可以获得这些奇怪值的唯一原因是跟踪效果不佳。我的建议是尝试使用前面提到的areJointsWellTracked方法,并仅在跟踪所有关节时估算高度。

Microsoft Kinect SDK v2

的附加说明

对于使用SDK v2的开发人员,请注意,在SDK v1.x中未定义骨架关节。下图显示了这种差异:

Kinect SDK v2 Skeletal Joints

由于某些关节的位置和定义不同,上述评估高度的算法应编辑如下:

torso_height = d(HEAD, NECK)+
               d(NECK, SPINE_SHOULDER) +
               d(SPINE_SHOULDER, SPINE_MID) +
               d(SPINE_MID, SPINE_BASE) +
               d(SPINE_BASE, avg(HIP_RIGHT, HIP_LEFT));

left_leg_height = d(HIP_LEFT, KNEE_LEFT) +
                  d(KNEE_LEFT, ANKLE_LEFT) +
                  d(ANKLE_LEFT, FOOT_LEFT);

right_leg_height = d(HIP_RIGHT, KNEE_RIGHT) +
                   d(KNEE_RIGHT, ANKLE_RIGHT) +
                   d(ANKLE_RIGHT, FOOT_RIGHT);

tot_height = torso_height +
             (left_leg_height + right_leg_height) / 2.0;

您可以在this link使用Microsoft Kinect SDK v2找到有关如何评估用户身高的有趣讨论。

答案 1 :(得分:1)

这个链接对我有帮助。
Find user height accurately