2014-10-30 73 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