关注Leap Motion很长时间了,很早就想入手。可是,一方面,一直忙着其它的比赛,没时间顾及;二是缺钱,钱都垫在比赛上了。

好不容易,11月18日,下定决心买进了,这么长时间,也就是再给贵阳职业学院的学生上课的时候显摆了一次。

周末休息,总算是强迫自己摆弄一下Leap Motion了。

那么做点什么呢?不放就先从简单的开始吧,就在窗口上显示一个红色的圆,以表示追踪到的某一个手指头(指尖)。

要开发Leap Motion应用,我觉得官方的文档必须要仔细的看看。

文档1:开发者首页,这里可以下载SDK。

文档2:理解C#例程,以便开发我们自己的应用程序。

文档3:Leap概述,获取开发的必要知识。

Step1:下载SDK,并解压缩。在“LeapSDK”中有我们需要用的源代码和类库。

Step2:创建一个C# WPF应用程序,不妨就叫“LeapMotion1_WPF”。

Step3:在项目中添加“lib/LeapCSharp.NET4.0.dll”引用(如果是.net framework 3.5的话,则添加LeapCSharp.NET3.5.dll),如图。

Step4:在项目中添加现有项,“lib/x86/Leap.dll”、“lib/x86/Leap.lib”和“lib/x86/LeapCSharp.dll”三个文件,并设置三个文件“始终复制”到输出目录,如图。

Step5:创建用户界面,在MainWindow上,放一个Canvas,两个Button,一个Ellipse,如图。

设置好相应的属性。Canvas的大小和窗口一样。

Step6:编写“连接设备”按钮的单击事件。在该事件中,我们需要让Leap Motion工作起来。不放看看“samples/Sample.cs”中是如何实现的。

该类实现的是一个控制台应用程序。我们从main开始看。代码如下:

     public static void Main ()
{
// Create a sample listener and controller
SampleListener listener = new SampleListener ();
Controller controller = new Controller (); // Have the sample listener receive events from the controller
controller.AddListener (listener); // Keep this process running until Enter is pressed
Console.WriteLine ("Press Enter to quit...");
Console.ReadLine (); // Remove the sample listener when done
controller.RemoveListener (listener);
controller.Dispose ();
}

文档2中说,“The Controller class provides the main interface between the Leap and your application. When you create a Controller object, it connects to the Leap software running on the computer and makes hand tracking data available through Frame objects. You can access these Frame objects by instantiating a Controller object and calling the Controller.Frame method”,即应用程序使用Controller对象来访问Leap硬件,追踪到的数据封装在Frame对象中的,这个对象可以通过Controller.Frame获取。

文档2中还说,“If your application has a natural update loop or frame rate, then you can call Controller.Frame as part of this update. Otherwise, you can add a listener to the controller object. The controller object invokes the callback methods defined in your Listener subclass whenever a new frame of tracking data is available (and also for a few other Leap events)”。如果开发的应用程序本身有个大循环的话(类似XNA应用程序的update,或是单片机程序的loop),可以在这个大循环中通过Controller.Frame获取Frame对象。否则,我们可以给Controller对象提供一个Listener,当Controller准备好新的Frame时会回调Listener,之后我们在进行处理。

这样来看,前三行代码就比较好理解了。

在我们的项目中,“连接设备”按钮的单击事件的代码如下:

         private void Button_Click_1(object sender, RoutedEventArgs e)
{
listener = new MyLeapListener();
controller = new Controller();
controller.AddListener(listener); btn1.IsEnabled = false;//btn1表示“连接设备”
btn2.IsEnabled = true;//btn2表示“断开设备”
}

Step7:“断开设备”的点击事件的代码自然也比较容易写出,代码如下:

         private void Button_Click_2(object sender, RoutedEventArgs e)
{
controller.RemoveListener(listener); btn1.IsEnabled = true;
btn2.IsEnabled = false;
}

Step8:仿照例程的Main方法,我们还需要销毁Controller对象。如下:

         private void Window_Closing_1(object sender, System.ComponentModel.CancelEventArgs e)
{
controller.Dispose();
}

Step9:实现自己的监听器。先来看看SampleListener是如何实现的呢?其骨架如下。

 class SampleListener : Listener
{
public override void OnInit (Controller controller)
{
} public override void OnConnect (Controller controller)
{
} public override void OnDisconnect (Controller controller)
{
} public override void OnExit (Controller controller)
{
} public override void OnFrame (Controller controller)
{
}
}

同样是在文档2中有详细的说明,我就不粘贴原文了。我们自己创建的监听器需要继承Listener,可以根据需要重写上面几个方法。对于我们而言,需要关注的是OnFrame方法,因为当一个新的Frame准备好后会调用这个方法。

