我想检查Leap Motion帧中的一只手当前是否为拳头。
通常建议的方法是查找值为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
}
});那么,如何获得其中两个位置之间的角度(carp到mcp,mcp到pip,pip到dip)?有什么想法吗?
发布于 2014-10-30 20:00:20
好吧,我想我找到了一种有效的方法来检测真正的拳头,而不是爪子。
首先,我们需要每个骨骼的距离向量,而不是关节的位置。
然后我们计算掌骨和近端骨之间的点积,以及近端和中间骨之间的点积。我们可以忽略远端骨骼,它不会改变结果太多。
我们将所有计算出的点积相加(总共10个),并计算出平均值(除以10)。这将给我们一个介于0和1之间的值。拳头低于0.5,高于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,因为我们每个手指有2个骨关节,有5个手指。我们想要所有这些计算的总和的平均值,因为不是所有的手指都会以相同的方式倾斜。因此,我们需要一些值,将所有这些值包含在一个单独的值中:平均值。假设我们总共有10个计算(每个手指2个,5个手指),我们将这些计算的总和除以,我们就得到了结果。我们将得到一个介于0和1之间的值。
关于minValue:试错。在我的一个项目中,我使用了值0.6。这是这种方法的另一个问题:理想情况下,平手的值应该接近0,而拳头的值应该是1。
发布于 2019-05-05 20:41:35
我知道这是一个古老的话题,但是如果你们还在的话,使用sphereRadius()可能会更简单;
发布于 2020-05-25 23:59:04
我发现"grabStrength“是个好词
https://stackoverflow.com/questions/26649941
复制相似问题