从坐标列表中提取运动数据

Posted

技术标签:

【中文标题】从坐标列表中提取运动数据【英文标题】:Extracting motion data from a list of coordinates 【发布时间】:2011-08-30 06:59:15 【问题描述】:

我有一系列带时间戳的坐标(X、Y 和 Z,单位为毫米)的 CSV 文件。从中提取运动数据的最简单方法是什么?

可衡量的

我想提取的信息包括:

    换向次数 第一个和最后一个动作的初始加速度 ...以及这些运动的方位(角度) 非静止时的平均速度

理想情况下,我最终希望能够对运动模式进行分类,因此任何可以提出这样做​​的方法的人都会获得奖励积分。让我感到震惊的是,我可以做到这一点的一种方法是从坐标生成运动的图片/视频,并要求人类对其进行分类 - 关于我如何做到这一点的建议非常受欢迎。

噪音

一个复杂的事实是读数被噪音污染。为了克服这一点,每个录音都以至少 20 秒的静止作为开头,这可以作为一种“噪声配置文件”。不过我不确定如何实现。

细节

如果有帮助,记录的动作是人手在简单抓取任务中的动作。数据是使用附在手腕上的磁性运动跟踪器生成的。另外,我使用的是 C#,但我猜数学与语言无关。

编辑

磁跟踪器规格:http://www.ascension-tech.com/realtime/RTminiBIRD500_800.php 样本数据文件:http://tdwright.co.uk/sample.csv

赏金

对于赏金,我真的很想看看一些(伪)代码示例。

【问题讨论】:

您想获取每个轴的运动信息吗? 啊,对不起。正如你回复的那样,我删除了我以前的 cmets。 别担心,您的改写很有用。想一想,我只真正关心 XY 平面中的运动 - 原点上方/下方的高度不太有趣。 好的。您想分别检测 x 轴和 y 轴的运动变化吗?或者,您想检测直线运动的推导(即同时考虑 x 轴和 y 轴) 根据我对录音的观察,似乎同时考虑两者会更好:通常方向变化非常微妙。 【参考方案1】:

让我们看看可以用您的示例数据做什么。

免责声明:我没有阅读您的硬件规格 (tl;dr :))

为方便起见,我将在 Mathematica 中解决这个问题。相关算法(不多)将作为链接提供。

第一个观察结果是您的所有测量在时间上都是等距的,这对于简化方法和算法最方便。我们将在方便时表示“时间”或“滴答”(测量值),因为它们是等价的。

让我们先按轴绘制你的位置,看看问题出在哪里:

(* This is Mathematica code, don't mind, I am posting this only for 
   future reference *)
ListPlot[Transpose@(Take[p1[[All, 2 ;; 4]]][[1 ;;]]), 
 PlotRange -> All,
 AxesLabel -> Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]]

现在,有两个观察结果:

您的移动开始于第 1000 点左右 您的移动不是从 0,0,0 开始

因此,我们将稍微转换您的数据,减去零位置并从第 950 点开始。

ListLinePlot[
 Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), , 950], 
 PlotRange -> All,
 AxesLabel -> Style["Ticks", Medium, Bold], 
               Style["Position (X,Y,Z)", Medium, Bold]]

由于曲线有足够的噪声破坏计算,我们将其与Gaussian Kernel 进行卷积以对其进行去噪:

kern = Table[Exp[-n^2/100]/Sqrt[2. Pi], n, -10, 10];
t = Take[p1[[All, 1]]];
x = Take[p1[[All, 2 ;; 4]]];

x1 = ListConvolve[kern, #] & /@ 
   Drop[Transpose@(x - Array[Mean@(x[[1 ;; 1000]]) &, Length@x]), , 
    950];

所以你可以在下面看到原始和平滑的轨迹:

现在我们已经准备好对速度和加速度进行导数了。我们将使用fourth order approximants 作为一阶和二阶导数。我们还将像以前一样使用高斯核对它们进行平滑:

Vel = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] + x1[[axis, i - 2]] - 
         8 x1[[axis, i - 1]] + 
         8 x1[[axis, i + 1]])/(12 (t[[i + 1]] - t[[i]])), axis, 1, 3], 
    i, 3, Length[x1[[1]]] - 2];

