2014-10-30 72 views
5

我想检查Leap Motion Frame中的手是否当前是拳头。用Leap Motion SDK V2检测拳头

通常建议的方法是寻找值为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沾)?有任何想法吗?

回答

3

好吧,我想我找到了一种工作方式来检测一个实际的拳头,而不是爪子。

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

然后我们计算Metacarpal和Proximal骨之间的Dot产品,以及Proximal和Intermediate Bone之间的点产品。我们可以忽略远端骨骼,它不会改变太多的结果。

我们将计算出的所有点积(总共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,因为我们有5个手指,每个手指有2个骨关节。我们希望所有这些计算之和的平均值,因为不是所有的手指都会以相同的方式成角度。因此,我们希望将所有这些值包含在一个值中的一些值:平均值。鉴于我们总共有10个计算(每个手指2个手指,5个手指),我们将这些计算的总和分开,然后我们就去了。我们将得到介于0和1之间的值。

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

+0

这是否也会使手指在关节处断裂,指向需要的角度方向相反的方向做一个拳头(好像完全不受关节范围的限制)? :d。 * cringe * – 2014-10-30 14:11:29

+0

我想这会,但是这个数学对我来说有点太复杂。 :P – DodgerThud 2014-10-30 14:17:27

+0

我发现一个很好的解决方案,使用每个手指和手掌之间的距离。计算这些距离的总和并检查它是否低于某个阈值。 – whoabackoff 2015-04-27 19:14:37