在LeapMotion1_WPF命名空间中添加一个新类MyLeapListener,其实现如下:

     class MyLeapListener : Listener
{
public override void OnFrame(Controller ctl)
{
}
}

Ok,非常好。我们可以在OnFrame方法中获得Frame对象,然后获取关于指尖的数据,然后进行一些操作,就如例程中那样。但是,在这个方法中,我们是无法改变Ellipse的位置的。我们需要多做一步操作,在MyLeapListener的OnFrame方法触发的时候,通知调用者进行处理。显然,使用事件可以完美的解决我们的问题。于是,我们修改了MyLeapListener的代码:

     class MyLeapListener : Listener
{
public event EventHandler OnFrameEvent = null;
public override void OnFrame(Controller ctl)
{
if (OnFrameEvent != null)
{
OnFrameEvent.Invoke(ctl, null);
}
}
}

在OnFrame方法中触发OnFrameEvent事件。那么,相应的,在实例化MyLeapListener的时候,就应该加一个事件处理方法进去。在Button_Click_1方法中作如下修改:

         private void Button_Click_1(object sender, RoutedEventArgs e)
{
listener = new MyLeapListener();
listener.OnFrameEvent += listener_OnFrameEvent;

controller = new Controller();
controller.AddListener(listener); btn1.IsEnabled = false;
btn2.IsEnabled = true;
}

Step10:实现listener_OnFrameEvent方法。先把方法声明写出来。

         void listener_OnFrameEvent(object sender, EventArgs e)
{
}

按照之前的说法,追踪的数据是封装在Frame对象中的,因此,我们首先获取该对象。

             //获取帧数据
LeapFrame frame = controller.Frame();//using LeapFrame = Leap.Frame;

再往下就需要用到文档3的知识了。Leap可以同时检测到若干只手,并用Hand对象封装数据,建议最多2只手进入Leap的检测区域。需要注意的是Leap无法区分左右手。我们判断一下Leap是否检测到手,如果检测到的话,就获取第一个。

             //如果能够获取手部数据
if (!frame.Hands.IsEmpty)
{
//获取手部数据
Hand hand = frame.Hands[];
}

有了Hand对象,我们就能够知道手相对于Leap的位置。

                 //获取手部的位置,判断检测的范围
LeapVector palmPosition = hand.PalmPosition;//using LeapVetcor = Leap.Vector;
float palmHeight = palmPosition.y;

这里的高度为什么是y,不是z?文档3中有介绍的啊。Leap的坐标系如下图所示。

我们要在窗口中绘制Ellipse表示指尖在Leap检测区域中的位置,Leap检测的坐标是毫米,窗口绘制的时候是像素,这就涉及到了坐标的转换。

我曾看到一篇文章,其说Leap的检测角度为150度,因此,在不考虑z轴的情况下,我们可以计算出来手所在的高度检测的宽度是多少,并将指尖的位置映射到窗口上。文档3说明了有效的检测区域是设备上方25毫米-600毫米的范围,故可以将指尖的高度映射到窗口上。

                 float detectionWidth = (float)(palmHeight * Math.Tan(75.0 / 180.0 * Math.PI) * );

有了手的数据,我们接下来获取指尖的信息。Leap检测时,并不是每一帧都包括指尖的信息,例如当握拳时就无法得到指尖的数据。所以,在使用指尖数据时,我们需要判断一下。

                 //获取指尖的数据
FingerList fingers = hand.Fingers;
if (!fingers.IsEmpty)
{
Finger f1 = fingers[];
}

获取指尖的位置数据,并计算其在窗口上的位置。

                     LeapVector position = f1.TipPosition;

                     float x = position.x;
float y = position.y; //下面将x、y映射到屏幕上
double screenWidth = canvas1.ActualWidth;
double screenHeight = canvas1.ActualHeight; x = x / detectionWidth * screenWidth + (screenWidth / );
y = screenHeight - y / ( – ) * screenHeight;

最后,需要设置Ellipse的位置。

                     this.Dispatcher.BeginInvoke(new Action(delegate {
Canvas.SetLeft(ellipse, x);
Canvas.SetTop(ellipse, y);
}), null);

注意,不能直接调用Canvas.SetLeft会出错的。

好了,运行程序,看看效果吧。

注意:

1、using Leap;

2、注意代码的缩进。

