使用Leap Motion SDK V2检测拳头

时间:2014-10-30 09:58:41

标签: javascript math leap-motion

我想检查闰动画帧中的手是否是当前的拳头。

通常建议的方法是查找值为{1}的hand.grabStrength。问题是,即使使用“爪状”手或其他任何手指略微卷曲的值,该值也会跳至1。

另一种方法是检查每个手指是否为extended。但是这有一个类似的问题,如果手指完全笔直,手指只算延长。因此,即使我检查所有手指没有延长,也会出现与上述相同的问题(爪状手会被识别为抓住)。

结合这两种方法也无法解决问题,因为它们都遇到了同样的问题,这并不奇怪。

现在,我们确实拥有每个手指的所有骨骼,包括位置和所有内容。但我不知道从哪里开始用数学来检测手指是否卷曲。

基本上我现在有这个设置:

var controller = Leap.loop(function(frame){
   if(frame.hands.length>0){
       //we only look at the first available hand
       var hand = frame.hands[0];
       //we get the index finger only, but later on we should look at all 5 fingers.
       var index = hands.fingers[1];
       //after that we get the positions of the joints between the bones in a hand
       //the position of the metacarpal bone (i.e. the base of your hand)
       var carp = index.carpPosition;
       //the position of the joint on the knuckle of your hand
       var mcp = index.mcpPosition;
       //the position of the following joint, between the proximal and the intermediate bones
       var pip = index.pipPosition;
       //the position of the distal bone (the very tip of your finger)
       var dip = index.dipPosition;

       //and now we need the angle between each of those positions, which is where i'm stuck
   }
});

那么,我如何获得两个位置之间的角度(鲤鱼到mcp,mcp到pip,pip到dip)?有什么想法吗?

3 个答案:

答案 0 :(得分:3)

好吧,我想我发现了一种检测实际拳头的工作方法,而不是爪子。

首先,我们需要每个骨骼的距离矢量,而不是关节的位置。

然后我们计算掌骨和近端骨之间的Dot积,以及近端骨和中间骨之间的点积。我们可以忽略远端骨骼,它不会过多地改变结果。

我们计算所有计算的点积(总共10个)并计算平均值(我们除以10)。这将给出一个0到1之间的值。一个拳头低于0.5,高于此值的一切基本上都不是拳头。

此外,您可能还想检查一只手上伸出的手指的数量,并检查它是否为0.这将确保一个"拇指向上"并且类似的1位数姿势不会被识别为拳头。

这是我的实施:

const minValue = 0.5;

var controller = Leap.loop(function(frame){
   if(frame.hands.length>0)
   {
      var hand = frame.hands[0];
      var isFist = checkFist(hand);
   }
});

function getExtendedFingers(hand){
   var f = 0;
   for(var i=0;i<hand.fingers.length;i++){
      if(hand.fingers[i].extended){
         f++;
      }
   }
   return f;
}

function checkFist(hand){
   var sum = 0;
   for(var i=0;i<hand.fingers.length;i++){
      var finger = hand.fingers[i];
      var meta = finger.bones[0].direction();
      var proxi = finger.bones[1].direction();
      var inter = finger.bones[2].direction();
      var dMetaProxi = Leap.vec3.dot(meta,proxi);
      var dProxiInter = Leap.vec3.dot(proxi,inter);
      sum += dMetaProxi;
      sum += dProxiInter
   }
   sum = sum/10;

   if(sum<=minValue && getExtendedFingers(hand)==0){
       return true;
   }else{
       return false;
   }
}

虽然这样做会有所作为,但我怀疑这是检测拳头的正确和最佳方法。所以,如果你知道更好的方法,请发布它。


  

解决方案是完美的,任何机会你都可以解释为什么你除以10以及为什么minValue为0.5?谢谢!

嗯,说实话,它并没有那么好用。我很快就会开始研究一个旨在通过Leap Motion改进拳头检测的小项目。

关于你的问题,我们将总和除以10,因为每个手指有2个骨关节,有5个手指。我们想要所有这些计算之和的平均值,因为不是所有的手指都会以相同的方式成角度。因此,我们需要一些将所有这些值包含在一个值中的值:平均值。鉴于我们总计有10次计算(每个手指2个,5个手指),我们将这些计算的总和除以我们去的位置。我们将得到一个介于0和1之间的值。

关于minValue:Trial&amp; Error。在我的一个项目中,我使用了0.6的值。 这是这种方法的另一个问题:理想情况下,平手应该是接近0的值,而拳头应该是1.

答案 1 :(得分:0)

我知道这是一个古老的话题,但是如果你们仍然在答案中,只需使用sphereRadius()即可;

答案 2 :(得分:-1)

我发现“ grabStrength”很好