基于离散点的手势检测算法

9
我正在尝试解决将人类生成的手势与已知手势进行匹配的问题。人类生成的手势将由一系列点表示,这些点需要被插值成路径并与现有路径进行比较。下面的图片展示了我要比较的内容: enter image description here 请帮忙提供资源或概念,帮助我构建一个算法来匹配这两条路径。由于我之前没有这方面的经验,因此任何见解都将不胜感激。

这些路径是如何存储的? - Trojan
最好的存储方式是什么?作为许多点的序列,还是作为函数,或者其他方式? - Atomix
3
请看这里。他有一个很酷的演示,包括代码和其他东西。 - Ebbe M. Pedersen
1个回答

6

接收输入

在某个时间间隔内测量输入。每隔 xx 毫秒,测量用户手指/笔的坐标。


存储模式和输入

模式(预期输入)

修改模式。目前它是一个连续的“函数”,但是以这样的方式测量输入是很困难的。使用某个时间间隔内的离散点。这个间隔可以非常短,取决于您需要多么精确地识别手势。实际上,它应该非常短;与更多点进行比较越多,结果会越好(我将在下一部分中更好地解释这个问题)。

输入(用户输入)

当测量输入时,输入测量间隔需要足够短,以便每个接收到的连续输入点对足够接近,可以与预期点进行比较。

想象一下,用户非常快地执行了某些手势(并在您的输入阅读器仅读取三帧的时间内完成)。模式和输入无法可靠地进行比较:

读者无法快速读取输入

为了避免这种情况,您的输入阅读器必须具有相对较短的间隔。然而,这可能并不是一个很大的问题,因为大多数硬件甚至可以读取最快的人类手势。

回到模式:它们应该始终足够详细,以包括任何可能的输入点。更多的预期点可以提高准确度。如果用户移动得很慢,则输入将具有更多的点;如果他们移动得很快,则输入将具有更少的点。

请考虑以下事项:完成单个手势会给您一半的输入帧,这些输入帧比模式中包含的点要少。用户以“正常”速度移动,因此,为了简化算法,您可以将模式“降级”一倍,然后直接将输入坐标与模式坐标进行比较。

这种方法比下一节中想到的替代方法更容易。


模式“密度”(坐标频率)

如果您只有少量的预期点,您将不得不做出一些近似值来匹配输入。

这是一个“极端”的示例,但它证明了这个概念。给定这个模式和输入:

输入点与模式点不匹配

点 3r 无法与点 2 或点 3 可靠比较,因此您必须使用点 2、3 和 3r 的一些函数来确定 3r 是否在正确的路径上。现在考虑相同的输入,但是模式的密度更高:

模式比输入更密集

现在,您不必妥协,因为 3r 实际上肯定在手势模式中。模式的轻微减少使其与输入很好地匹配。


定位

相对定位

与其在触摸屏等绝对位置上进行比较,您可能希望手势可以在某个平面的任何地方被允许。为此,您必须将输入的起始点与某个坐标系相关联。

将输入与坐标系相关联

规范化

为了使用户友好,允许手势在一定范围内完成。您不想比较原始数据,因为输入平面的大小很可能与模式平面的大小不匹配。

将输入在x和y方向上规范化以匹配您的模式的大小。不要保持宽高比。

  1. 按照上一个小标题所述,将输入与坐标系相关联
  2. 找到任意两个输入点之间的最大水平和垂直距离(称为RecMaxHRecMaxV
  3. 找到任意两个模式点之间的最大水平和垂直距离(称为ExpMaxHExpMaxV
  4. 将所有输入点的x坐标乘以ExpMaxH/RecMaxH
  5. 将所有输入点的y坐标乘以ExpMaxV/RecMaxV

将输入规范化以匹配模式大小

现在您有两组更相似的点,可以进行比较。规范化可以比这更详细;例如,您可以每次规范化3个点集以获得非常相似的图像(但您可能必须为每个模式执行此操作,然后将所有差异的总和进行比较以找到最可能的匹配模式)。

我建议将所有手势模式存储为相同大小的图形;这样在测量输入与可能的模式匹配的接近程度时可以减少计算量。


何时测量输入

用户驱动

想象一下一个按钮,在点击/激活时,导致程序开始测量输入。这类似于Google的语音搜索,它不会持续记录和搜索;相反,您说“好 Jarvis”或单击便捷的麦克风图标并开始说出您的查询。

优点:

  • 简化算法
  • 防止用户意外触发事件。想象一下,如果您说的每个单词都被分析并作为搜索查询的一部分发送到Google。有时您只是不想做任何事情。

缺点:

  • 用户体验较差。用户必须特意触发手势记录。
如果你正在编写一个手势搜索应用程序(荒谬的例子),那么这可能是更好的实现方法。没有人希望他们在应用程序中的每个动作都被解释为一个动作。然而,如果你正在编写一个基于Kinect或手势的游戏,你可能想要不断地记录和寻找手势。
常量:
你的程序会不断地在指定的时间间隔内记录手势坐标(这可以缩短为“如果有运动,则记录,否则不存储坐标”)。你必须做出决策:你将记录多少“帧”才能确定当前存储的运动不是一个已识别的手势?
在缓冲区中存储坐标:队列长度为最大帧数的1.5或2倍(为了谨慎起见)。
一旦确定在该缓冲区中存在与某个模式匹配的帧序列,就执行该手势的结果,并清除队列。
如果下一个手势可能是最近手势的“选项”,请将应用程序状态记录为“当前正在等待 ____ 手势的选项”,并等待选项出现。
如果确定缓冲区中前x帧无法匹配一个模式(由于它们的序列或位置),请将它们从队列中删除。
优点:
允许更动态地处理手势
自动识别用户输入
缺点:
更复杂的算法
更重的计算
如果你正在编写一个基于实时输入运行的游戏,这可能是正确的选择。
算法:
如果你正在使用用户驱动的识别:
记录在允许的时间范围内的所有输入(或直到用户表示他们完成)。
为了评估输入,将模式的密度减少到与输入相匹配。
将输入与坐标系相关联。
标准化输入。
使用函数比较方法(这个计算的宽松程度取决于你:标准差、方差、值的总差异等),选择最不同的可能性。
如果没有可能性足够相似以满足您所需的阈值(您必须决定这一点),则不接受该输入。
如果你正在使用常量测量:
在您的缓冲区中,将从每个帧倍数(由您决定)开始的 max_sequence_size(您决定)序列视为可能的手势。例如,如果我所有可能的手势长度最多为20帧,并且我相信每5帧可能会开始一个新手势(并且在这5帧中我不会失去任何关键数据),那么我会将缓冲区的每个部分与所有可能的手势进行比较(从0-19、5-24、10-29等部分)。当frame_multiples减小时,计算量会变得更重。对于完美的测量,frame_multiples为1(但这可能不合理)。
希望您喜欢阅读这个答案,就像我喜欢写它一样。我以前从未做过这件事,但您引起了我的兴趣,这种情况很少发生。编辑和改进我的答案!如果有某个部分似乎不完整,请添加内容。我非常好奇(特别是更有经验的)回应和批评。

你最后一段让我感到困惑。你的整个回答是猜测,还是你之前在这个领域做过工作? - stackoverflowuser2010
@stackoverflowuser2010 我在这个领域没有做过工作,所以我想你会认为这是推测。 - Trojan

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