使用Kinect / SimpleOpenNI +处理深度模拟按钮按下

时间:2012-07-18 21:56:13

标签: processing kinect openni

我正在使用Kinect和Simple OpenNI和Processing,我试图使用手的Z位置来模拟按下按钮。到目前为止,当我用一只手尝试它时效果非常好,然而,当我试着让它用秒针工作时,只有一只手工作。 (我知道除了填写if语句之外的所有内容都可以更有效率,但我保留了那些内容,以防我想要更改大小或其他内容。)

irz和ilz是当他们首次被onCreateHands识别并且rz和lz是当前Z位置时手的初始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的值,并且数字范围从小负值到小正值(大约-8到8),用于lz - ilz。但rz - irz输出的数字大约是8-30,这取决于我每次运行它并且从不一致。此外,当我注释掉lz-ilz的代码时,rz-irz的值看起来很好,并且按预期运行。是否有理由追踪两个Z位置?有没有办法让它发挥作用?

谢谢!

1 个答案:

答案 0 :(得分:1)

我有几点想法:

  1. 使用NITE“点击”手势
  2. 像现在一样使用手的z位置,但也跟踪z运动的差异
  3. 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,但请注意手部精度较低。