0

我正在使用带有 Simple OpenNI 和处理的 Kinect,并且我试图使用手的 Z 位置来模拟按钮按下。到目前为止,当我用一只手尝试它时效果非常好,但是,当我尝试让它用另一只手工作时,只有一只手可以工作。(我知道通过移动除 if 语句的填充之外的所有内容会更有效,但我将它们保留在那里以防万一我想更改大小或其他内容。)

irz 和 ilz 是手在第一次被 onCreateHands 识别时的初始 Z 位置,而 rz 和 lz 是当前 Z 位置。到目前为止,代码可以用一只手正常工作,但另一只手将保持按下或未按下。如果我将其中一个部分注释掉,它也可以正常工作。

if (rz - irz > 0) {
 pushStyle();
 fill(60);
 ellipse(rx, ry, 10, 10);
 popStyle();
 rpressed = true;
}
else {
 pushStyle();
 noFill();
 ellipse(rx, ry, 10, 10);
 popStyle();
 rpressed = false;
}

if (lz - ilz > 0) {
 pushStyle();
 fill(60);
 ellipse(lx, ly, 10, 10);
 popStyle();
 lpressed = true;
}
else {
 pushStyle();
 noFill();
 ellipse(lx, ly, 10, 10);
 popStyle();
 lpressed = false;
}

我尝试输出 rz - irz 和 lz - ilz 的值,对于 lz - ilz,数字范围从小的负值到小的正值(大约 -8 到 8)。但是 rz - irz 输出的数字在 8-30 左右,具体取决于我每次运行它的时间,而且从来都不是一致的。此外,当我注释掉 lz-ilz 的代码时,rz-irz 的值看起来还不错,并且可以按预期运行。跟踪两个 Z 位置是否有理由让一只手丢掉?有没有办法让它工作?

谢谢!

4

1 回答 1

1

我有几个想法:

  1. 使用 NITE“点击”手势
  2. 像现在一样使用手的 z 位置,但也要跟踪 z 运动的差异

SimpleOpenNI 似乎更喜欢一只手而不是两只手,比如“点击”之类的 NITE 手势(你应该在拿起手后看到打印的消息,然后向前和向后移动你的手)。贝娄是一个简单的例子。请注意,我正在跟踪 Z 上的 +/- 差异,并使用阈值仅基于特定距离触发,例如,这可能是范围。

import SimpleOpenNI.*;
SimpleOpenNI context;
boolean      handsTrackFlag = false;
PVector      handVec = new PVector();
PVector      handVec2D  = new PVector();//just for drawing
String       lastGesture = "";
float        lastZ = 0;
boolean      isPushing,wasPushing;
float        yourClickThreshold = 20;//set this up as you see fit for your interaction

void setup(){
  size(640,480);  
  context = new SimpleOpenNI(this);
  context.enableDepth();
  // enable hands + gesture generation
  context.enableGesture();
  context.enableHands();
  // add focus gestures  / here i do have some problems on the mac, i only recognize raiseHand ? Maybe cpu performance ?
  context.addGesture("Wave");
  context.addGesture("Click");
  context.addGesture("RaiseHand");

}

void draw()
{
  context.update();
  image(context.depthImage(),0,0);
  // draw the tracked hand
  if(handsTrackFlag){
    context.convertRealWorldToProjective(handVec,handVec2D);
    float diff = (handVec.z-lastZ);
    isPushing = diff < 0;
    if(diff > yourClickThreshold){
      if(!wasPushing && isPushing) fill(255,0,0);
      if(wasPushing && !isPushing) fill(0,255,0);
    }else fill(255);
    lastZ = handVec.z;
    wasPushing = isPushing;
    ellipse(handVec2D.x,handVec2D.y,10,10);
  }

}


// -----------------------------------------------------------------
// hand events

void onCreateHands(int handId,PVector pos,float time){
  println("onCreateHands - handId: " + handId + ", pos: " + pos + ", time:" + time);

  handsTrackFlag = true;
  handVec = pos;
}

void onUpdateHands(int handId,PVector pos,float time){
  //println("onUpdateHandsCb - handId: " + handId + ", pos: " + pos + ", time:" + time);
  handVec = pos;
}

void onDestroyHands(int handId,float time){
  println("onDestroyHandsCb - handId: " + handId + ", time:" + time);
  handsTrackFlag = false;
  context.addGesture(lastGesture);
}

// -----------------------------------------------------------------
// gesture events

void onRecognizeGesture(String strGesture, PVector idPosition, PVector endPosition){
  if(strGesture == "Click") println("onRecognizeGesture - strGesture: " + strGesture + ", idPosition: " + idPosition + ", endPosition:" + endPosition);

  lastGesture = strGesture;
  context.removeGesture(strGesture); 
  context.startTrackingHands(endPosition);
}

void onProgressGesture(String strGesture, PVector position,float progress){
  //println("onProgressGesture - strGesture: " + strGesture + ", position: " + position + ", progress:" + progress);
}

获得两只手的另一种方法是SKEL_PROFILE_HEAD_HANDS在进行骨骼跟踪时使用,但请注意手的精度较低。

于 2012-11-15T01:35:02.393 回答