Acc = ListConvolve[kern, #] & /@ 
   Transpose@
    Table[Table[(-x1[[axis, i + 2]] - x1[[axis, i - 2]] + 
         16 x1[[axis, i - 1]] + 16 x1[[axis, i + 1]] - 
         30 x1[[axis, i]])/(12 (t[[i + 1]] - t[[i]])^2), axis, 1,  3], 
   i, 3, Length[x1[[1]]] - 2];

我们绘制它们:

Show[ListLinePlot[Vel,PlotRange->All,
     AxesLabel->Style["Ticks",Medium,Bold],
                 Style["Velocity (X,Y,Z)",Medium,Bold]],
    ListPlot[Vel,PlotRange->All]]

Show[ListLinePlot[Acc,PlotRange->All,
     AxesLabel->Style["Ticks",Medium,Bold],
                 Style["Acceleation (X,Y,Z)",Medium,Bold]],
     ListPlot[Acc,PlotRange->All]]

现在,我们还有速度和加速度模数:

ListLinePlot[Norm /@ (Transpose@Vel), 
 AxesLabel -> Style["Ticks", Medium, Bold], 
               Style["Speed Module", Medium, Bold], 
 Filling -> Axis]
ListLinePlot[Norm /@ (Transpose@Acc), 
 AxesLabel -> Style["Ticks", Medium, Bold], 
               Style["Acceleration Module", Medium, Bold],
 Filling -> Axis]       

以及Heading,作为Velocity的方向:

Show[Graphics3D[
 Line@(Normalize/@(Transpose@Vel)),
 Opacity[.7],Sphere[0,0,0,.7],
 Epilog->Inset[Framed[Style["Heading",20],
        Background->LightYellow],Right,Bottom,Right,Bottom]]]

我认为这足以让您入门。如果您在计算特定参数时需要帮助,请告诉我。

HTH!

编辑

举个例子,假设您想计算手不静止时的平均速度。因此,我们选择所有速度大于截止点的点,例如 5,并计算平均值:

Mean@Select[Norm /@ (Transpose@Vel), # > 5 &]
-> 148.085

那个量级的单位取决于你的时间单位,但我没有看到它们在任何地方指定。

请注意,截止速度不是“直观的”。您可以通过绘制平均速度与截止速度来搜索合适的值:

ListLinePlot[
 Table[Mean@Select[Norm /@ (Transpose@Vel), # > h &], h, 1, 30], 
 AxesLabel -> Style["Cutoff Speed", Medium, Bold], 
               Style["Mean Speed", Medium, Bold]]

所以你看到 5 是一个合适的值。

【讨论】:

很好的答案,但你已经成功地引起了一些严重的 Mathematica 嫉妒!打算尝试为 C# 找到一个好的高斯核算法... @Tom 高斯过滤器是一个不错的过滤器,但也许其他过滤器也可以。不要被它困住。 我认为贝利撒留真的应该得到赏金! @gpu_drug 我完全同意。谢谢@belisarius! @Tom 感谢您的赏金。如果您需要进一步说明,请告诉我【参考方案2】:

e 解决方案可以像状态机一样简单,其中每个状态代表一个方向。运动序列由方向序列表示。这种方法只有在传感器的方向不随运动改变时才有效,否则在计算方向序列之前,您需要一种将运动转换为正确方向的方法。

另一方面,您可以使用各种 AI 技术,尽管您会使用的具体方法超出了我的范围。

获取任意两个坐标之间的速度:

               _________________________________
Avg Speed =   /(x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2
            --------------------------------------
                 (t2-t1)

要获得整个运动的平均速度,假设您有 100 个带时间戳的坐标,请使用上述等式计算 99 个速度值。然后将所有速度相加,然后除以速度数 (99)

要获得加速度,需要三个时刻的位置,或者两个时刻的速度。

Accel X = (x3 - 2*x + x1) / (t3 - t2)
Accel Y = (y3 - 2*y + y1) / (t3 - t2)
Accel Z = (z3 - 2*z + z1) / (t3 - t2)

【讨论】:

速度总是标量。速度是一个向量。 规范是一个冗长而枯燥的文档——你想要什么信息?如果有帮助,我会上传一个示例数据文件。 如果起点和终点相同,您的平均速度(可以进一步推广到包括 z 坐标)将不起作用。它可以应用于每一步(坐标对),但这仍然不能解释不运动的时刻。【参考方案3】:

注意:这一切都假设每轴计算:我没有两轴粒子运动的经验。

如果您首先将位置测量值转换为速度测量值,您会更轻松地完成此操作。

第一步:去除噪音。正如你所说,每段录音都以 20 秒的静止开始。因此,要找到实际测量值,请搜索位置不变的 20 秒间隔。然后,直接进行测量。

第二步:计算速度使用:(x2 - x1)/(t2 - t1);斜率公式。间隔应与录音的间隔相匹配。

计算:

方向变化:

方向改变发生在加速度为零的地方。使用数值积分来查找这些时间。从 0 开始积分,直到积分结果为零。记录这一次。然后,从上一次积分直到再次归零。重复直到到达数据的末尾。

初始加速度:

再次使用斜率公式找到这些,将v 替换为x

平均速度:

平均速度公式是斜率公式。 x1 和 t1 应该对应第一个读数,x2 和 t2 应该对应最终读数。

【讨论】:

就像我说的,这不适用于二维运动。希望比我更擅长数学的人可以将其应用于二维运动:)

以上是关于从坐标列表中提取运动数据的主要内容,如果未能解决你的问题,请参考以下文章

逐步简化 (x,y) 坐标列表中的直线运动

从通用视频编码中提取运动矢量

从 H.264 比特流中提取运动矢量 [关闭]

来自前景提取的物体运动检测(grabcut)

我有时空运动数据。我将如何计算坐标之间的速度? (使用 R)

将实时数据从运动捕捉系统写入 CSV 文件?