【问题标题】:Kinect & Processing - Convert position of joint as mouse x and mouse y?Kinect & Processing - 将关节的位置转换为鼠标 x 和鼠标 y?
【发布时间】:2015-11-22 00:33:08
【问题描述】:

我目前使用的是 XBOX KINECT 型号 1414,处理 2.2.1。我希望用右手作为鼠标来引导角色通过屏幕。

我设法画了一个椭圆来跟随 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);
}

任何形式的链接或帮助将不胜感激,谢谢!

【问题讨论】:

    标签: position mouse processing kinect


    【解决方案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 示例。
    这对您有帮助吗?

    【讨论】:

      【解决方案2】:

      目前还不清楚您要达到的目标。 如果您只需要二维屏幕坐标中手的位置,您发布的代码已经包含以下内容:

      1. kinect.getJointPositionSkeleton() 获取 3D 坐标
      2. kinect.convertRealWorldToProjective() 将它们转换为 2D 屏幕坐标。

      如果您希望能够在使用 kinect 跟踪的手部坐标和鼠标坐标之间进行交换,您可以将 2D 转换中使用的 PVector 存储为对整个草图可见的变量,您可以通过 kinect 骨架(如果它正在更新)跟踪或鼠标:

      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 示例(通过 Processing > File >示例 > 贡献库 > SimpleOpenNI > OpenNI > RecorderPlay)。 OpenNI 具有记录场景(包括深度数据)的能力,这将使测试变得更简单:只需记录一个包含您所针对的最常见交互的 .oni 文件,然后在开发时重新使用记录。 使用 .oni 文件只需为 OpenNI 使用不同的构造函数签名:

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

      要记住一个警告:深度以分辨率的一半存储(因此坐标需要加倍才能与实时版本相提并论)。

      【讨论】:

        猜你喜欢
        • 2011-01-13
        • 1970-01-01
        • 2014-02-09
        • 1970-01-01
        • 2016-04-08
        • 1970-01-01
        • 2011-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多