Leap Motion 教你玩转手势

本文分享了使用Leap Motion SDK进行手势识别的实际经验,包括如何通过调整阈值提高手势识别精度,解决手势与具体手指关联的问题,并介绍了关键的手势识别参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


        刚尝试手势的时候我差点选择放弃,现在想想还是自己不好好看SDK,小心使得万年船啊。

        废话不多说,直接贴代码,这段代码实现的是在画圈停止后输出一个Gesture通知,代码很顺利,结果很粗糙。由于手部肌肉连带,食指动的时候必然中指也动,加上Leap“超凡的精确度”,导致动了右手食指,出来四胞胎结果——拇指,食指,中指,无名指。


[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public override void OnFrame(Controller arg0)  
  2.         {  
  3.             Frame frame = arg0.Frame();  
  4.             GestureList gestures = frame.Gestures();  
  5.             for (int i = 0; i < gestures.Count; i++)  
  6.             {  
  7.                 Gesture gesture = gestures[i];  
  8.   
  9.                 switch (gesture.Type)  
  10.                 {  
  11.                     case Gesture.GestureType.TYPE_CIRCLE:  
  12.                         CircleGesture circle = new CircleGesture(gesture);  
  13.   
  14.                         // Calculate clock direction using the angle between circle normal and pointable  
  15.                         String clockwiseness;  
  16.                         if (circle.Pointable.Direction.AngleTo(circle.Normal) <= Math.PI / 2)  
  17.                         {  
  18.                             //Clockwise if angle is less than 90 degrees  
  19.                             clockwiseness = "clockwise";  
  20.                         }  
  21.                         else  
  22.                         {  
  23.                             clockwiseness = "counterclockwise";  
  24.                         }  
  25.   
  26.                         float sweptAngle = 0;  
  27.   
  28.                         // Calculate angle swept since last frame  
  29.                         if (circle.State != Gesture.GestureState.STATE_START)  
  30.                         {  
  31.                             CircleGesture previousUpdate = new CircleGesture(arg0.Frame(1).Gesture(circle.Id));  
  32.                             sweptAngle = (circle.Progress - previousUpdate.Progress) * 360;  
  33.                         }  
  34.   
  35.                         if(circle.State==Gesture.GestureState.STATE_STOP)  
  36.                             Console.WriteLine("  Circle id: " + circle.Id  
  37.                                             + ", " + circle.State  
  38.                                             + ", progress: " + circle.Progress  
  39.                                             + ", radius: " + circle.Radius  
  40.                                             + ", angle: " + sweptAngle  
  41.                                             + ", " + clockwiseness);  
  42.                         break;  
  43.                 }  
  44.                       
  45.             }  
  46.         }  


        修改过一个小东西后,手势明显变得好用了,就是阈值。图上是检测Key_Tap时候的反馈数据,由于设定了min_distance,即最小移动检测阈值,反馈良好,基本不会出现误操作的问题。由此可见好好看SDK是多么重要啊!阈值参数表如下:

画圈手势
Gesture.Circle.MinRadius float5mm
Gesture.Circle.MinArc float1.5 * piradians
按键手势
Gesture.KeyTap.MinDownVelocity float50mm/s
Gesture.KeyTap.HistorySeconds float0.1s
Gesture.KeyTap.MinDistance float3mm
横扫手势
Gesture.Swipe.MinLength float150mm
Gesture.Swipe.MinVelocity float1000mm/s
触摸手势
Gesture.ScreenTap.MinForwardVelocity float50mm/s
Gesture.ScreenTap.HistorySeconds float0.1s
Gesture.ScreenTap.MinDistance float5mm


       第一项为名称,第二项是数据类型(都是float),第三项是默认阈值大小,第四项是单位,csdn的表格有点不方便,然而对于一个写程序刚入门的,还去用dreamwaver编个表格粘到源码里,太麻烦,大家就这么一看,我就这么一画吧。修改阈值的方式也很简单:这里用Circle手势作为参考,修改了最小半径和最小角速度,然后记得保存。

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. controller.Config.SetFloat ("Gesture.Circle.MinRadius", 10.0f);  
  2. controller.Config.SetFloat ("Gesture.Circle.MinArc", .5f);  
  3. controller.Config.Save ();  

       那么问题又来了,手势是对了,怎么知道是哪根指头操作的呢,不能玩第二根半价(权值选择不读)的游戏啊,肯定得想办法把所有指头都用上。想了两个办法,第一个操作一个Hand循环,采样手指名称,比如finger.type等于“TYPE_INDEX”是食指,是需要的的指头操作,测试发现问题了,因为是foreach fingers,所以只要手指头被检测到,就会被刷出来,第一种方案胎死腹中。第二个方案比较原始,即判断激发点和手指的位置是不是重合,但是由于Finger中并没有postion参数,只好想其他办法,不过下期一定贴代码!

      另外,细心的朋友发现程序失焦后会不工作,这是Leap的一种保护机制,然而这种保护机制我给零分,明明应该是默认读取数据,我可以选择关闭,现在是默认关闭我可以选择打开,好吧,我服,其实就是加了一句话:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Controller.SetPolicy(Controller.PolicyFlag.POLICY_BACKGROUND_FRAMES);  

       这样子程序就可以后台继续数据了,回来路上我还纳闷这个问题呢,心想不应该,实在不行创建个新进程单独走,然而SDK再一次告诉我想多了,好好看SDK,东西全在里面,写不出都是自己的问题。现在节奏快,巴不得什么东西都不学,一口吃成个大胖子,唉,急不得啊。

       如果有朋友有finger和gesture匹配的解决方案,记得留言!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值