2015-11-22 40 views
1

我目前正在使用XBOX KINECT模型1414,並處理2.2.1。我希望用右手作爲鼠標指導角色穿過屏幕。Kinect&Processing - 將鼠標x和鼠標y的關節位置轉換爲?

我設法繪製一個橢圓來跟隨一個kinect骨架上的右手關節。我如何能夠弄清楚該關節的位置,以便我可以根據需要替換mouseX和mouseY?

下面是將跟蹤你的右手和在它上面繪製一個紅色橢圓代碼:

import SimpleOpenNI.*; 

SimpleOpenNI kinect; 

void setup() 
{ 
// instantiate a new context 
kinect = new SimpleOpenNI(this); 
kinect.setMirror(!kinect.mirror()); 
// enable depthMap generation 
kinect.enableDepth(); 

// enable skeleton generation for all joints 
kinect.enableUser(); 

smooth(); 
noStroke(); 

// create a window the size of the depth information 
size(kinect.depthWidth(), kinect.depthHeight()); 

} 



void draw() 
{ 

// update the camera...must do 
kinect.update(); 

// draw depth image...optional 
image(kinect.depthImage(), 0, 0); 

background(0); 


// check if the skeleton is being tracked for user 1 (the first user that detected) 
if (kinect.isTrackingSkeleton(1)) 
{ 
int joint = SimpleOpenNI.SKEL_RIGHT_HAND; 

// draw a dot on their joint, so they know what's being tracked 
drawJoint(1, joint); 

PVector point1 = new PVector(-500, 0, 1500); 
PVector point2 = new PVector(500, 0, 700); 
} 
} 

/////////////////////////////////////////////////////// 

void drawJoint(int userID, int jointId) { 
// make a vector to store the left hand 
PVector jointPosition = new PVector(); 
// put the position of the left hand into that vector 
kinect.getJointPositionSkeleton(userID, jointId, jointPosition); 
// convert the detected hand position to "projective" coordinates that will match the depth image 
PVector convertedJointPosition = new PVector(); 
kinect.convertRealWorldToProjective(jointPosition, convertedJointPosition); 
// and display it 
fill(255, 0, 0); 

float ellipseSize = map(convertedJointPosition.z, 700, 2500, 50, 1); 
ellipse(convertedJointPosition.x, convertedJointPosition.y, ellipseSize, ellipseSize); 
} 

//////////////////////////// Event-based Methods 

void onNewUser(SimpleOpenNI curContext, int userId) 
{ 
println("onNewUser - userId: " + userId); 
println("\tstart tracking skeleton"); 

curContext.startTrackingSkeleton(userId); 
} 

void onLostUser(SimpleOpenNI curContext, int userId) 
{ 
println("onLostUser - userId: " + userId); 
} 

任何形式的鏈接或幫助將非常感激,謝謝!

回答

1

在你的情況下,我會建議你使用右手關節的座標。這是你如何讓他們:

foreach (Skeleton skeleton in skeletons) { 
    Joint RightHand = skeleton.Joints[JointType.HandRight]; 

    double rightX = RightHand.Position.X; 
    double rightY = RightHand.Position.Y; 
    double rightZ = RightHand.Position.Z; 
} 

注意的事實是,我們正在尋找在3個維度,所以你將有一個X,Y和Z座標。

供參考:您將不得不將這些代碼行插入事件處理程序SkeletonFramesReady。 如果你仍然想要圍繞它的圓看看Kinect SDK中的Skeleton-Basics WPF示例。
這對你有幫助嗎?

1

稍微不清楚你試圖達到什麼目的。 如果你只需要在2D屏幕座標手的位置,你已經發布的代碼包括這樣的:

  1. kinect.getJointPositionSkeleton()獲取三維座標
  2. kinect.convertRealWorldToProjective()將它們轉換爲2D屏幕座標。

如果你希望能夠使用Kinect的跟蹤手部座標和鼠標座標之間的交換,你可以存儲在2D轉換用作可變可見整個草圖您通過Kinect的骨架,如果更新要麼PVector它正在跟蹤或以其他方式鼠標:

import SimpleOpenNI.*; 

SimpleOpenNI kinect; 

PVector user1RightHandPos = new PVector(); 
float ellipseSize; 

void setup() 
{ 
// instantiate a new context 
kinect = new SimpleOpenNI(this); 
kinect.setMirror(!kinect.mirror()); 
// enable depthMap generation 
kinect.enableDepth(); 

// enable skeleton generation for all joints 
kinect.enableUser(); 

smooth(); 
noStroke(); 

// create a window the size of the depth information 
size(kinect.depthWidth(), kinect.depthHeight()); 

} 



void draw() 
{ 

    // update the camera...must do 
    kinect.update(); 

    // draw depth image...optional 
    image(kinect.depthImage(), 0, 0); 

    background(0); 


    // check if the skeleton is being tracked for user 1 (the first user that detected) 
    if (kinect.isTrackingSkeleton(1)) 
    { 
     updateRightHand2DCoords(1, SimpleOpenNI.SKEL_RIGHT_HAND); 
     ellipseSize = map(user1RightHandPos.z, 700, 2500, 50, 1); 
    }else{//if the skeleton isn't tracked, use the mouse 
     user1RightHandPos.set(mouseX,mouseY,0); 
     ellipseSize = 20; 
    } 

    //draw ellipse regardless of the skeleton tracking or mouse mode 
    fill(255, 0, 0); 

    ellipse(user1RightHandPos.x, user1RightHandPos.y, ellipseSize, ellipseSize); 
} 

/////////////////////////////////////////////////////// 

void updateRightHand2DCoords(int userID, int jointId) { 
    // make a vector to store the left hand 
    PVector jointPosition = new PVector(); 
    // put the position of the left hand into that vector 
    kinect.getJointPositionSkeleton(userID, jointId, jointPosition); 
    // convert the detected hand position to "projective" coordinates that will match the depth image 
    user1RightHandPos.set(0,0,0);//reset the 2D hand position before OpenNI conversion from 3D 
    kinect.convertRealWorldToProjective(jointPosition, user1RightHandPos); 
} 

//////////////////////////// Event-based Methods 

void onNewUser(SimpleOpenNI curContext, int userId) 
{ 
    println("onNewUser - userId: " + userId); 
    println("\tstart tracking skeleton"); 

    curContext.startTrackingSkeleton(userId); 
} 

void onLostUser(SimpleOpenNI curContext, int userId) 
{ 
    println("onLostUser - userId: " + userId); 
} 

可選地,可以使用一個布爾測試時鼠標/ Kinect的模式之間切換。

如果您需要的鼠標座標簡單地進行測試,而不必從Kinect的的得到,我推薦看看RecorderPlay例如(通過處理>文件>實例的所有時間>第三方庫> SimpleOpenNI > OpenNI> RecorderPlay)。 OpenNI能夠記錄一個場景(包括深度數據),這將使測試變得更加簡單:只需記錄一個.oni文件,其中包含最常見的相互作用,然後在開發時重新使用該記錄。 所有則需使用.oni文件使用不同的構造函數簽名OpenNI:

kinect = new SimpleOpenNI(this,"/path/to/yourRecordingHere.oni"); 

一個警告要牢記:深度存儲在一半的分辨率(所以有需要的座標是加倍與實時版本相當)。