Unity3D中使用Leap Motion进行手势控制

时间:2023-02-21 13:47:05

Leap Motion作为一款手势识别设备,相比于Kniect,长处在于准确度。

在我的毕业设计《场景漫游器》的开发中。Leap Motion的手势控制作为重要的一个环节。以此,谈谈开发中使用Leap Motion进行手势识别的实现方式以及须要注意的地方。

一、对Leap Motion的能力进行评估

在设定手势之前。我们必须知道Leap Motion能做到哪种程度,以免在设定方案之后发现非常难实现。

这个评估依靠实际对设备的使用体验。主要从三个方面:

1.Leap Motion提供的可视化的手势识别界面

2.SDK文档说明

3.Leap商店中的APP

基本能够的得出:

1.Leap Motion的识别对于水平方向或者以水平方向为基础手势可以较好的识别。

2.对于握拳或者垂直的行为识别会出现误差。这样的误差和详细的手势行为有关。

3.不应该过分依赖高准确度,Leap Motion能检測到毫米级别是没错的,可是有时候会把你伸直的手指识别成弯曲的。所以要做好最坏的打算。

二、实际的须要

移动、旋转、点击button、缩放和旋转物体、关闭程序、暂停,主要的功能需求是这样。

有一些原则:

1.同样环境下的手势应该接近和方便的转换。旋转和移动的之间的转换应该设计的非常自然。

2.手势避免冲突,手势过于相似不是什么好事。

比方三个伸直的手指和四个伸直的手指不应该被设计成两个手势。当然这不是绝对的。假设你进行一个缓慢的动作而且动作是面向Leap Motion的摄像头,这时候应该相信它。至少要针对这个手势做一个单独的測试。

三、考虑主要的数据结构和算法的轮廓

Leap Motion的SDK在第一部分的时候已经浏览过。最起码能知道Leap Motion能够包括的信息。从SDK看来这是非常丰富的,既然设计自己的手势,那么最好不要依赖于SKD开发包的炫酷的手势。非常可能,这些手势仅仅是官方用来演示或者炫耀的。自己设计手势的基本数据结构也有另外的优点,比方更换了体感设备,可是功能是相似的。这时候仅仅须要更改获取数据的方式就能够了(从一个SDK更换到还有一个SDK),而不要改动算法。

算法的轮廓与基本数据有非常大的关系。所以数据结构一定要尽量的精简而且同意改动(可能某个算法占领了决定性因素,可是開始没考虑到)。

