与Kinect比较保存的动作和其他动作

10

我需要开发一个应用程序,用户(物理治疗师)将在Kinect前面进行动作,我将把该动作数据写入数据库,然后患者将尝试模仿这个动作。系统会计算记录的动作和执行的动作之间的相似度。

我的第一个想法是在记录时(例如每5秒),存储点的位置(x、y、z),然后在执行时间(由患者执行时)进行比较。

我知道这种方法过于简单,因为我想象中不同大小的人的骨架被识别的方式也不同,所以比较结果不可靠。

我的问题是如何最好地比较保存的动作和执行时的动作。


一个朋友建议我“规范化”物理治疗师和患者的大小,但我认为这不是一个好主意。 - Ewerton
抱歉,该内容无法翻译。 - Liam McInroy
我只是使用椭圆并将它们映射到画布上,然后使用算法乘以它们的位置:whereItIs * (whereYouWantItToBe / whereItIs) - Liam McInroy
Outlaw Lemur,你能详细解释一下吗? - Ewerton
如果你还需要帮助,只需问就可以了。 - Liam McInroy
请在Kinect开发聊天室与我会面。 - Liam McInroy
2个回答

7
我已经完成了这个任务,将医生的框架投影到患者的框架上,但是整体骨架不太适用,因为不同的骨头高度:/。 代码可以在这里找到。 它是beta 2代码,更多更新版本可以在这里找到,但目前还不能完美运行

至于比较,请像这样操作

for (int i = 0; i < patientList.Count; i++)
{
    int diff = (int)Math.Abs(patientList[i] - doctorList[i]);

    if (diff < 100) //or whatever number you want
    {
         Debug.WriteLine("Good Job");
    }
}

由于Fixus提到的骨高度问题,我放弃了整体人物的想法,所以我的当前程序看起来像这样:

image

编辑

这是使用Kinect比较两个动作并计算它们之间相似度的概念,我会深入解释。

假设我有以下2个点,点A(0, 0, 0)和点B(1, 1, 1)。现在我想找出从点A到B的差异,所以我将减去所有X、Y和Z数字,因此差异为1 X 1 Y 1 Z。那是简单的东西。现在来实施它。我写的代码,会像这样实现。

//get patient hand coordinates
double patienthandX = Canvas.GetLeft(patienthand);
double patienthandY = Canvas.GetTop(patienthand);

//get doctor hand coordinates
double doctorhandX = Canvas.GetLeft(doctorhand);
double doctorhandY = Canvas.GetTop(doctorhand);

//compare difference for each x and y
//take Absolute value so that it is positive
double diffhandX = Math.Abs(patienthandX - doctorhandX);
double diffhandY = Math.Abs(patienthandY - doctorhandY);

现在又出现了另一个问题。医生的协调点始终是相同的,但如果病人不站在记录医生协调点的位置怎么办?我们现在使用更简单的数学方法。拿这个简单的例子来说,假设我想让A点(8,2)移动到B点(4,12)。你需要将点A的x和y乘以一个系数才能得到B点。所以我会将X乘以0.5,Y乘以6。对于Kinect来说,我会在病人臀部放置一个元素,然后将其与医生的臀部进行比较。接下来将医生所有关节乘以此系数,以实现医生关节覆盖在病人上方(或者更多)。例如:

double whatToMultiplyX = (double) doctorhipX / patienthipX;
double whatToMultiplyY = (double) doctorhipY / patienthipY;

这一切都相当简单,但把它们结合起来是更难的部分。到目前为止,我们已经完成了以下步骤:1)将医生框架缩放至患者框架之上;2)计算两者之间的差异;3)比较整个重复过程中的差异;4)为下一个重复过程进行重置。看似简单,但实际上并非如此。要计算整个重复过程的差异,请按照以下方式操作:

//get patient hand coordinates
double patienthandX = Canvas.GetLeft(patienthand);
double patienthandY = Canvas.GetTop(patienthand);

//get doctor hand coordinates
double doctorhandX = Canvas.GetLeft(doctorhand);
double doctorhandY = Canvas.GetTop(doctorhand);

//compare difference for each x and y
//take Absolute value so that it is positive
double diffhandX = Math.Abs(patienthandX - doctorhandX);
double diffhandY = Math.Abs(patienthandY - doctrorhandY);

//+= so that it keeps adding to it.
totaldiffhandX += diffhandX;
totaldiffhandY += diffhandY;

现在我们可以进行比较,并说:
if (totaldiffhandX < 1000 && totaldiffhandY < 1000) //keep numbers pretty high since it is an entire rep
{
     //reset difference
     totaldiffhandX = 0;
     totaldiffhandY = 0;

     //tell the patient good job
     Debug.WriteLine("Good Job");
}

这很简单,但请记住您必须为每个关节的x和y都执行此操作。否则它将无法正常工作。希望能帮到您。

4
首先要记住,每个人都是不同的。每个人的身高、宽度、体重、骨骼长度等都不同,因此您的代码可能永远无法正常工作。
其次,您需要更加注重几何学思考。不只是考虑点,而是考虑向量及其方向。每个动作都是某些向量在某些方向上的运动。然后是比例。您需要为每个用户配置应用程序。
您有一些模式。该模式是您的物理治疗师。您需要记住他的动作,还要记住他的身体。手臂长度、腿长、距离等等。使用您的应用程序的每个用户也需要进行测量。有了所有这些数据,您可以通过缩放大小和比较移动方向来比较运动。
当然,记住有一些非常简单的动作,例如。可以通过检查手的实际位置并检查运动方向,通过简单的数学来识别它们。您需要三个控制点,就能成功啦 :)
手势识别并不是一件简单的事情。

有趣的是,在理论领域它是可行的,但是我即将实现代码,我需要一些具体的指导。 :) - Ewerton
1
@Ewerton 别误解我的意思,但这是大量编码和实现数学,所以不要指望我会为你写好它。你需要明白,识别手势(当你想要识别高级动作,如全身运动)并不是一件简单的事情,而且需要艰苦的努力。如果你需要理论或者对于你无法运行的代码的帮助,请随时问我。记住,如果你想做正确,这不是一个一天能完成的工作。 - Fixus
@Fixus 真的,到目前为止我已经在这个项目上投入了大约250个小时。 - Liam McInroy
我同意,并且我不需要代码,这是我的工作,我对它感到兴奋,我会完成它。当我说具体时,我指的是像这样的东西:“是的,伙计,在我的上一个项目中,我已经实现了这个目标,我使用了以下策略:啦啦啦。 :)” - Ewerton
-1 只是描述问题及其非常一般的解决方法,但并没有深入探讨。 - Liam McInroy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接