Well, I think I found a kind of working approach to detect the actual fist, not the claw.
First of all, instead of the positions of the joints, we need distance vectors for each bone.
We then calculate the Dot product between Metacarpal and the proximal bone, as well as the Spot product between the Proximal and the intermediate bone. We can ignore the distal bone, it does not change the result too much.
We summarize all calculated point products (total 10) and calculate the average value (we divide by 10). This will give us a value from 0 to 1. The fist is below 0.5, and everything higher than basically is not a fist.
In addition, you can also check the number of extended fingers on your hand and check if it is 0. This ensures that “Thumbs-up” and similar 1-digit poses are not recognized as “Fist”.
Here is my implementation:
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; } }
Although this works as it should, I doubt it is the right and best approach for finding Fist. So please, if you know the best way, post it.
The solution works just fine, any chance you could explain why you are dividing by 10 and why minValue is 0.5? Thanks!
Well, that doesn't work, to be honest. I will soon start working on a small project whose goal is to improve fist detection with Leap Motion.
As for your questions, we divide the amount by 10, because we have 2 bone joints for each finger with 5 fingers. We want to get the average value from the sum of all these calculations, because not all fingers will be angled the same. Therefore, we want some value to include all these values in a single whole: the average value. Given that we have only 10 calculations (2 for each finger, 5 fingers), we divide the sum of these calculations, and there we go. We get a value from 0 to 1.
Regarding minValue: Trial & Error. In my project, I used a value of 0.6. This is another problem with this approach: ideally, a flat arm should be a value of almost 0, and a fist should be 1.