我需要开发一个应用程序,用户(物理治疗师)将在 Kinect 前执行运动,我将在数据库中写入数据运动,然后患者将尝试模仿这个运动。系统将计算记录和执行的动作之间的相似度。
我的第一个想法是,在记录期间(例如每 5 秒),存储点的位置(x,y,z),然后在执行时间(按患者)比较它们。
我知道这种方法太简单了,因为我想象在不同体型的人中,对骨骼的识别是不同的,所以比较是不可靠的。
我的问题是关于将保存的动作与执行的动作(在运行中)进行比较的最佳方法。
我已经这样做了,将医生框架投影到患者框架上,但是对于整个骨骼,由于骨骼高度不同,因此效果不佳:/。代码可以在这里找到。它是 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 提到的骨骼高度,我已经放弃了整体图的想法,所以我当前的程序看起来像这样:
编辑
这是用 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 执行此操作。否则它将无法正常工作。希望这可以帮助。
首先要记住,人是不同的。每个人都有不同的身高、宽度、体重、不同的骨骼长度等
你的代码可能永远不会因为这个而工作。
其次,你需要更多地考虑几何。不要只考虑点,要考虑向量,它们的方向。每个运动都是一些向量在某些方向上的运动。然后是比例。您需要为每个用户配置应用程序。
你有一些模式。模式是你的物理治疗师。你不仅要记住他的动作,还要记住他的身体。臂长、腿长、距离等。将使用您的应用程序的每个用户也需要我测量。拥有所有这些数据,您可以通过缩放大小和比较运动方向来比较运动
当然请记住,有一些非常简单的动作,例如。通过检查手的实际位置和检查运动的方向,可以通过简单的数学来识别它们。您需要这 3 个控制点并且您在家 :)
手势识别不是一件简单的事