我想检查Leap Motion Frame中的Hand当前是否是拳头.
通常建议的方法是hand.grabStrength使用值1 来查找.问题是,即使使用"爪状"手,或者手指非常轻微卷曲的任何其他值,该值也会跳至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
}
});
Run Code Online (Sandbox Code Playgroud)
那么,我如何得到两个位置之间的角度(鲤鱼到mcp,mcp到pip,pip到dip)?有任何想法吗?
小智 3
好吧,我想我找到了一种检测实际拳头而不是爪子的工作方法。
首先,我们需要每个骨骼的距离向量,而不是关节的位置。
然后我们计算掌骨和近端骨之间的点积,以及近端骨和中间骨之间的点积。我们可以忽略远端骨骼,它不会对结果产生太大影响。
我们将所有计算出的点积相加(总共 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;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这可以正常工作,但我怀疑这是检测拳头的正确且最佳的方法。所以,如果您知道更好的方法,请发布。
解决方案非常完美,您能否解释一下为什么除以 10 以及为什么 minValue 是 0.5?谢谢!
嗯,说实话,效果不太好。我很快就会开始从事一个小项目,其目标是通过 Leap Motion 改进拳头检测。
关于您的问题,我们将总和除以 10,因为我们有 5 个手指,每个手指有 2 个骨关节。我们需要所有这些计算总和的平均值,因为并非所有手指都会以相同的方式倾斜。因此,我们需要一个将所有这些值包含在一个值中的值:平均值。鉴于我们总共有 10 次计算(每个手指 2 次,5 根手指),我们将这些计算的总和除以就可以了。我们将得到一个介于 0 和 1 之间的值。
关于 minValue:尝试与错误。在我的一个项目中,我使用了 0.6 的值。这是这种方法的另一个问题:理想情况下,平手的值应接近 0,而拳头的值应为 1。