0

私はKinectをSimple OpenNIとProcessingで使用しており、手のZ位置を使用してボタンの押下をエミュレートしようとしていました。これまでのところ、片手で試してみると非常にうまく機能しますが、秒針で機能させようとすると、片方の手しか機能しません. (if ステートメントの入力以外のすべてを移動することで効率が上がることはわかっていますが、サイズなどを変更したい場合に備えて、それらをそのままにしておきました。)

irz と ilz は onCreateHands によって最初に認識されたときの手の初期 Z 位置であり、rz と lz は現在の Z 位置です。現時点では、コードは片手で問題なく動作しますが、もう一方の手は押したままにするか、押したままにします。セクションの1つをコメントアウトすると、うまく機能します。

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ジェスチャを使用すると、片方の手が2つよりも好むようです(手を持ち上げてから手を前後に動かすと、メッセージが印刷されます)。ベローは簡単な例です。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 に答える