我正在尝试使用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)这样的数字?
答案 0 :(得分:4)
我在您的代码中看到shoulderCenter
,因此您可能正在使用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
方法,并仅在跟踪所有关节时估算高度。
对于使用SDK v2的开发人员,请注意,在SDK v1.x中未定义骨架关节。下图显示了这种差异:
由于某些关节的位置和定义不同,上述评估高度的算法应编辑如下:
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