我目前正在使用Windows 8.1上的Microsoft Kinect for Windows SDK 2进行编程。事情进展顺利,在家庭开发环境中,与“现实世界”相比,背景显然没有太多噪音。
我想从那些拥有Kinect在“现实世界”应用程序方面经验的人那里寻求一些建议。Kinect(尤其是v2)在具有路人,旁观者和非预期对象的实时环境中的表现如何?我确实希望,从Kinect传感器到用户的空间通常不会产生干扰-我现在非常注意的是背景噪声。
虽然我知道Kinect在阳光直射下(无论是在传感器上还是在用户身上)都无法很好地跟踪-是否需要将某些光照条件或其他外部因素纳入代码中?
我正在寻找的答案是:
我像以前一样创建了一个家用应用程序,然后在公共场合展示了该应用程序。结果令我感到尴尬,因为在受控环境中,我将无法预料到很多错误。但这确实对我有所帮助,因为它使我对代码进行了一些有趣的调整,仅以人工检测为中心。
有条件检查“人”的有效性。
当我在演示厅的中间展示我的应用程序以及许多其他对象和道具时,我发现甚至椅子在短暂的时间内也可能被误认为是人,这导致我的应用程序在用户和无生命的对象之间切换。失去对用户的跟踪并失去他们的进度。为了对付这种或其他假阳性的人类检测结果,我添加了自己的针对人类的其他检查。我最成功的方法是比较人体的比例。我以主机为单位实现了这一目标。(主机图片)下面是我如何执行此操作的代码(SDK版本1.8,C#)
bool PersonDetected = false;
double[] humanRatios = { 1.0f, 4.0, 2.33, 3.0 };
/*Array indexes
* 0 - Head (shoulder to head)
* 1 - Leg length (foot to knee to hip)
* 2 - Width (shoulder to shoulder center to shoulder)
* 3 - Torso (hips to shoulder)
*/
....
double[] currentRatios = new double[4];
double headSize = Distance(skeletons[0].Joints[JointType.ShoulderCenter], skeletons[0].Joints[JointType.Head]);
currentRatios[0] = 1.0f;
currentRatios[1] = (Distance(skeletons[0].Joints[JointType.FootLeft], skeletons[0].Joints[JointType.KneeLeft]) + Distance(skeletons[0].Joints[JointType.KneeLeft], skeletons[0].Joints[JointType.HipLeft])) / headSize;
currentRatios[2] = (Distance(skeletons[0].Joints[JointType.ShoulderLeft], skeletons[0].Joints[JointType.ShoulderCenter]) + Distance(skeletons[0].Joints[JointType.ShoulderCenter], skeletons[0].Joints[JointType.ShoulderRight])) / headSize;
currentRatios[3] = Distance(skeletons[0].Joints[JointType.HipCenter], skeletons[0].Joints[JointType.ShoulderCenter]) / headSize;
int correctProportions = 0;
for (int i = 1; i < currentRatios.Length; i++)
{
diff = currentRatios[i] - humanRatios[i];
if (abs(diff) <= MaximumDiff)//I used .2 for my MaximumDiff
correctProportions++;
}
if (correctProportions >= 2)
PersonDetected = true;
我成功的另一种方法是找到关节距离之和的平均值。我发现非人类的检测距离总和变化较大,而人类则更一致。我使用一维支持向量机学习的平均值(我发现用户的总距离通常小于9)
//in AllFramesReady or SkeletalFrameReady
Skeleton data;
...
float lastPosX = 0; // trying to detect false-positives
float lastPosY = 0;
float lastPosZ = 0;
float diff = 0;
foreach (Joint joint in data.Joints)
{
//add the distance squared
diff += (joint.Position.X - lastPosX) * (joint.Position.X - lastPosX);
diff += (joint.Position.Y - lastPosY) * (joint.Position.Y - lastPosY);
diff += (joint.Position.Z - lastPosZ) * (joint.Position.Z - lastPosZ);
lastPosX = joint.Position.X;
lastPosY = joint.Position.Y;
lastPosZ = joint.Position.Z;
}
if (diff < 9)//this is what my svm learned
PersonDetected = true;
使用玩家ID和索引来记住谁是谁
这与上一个问题有关,如果Kinect将要跟踪的两个用户切换到其他用户,则由于数据的突然更改,我的应用程序将崩溃。为了解决这个问题,我将同时跟踪每个玩家的骨骼索引和他们的玩家ID。要了解有关如何执行此操作的更多信息,请参阅Kinect用户检测。
添加可调参数以适应各种情况
在我演示的地方,相同的倾斜角和其他基本Kinect参数(如近模)在新环境中不起作用。让用户能够调整其中一些参数,以便他们能够获得最佳的设置。
期望人们做愚蠢的事情
下次我演讲时,我可以调节倾斜角度,您可以猜测是否有人烧毁了Kinect的电机。任何可以在Kinect上破坏的东西,都会有人破坏。在文档中留下警告是不够的。您应该在Kinect的硬件上添加警告检查,以确保人们在无意间破坏某些东西时不会感到沮丧。这是一些代码,用于检查用户是否在两分钟内使用了20次以上的电机。
int motorAdjustments = 0;
DateTime firstAdjustment;
...
//in motor adjustment code
if (motorAdjustments == 0)
firstAdjustment = DateTime.Now;
++motorAdjustments;
if (motorAdjustments < 20)
{
//adjust the tilt
}
else
{
DateTime timeCheck = firstAdjustment;
if (DateTime.Now > timeCheck.AddMinutes(2))
{
//reset all variables
motorAdjustments = 1;
firstAdjustment = DateTime.Now;
//adjust the tilt
}
}
我会注意到,对于Kinect的第一个版本,所有这些对我来说都是问题,而我不知道在第二个版本中已经解决了多少个问题,因为我很遗憾还没有动手。但是,即使不是备份技术,我仍然会实施其中一些技术,因为会有例外,尤其是在计算机视觉方面。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句