public class HandAndFingersPoint : MonoBehaviour
{
const int BUFFER_MAX=5;
Controller m_LeapCtrl; <span style="white-space:pre"> </span>public E_HandInAboveView m_AboveView = E_HandInAboveView.None; //手指-数据 ,[0]表示左手,[1]表示右手
private Dictionary<Finger.FingerType,FingerData>[] m_FingerDatas = new Dictionary<Finger.FingerType, FingerData>[2];
//buffer,[0]表示左手,[1]表示右手,[,n](n属于0,3。表示第n次缓存)
private Dictionary<Finger.FingerType,FingerData>[,] m_FingerDatasBuffer=new Dictionary<Finger.FingerType, FingerData>[2,BUFFER_MAX];
private int m_CurBufIndex=0;
//palm 0:左手 和1:右手
private PointData[] m_PalmDatas = new PointData[2]; private readonly PointData m_DefaultPointData = new PointData(Vector.Zero, Vector.Zero);
private readonly FingerData m_DefaultFingerData = new FingerData(Vector.Zero,Vector.Zero,Vector.Zero);

HandAndFingersPoint类中剩下的部分是对数据的填充、清除、刷新等方法。E_HandInAboveView记录哪仅仅手先进入Leap Motion的视野。用于设定优先级。

另外两个主要的数据结构PointData和FingerData:

//一个手指的数据包括一个指尖点数据和手指根骨的位置数据
public struct FingerData
{
public PointData m_Point;//指尖的位置和指向
public Vector m_Position;//手指根骨的位置,对于拇指来说是Proximal phalanges近端指骨的位置 public FingerData(PointData pointData, Vector pos)
{
m_Point = pointData;
m_Position = pos;
} public FingerData(Vector pointPos, Vector pointDir, Vector pos)
{
m_Point.m_Position = pointPos;
m_Point.m_Direction = pointDir;
m_Position = pos;
} public void Set(FingerData fd)
{
m_Point = fd.m_Point;
m_Position = fd.m_Position;
}
}
//一个点的数据,包括方向和位置
public struct PointData
{
public Vector m_Position;//位置
public Vector m_Direction;//方向 public PointData(Vector pos,Vector dir)
{
m_Position = pos;
m_Direction = dir;
} public void Set(PointData pd)
{
m_Position = pd.m_Position;
m_Direction = pd.m_Direction;
} public void Set(Vector pos,Vector dir)
{
m_Position = pos;
m_Direction = dir;
}
} //先被看到的手
public enum E_HandInAboveView
{
None,
Left,
Right
}

基本数据定义好之后,最好确认数据的填充是没问题的。实际通过Frame frame = Leap.Controller.Frame();来获取最新的数据。

这时候并不急着写完和基本数据相关的方法。如今终于要的是手势算法的合理性。要推断是否合理,最好先写一个算法。

最简单的是伸掌手势,在控制中水平的伸掌用于漫游,垂直的伸掌用于暂停。我发现手掌依赖于手指,而手指包含两个状态——伸直和弯曲。

另外,其它的手势,也都是手指的伸直或者弯曲,外加方向的判定累积出各种效果。理所当然的,应该单独写出手指的弯曲和伸直判定算法:

/// <summary>
/// 该方法提供对于单个手指匹配的算法,如伸直。弯曲
/// 以后可能的改变:对于不同的场景可能要求有所不同。这里的阈值或许会随之改变
/// </summary>
public class FingerMatch
{
//弯曲状态的角度阈值
static readonly float FingerBendState_Radian = Mathf.PI*4f / 18 ;//40度
//伸直状态的角度阈值
static readonly float FingerStrightState_Radian = Mathf.PI/12;//15度 /// <summary>
/// 手指伸直的状态,当根骨-指尖的方向和指向的偏差小于阀值时,判定手指为伸直状态。
/// 注意无效的方向为零向量。先判定是零向量
/// </summary>
/// <param name="adjustBorder">对阈值做的微调</param>
/// <returns></returns>
public static bool StrightState(FingerData fingerData, float adjustBorder=0f)
{
bool isStright =false;
Vector disalDir = fingerData.m_Point.m_Direction;
//假设指尖方向为0向量,表示无效的数据
if (!disalDir.Equals(Vector.Zero))
{
Vector fingerDir = fingerData.m_Point.m_Position - fingerData.m_Position;//指尖位置减去指根位置,由指根指向指尖的向量
float radian = fingerDir.AngleTo(disalDir); if (radian < FingerStrightState_Radian + adjustBorder)
{
isStright = true;
}
}
return isStright;
} /// <summary>
/// 推断一根手指是否处于弯曲状态
/// </summary>
/// <param name="fingerData">须要判定的手指数据</param>
/// <param name="bandBorder">弯曲的阈值</param>
/// <returns></returns>
public static bool BendState(FingerData fingerData, float adjustBorder=0f)//,out float eulerAugle)
{
bool isBend = false; //eulerAugle = -1f;
Vector disalDir = fingerData.m_Point.m_Direction;
if( !disalDir.Equals(Vector.Zero) )
{
Vector fingerDir = fingerData.m_Point.m_Position - fingerData.m_Position;//指尖位置减去指根位置,指跟到指尖的向量 float radian = fingerDir.AngleTo(disalDir);
//eulerAugle = radian*180/Mathf.PI;
//夹角超过定义的阈值时,认定为弯曲状态
if (radian > FingerBendState_Radian + adjustBorder)
{
isBend = true;
}
} return isBend;
} }

上面包括了一个重要的概念——阈值。它是描写叙述究竟何种程度算是伸直,何种程度算是弯曲。阈值的确定是须要实际測试来决定的。

写到这里也是时候进行一次简单的測试了,毕竟算法的轮廓已经确定。我甚至没写出手掌伸直的判定算法。就确定是可行的。

基本数据结构相关的操作——HandAndFingersPoint类:源码GitHub链接

该类使用基本数据。在Unity Editor中执行会展示了一个手掌的轮廓,蓝色表示手指的方向。红色表示手指骨根到掌心和指尖的连线,黄色表示掌心到指尖的连线:

Unity3D中使用Leap Motion进行手势控制

四、手势实现中简要的概括

其它代码都能够在我的GitHub:Leap Motion In Unity3D仓库中获取。在手势的实现中,也包括了一些小的技巧。比方对于动作的匹配要防止手指的颤抖引起的误差。採用离散的数据取样——每隔一定时间做一次取样。

使用和观察这些脚本的方式:能够把这些脚本放在一个GameObject中。通过Leap Motion会看到脚本的属性在匹配成功时会发生变化。另外,脚本中包括了事件的注冊功能,换句话说。外部能够向随意的手势注冊一个事件,以便手势完毕匹配或者到达某种匹配状态时做一些额外的处理。这些脚本如今并不能直接完毕我们的需求,如暂停。我们须要在这些手势状态或者动作上做进一步的限定,如依据掌心的方向设定垂直向前的手掌为暂停,水平的手掌为平移之类的。

Unity3D中使用Leap Motion进行手势控制的更多相关文章