LeapMotion(1):环境配置、简单测试、理解对象的更多相关文章

  1. YOLOv4 资源环境配置和测试样例效果

    YOLOv4 资源环境配置和测试样例效果 基本环境:cuda=10.0,cudnn>=7.0, opencv>=2.4 一.下载yolov4 git clone https://githu ...

  2. Python+Selenium笔记(一):环境配置+简单的例子

    #环境配置基于windows操作系统 #学习selenium要有一些HTML和xpth的基础,完全不会的建议先花点时间学点基础(不然元素定位,特别是xpth可能看的有点懵) #HTML :  http ...

  3. Tomcat环境配置部署测试环境及架构

    Tomcat环境配置已经在前面介绍过了,这边就为童鞋们介绍下对于Tomcat的架构是怎么样的! Tomcat的架构包含(bin.conf.lib.logs.temp.wenapps.work)等文件夹 ...

  4. nodejs安装、环境配置和测试

    nodejs下载 https://nodejs.org/en/ nodejs安装 双击下载的nodejs,可自定义安装路径,安装模块部分直接next即可安装. 检查是否安装 win+R输入cmd,打开 ...

  5. Windows10 + Visual Studio 2017 + CMake +OpenCV编译、开发环境配置及测试

    由于最近需要使用OpenCV,本人需要在自己的PC上使用OpenCV,因此最近一直在研究如何使用Visual Studio编译OpenCV源代码并搭建开发环境,折腾了很长时间,查阅了很多相关资料,终于 ...

  6. ionic+angularjs开发hybrid App(环境配置+创建测试项目)

    本文使用的系统是win10 因为后期需要使用nodejs 所以先把node装好 https://nodejs.org/download/ 下载JDK并配置Java运行环境 http://www.ora ...

  7. C连接MySQL数据库开发之Xcode环境配置及测试

    一.开发环境 Mac OS X 10.9.2 64位.Xcode5.1.MySQL5.5.37 64位 MySQL安装目录为:/usr/local/mysql 二.配置xcode连接mysql的编译选 ...

  8. C连接MySQL数据库开发之Windows环境配置及测试

    一.开发环境 Win8.1 64位.VS2013.MySQL5.5.3764位 MySQL安装目录为:C:\Program Files\MySQL\MySQL Server 5.5 二.配置工程环境 ...

  9. Eclipse Maven profiles 多环境配置,测试环境与开发环境分开打包

    1.将开发环境.测试环境.生产环境的配置文件分开存放,如下图: 2.在Maven中配置不同的环境打包配置文件的路径,配置如下: <profiles> <profile> < ...

  10. Java Jdk 环境配置和测试

    测试jdk:1.6 安装完jdk1.6以后,在我的电脑中找到环境变量配置 在系统变量的Path 中输入 ;E:\Program Files (x86)\Java\jdk1.6.0_01\bin(路径根 ...

随机推荐

  1. Ios入门

    storyboard 文件的认识 用来描述软件界面 默认情况下程序启动就会加载Main.storyboard 加载storyboard时,会首先创建和显示箭头所指向的控制器界面 什么是UIscroll ...

  2. 【AR】Vuforia App key is missing.Please get a valid key

    在跑Vuforia 的sample android app 的时候报了下面这个错,找了半天才找到解决方法: "Vuforia App key is missing. Please get a ...

  3. XE5 Android 开发数据访问手机端 解决乱码的办法

    经过测试,将sqlserver里的字段由varchar 或者char  改为  nvarchar 或者nchar 然后在手机端的clientdataset 增加字段的时候数据类型选择widestrin ...

  4. xe5 android tts(Text To Speech)

    xe5 android  tts(Text To Speech) TTS是Text To Speech的缩写,即“从文本到语音”,是人机对话的一部分,让机器能够说话. 以下代码实现xe5 开发的文本转 ...

  5. sql导出查询数据

    from sysobjects where name ='proc_exporttb' and xtype ='P') drop proc proc_exporttb go create proc p ...

  6. android app性能优化大汇总(google官方Android性能优化典范 - 第1季)

    大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能.从设计师的角度,他们希望App能够有更多的动画,图片等时尚元素来实现流畅的用户体验.但是Android系统很有可能无法及时完成那些复杂的界 ...

  7. VS2015环境下Crystal Reports(水晶报表)的安装使用

    1.首先下载Crystal Reports13对于Visual Studio 2015支持的2个文件. CRforVS_13_0_17 CRforVS_redist_install_64bit_13_ ...

  8. Cocos2d-x场景切换相关函数介绍

    场景切换是通过导演类Director实现的,其中的相关函数如下: runWithScene(Scene* scene).该函数可以运行场景.只能在启动第一个场景时候调用该函数.如果已经有一个场景运行情 ...

  9. Java中toArray的用法探究(java数组与list转换)

    转载原文地址: http://blog.csdn.net/guopengzhang/article/details/5497875 一.             Incident import jav ...

  10. 分享9款用HTML5/CSS3制作的动物人物动画

    1.纯CSS3绘制可爱的蚱蜢 还有眨眼动画 今天我们要分享一个利用纯CSS3绘制的蚱蜢动画,非常可爱. 在线演示 源码下载 2.HTML5 Canvas头发飘逸动画 很酷的HTML5动画 HTML5 ...