2014-10-30 7 views
5

Voglio verificare se una mano in un fotogramma di salto è attualmente un pugno.Rilevamento di un pugno con Leap Motion SDK V2

Il metodo suggerito di solito è quello di cercare hand.grabStrength con un valore pari a 1. Il problema è che il valore passa a 1 anche con dita "artiglio" Hand, o qualsiasi altra cosa con leggermente arricciato.

Un altro approccio sarebbe quello di verificare su ogni dito se è extended. Ma questo ha un problema simile, le dita contano solo se estese se sono completamente diritte. Quindi, anche se controllo che tutte le dita non siano estese, si verifica lo stesso problema di cui sopra (le mani simili a un artiglio vengono riconosciute come afferrate).

La combinazione di questi due metodi non risolve il problema, il che non sorprende dato che entrambi soffrono degli stessi problemi.

Ora, abbiamo a disposizione tutte le ossa di ogni dito, con posizioni e tutto. Ma non ho idea di dove iniziare con la matematica per rilevare se un dito è arricciato.

Fondamentalmente ho questa messa a punto, per ora:

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 
    } 
}); 

Allora, come faccio ad avere l'angolo tra due di queste posizioni (carpa di MCP, MCP a Pip, pip a tuffo)? Qualche idea?

risposta

3

Va bene, penso di aver trovato una sorta di approccio di lavoro per rilevare un pugno vero e proprio non un artiglio.

Prima di tutto, invece delle posizioni dei giunti, abbiamo bisogno dei vettori di distanza per ogni osso.

Quindi si calcola il prodotto punto tra il metacarpo e l'osso prossimale, nonché il punto prodotto tra il prossimale e l'osso intermedio. Possiamo ignorare l'osso distale, non cambia troppo il risultato.

Sommiamo tutti i prodotti punto calcolato (10 in totale) e calcoliamo la media fuori (dividiamo per 10). Questo ci darà un valore compreso tra 0 e 1. Un pugno è inferiore a 0.5 e tutto ciò che sopra non è fondamentalmente un pugno.

Inoltre, si potrebbe anche voler controllare la quantità di dita estese su una mano e controllare se è 0. Ciò garantirà che un "Thumbs-up" e simili posizioni a 1 cifra non vengano riconosciuti come un pugno .

Qui è la mia realizzazione:

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; 
    } 
} 

Anche se questo funziona come dovrebbe, dubito che questo sia l'approccio corretto e migliore per rilevare un pugno. Quindi, per favore, se conosci un modo migliore, pubblicalo.


Solution funziona perfetto, qualsiasi possibilità che tu possa spiegare perché si divide per 10 e perché il minValue è di 0,5? Grazie!

Bene, non funziona così bene, ad essere onesti. Presto comincerò a lavorare su un piccolo progetto che ha l'obiettivo di migliorare il rilevamento dei pugni con Leap Motion.

Per quanto riguarda le tue domande, dividiamo la somma per 10 perché abbiamo 2 Bone Joints per dito, con 5 dita.Vogliamo il valore medio dalla somma di tutti quei calcoli, perché non tutte le dita saranno inclinate allo stesso modo. Quindi vogliamo un valore che racchiuda tutti questi valori in uno solo: il valore medio. Dato che abbiamo 10 calcoli in totale (2 per ogni dito, 5 dita), dividiamo la somma di quei calcoli e ci siamo. Otterremo un valore compreso tra 0 e 1.

Per quanto riguarda il valore min: errore di prova &. In un mio progetto, invece, ho usato un valore di 0.6. Questo è un altro problema di questo approccio: idealmente una mano piatta dovrebbe avere un valore di quasi 0, mentre un pugno dovrebbe essere 1.

+0

Non dovrebbe anche passare le dita spezzate sul giunto, indicando la direzione opposta angolare necessaria fare un pugno (come se completamente libero dalla gamma del giunto)? : D. * cringe * –

+0

Suppongo che lo farebbe, ma questa matematica è un po 'troppo complessa per me. : P – DodgerThud

+0

Ho trovato una buona soluzione usando la distanza tra ogni dito e il palmo. Calcola la somma di queste distanze e controlla se si trova al di sotto di una certa soglia. – whoabackoff