  1. 如何在Unity中开发Leap Motion桌面版(Non-VR)APP

    最近因需要,翻出几年前的Leapmotion感测器,准备用Unity3D做个互动APP,于是连上官网下载SDK.等下载下来一安装调试,瞬间傻眼,居然要求VR设备.我们Lab倒是不缺VR,有几套VIVE ...

  2. 基于unity3d和leap motion的拼图游戏

    近期用unity3d引擎做了一个拼图游戏,会分几次写完,以此作为总结. 本文基本查找了网上能查到的全部资料作为參考.也算是大家节省了时间. 眼下仅仅完毕了拼图部分,leap motion手势控制部分会 ...

  3. Leap Motion颠覆操控体验的超精致手势追踪技术【转】

    转自:http://www.cnblogs.com/emouse/archive/2013/02/28/2936689.html 先来看两段简介视频: 看了介绍视频后,对如此次超高精度的手势追踪非常好 ...

  4. Leap Motion发布新平台&comma;直击下一代移动端VR&sol;AR手部追踪

    2013年,动作捕捉技术公司Leap Motion发布了面向PC的体感控制器,不过销量并不乐观.随着2014年虚拟现实技术的再一次兴起,它发布一款用于Oculus Rift的附加设备,从而正式登上VR ...

  5. (转)在Unity3D中控制动画播放

    用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西.这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问 ...

  6. leap motion

    体感控制器: 识别:手,手指和工具,获取位置,手势,动作 范围:倒金字塔,塔尖在设备中心,2.5cm~0.6米 坐标系统:采用右手笛卡尔积坐标系,返回的数值:毫米 摆放:绿灯朝向自己,z轴距离屏幕越来 ...

  7. 十大最佳Leap Motion体感控制器应用

    十大最佳Leap Motion体感控制器应用   Leap Motion Controller也许还没有准备好大规模的发售,但是毫无疑问,这款小巧的动作捕捉器是我们见过的最酷的设备之一.这款设备的硬件 ...

  8. Leap Motion 开发笔记

    Leap Motion 体系架构 Leap Motion支持所有主流操作系统,leap motion在Windows系统下是作为一个服务运行的,在Mac和Linux是后台守护进程.软件通过USB线连接 ...

  9. Leap Motion 上手体验

    很早之前就关注了Leap Motion这个颠覆性的体感操作设备,如今7月22日上市至今已经一个月左右,淘宝的价格也已经降到650元,虽说相对国外还是偏贵,但是已经忍不住尝尝鲜了. Leap Motio ...

随机推荐

  1. hihoCoder&num;1082

    刚开始学习C语言,准备在做hiho的题目的过程中来学习,在此进行记录,如果代码中有错误或者不当的地方还请指正. 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 fjxmlh ...

  2. WPF 自定义Metro Style窗体

    为了使WPF程序在不同版本的操作系统上保持一致的显示效果,我们需要重写WPF控件样式.这篇博客将展示如何创建一个Metro Style的WPF窗体. 首先先看一下最终窗体的效果图, 通过截图我们可以看 ...

  3. HBM内存介绍

    原帖地址:http://www.anandtech.com/show/9969/jedec-publishes-hbm2-specification The high-bandwidth memory ...

  4. postfix

    http://www.postfix.org/ All programmers are optimists -- Frederick P. *s, Jr. 所有程序员都是乐天派

  5. 用Cookie记住上次登录用户名

    一个登录页面设置查看Cookie中的数据(Cookie不为null);然后将页面提交到另一个页面去,在这个页面中的到是否选择记住用户名,如果选择了, 就创建Cookie对象,将用户名存储起来,下次登录 ...

  6. fullPage&period;js插件用法(转发)

    fullPage.js主要功能有: 支持鼠标滚动 支持前进后退和键盘控制 多个回调函数 支持手机.平板触摸事件 支持 CSS3 动画 支持窗口缩放 窗口缩放时自动调整 可设置滚动宽度.背景颜色.滚动速 ...

  7. 侧滑面板(对viewGroup的自定义)

    额,好吧,最近一直在做侧滑的事情,到目前为止一共是学了三种方法了,一个是直接加第三方开源框架SlidingMenu,第二给是用DrawerLayout,今天这个是用谷歌官方提供的在新的support- ...

  8. Linux中常用来查看进程的命令PS

    查看所有运行中的进程:ps aux | less 显示所有进程: ps -A / ps -e 显示进程的树状图:pstree

  9. 魔力Python--经典SQL语法大全

    具体转载自哪里,我也忘记了... 一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明: ...

  10. make、makefile、cmake、qmake对比

    作者:玟清链接:https://www.zhihu.com/question/27455963/answer/36722992来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...