Detecting a user's pose

In this recipe, we are going to show you how to request a search for a specific pose on a user and show the status of all the users' poses.

In the current version of NiTE, there are only two predefined poses that can be tracked and recognized: the PSI pose that was formally used as a calibration pose and the crossed hands pose that is a newly introduced pose. What follows is an image of a PSI pose:

Detecting a user's pose

In the new version of NiTE, there is no practical need to find out if a user is in one of these two predefined poses, because there is no need to be in a PSI pose for calibration and no requirement for the crossed hands pose that we are aware of. But you can still use these poses alone or if you want to support other third-party middleware. Also, even when it seems there is no need for PSI poses for calibration, it is still an error to indicate that calibration failed because of a lack of poses. So it may be used in some rare cases.

Getting ready

Create a project in Visual Studio and prepare it for working with OpenNI and NiTE using the Create a project in Visual Studio 2010 recipe in Chapter 2, OpenNI and C++.

How to do it...

  1. Add these lines at the top of your source code (just below the #include lines):
    char ReadLastCharOfLine()
    {
      int newChar = 0;
      int lastChar;
      fflush(stdout);
      do 
      {
        lastChar = newChar;
        newChar = getchar();
      }
      while ((newChar != '
    ') 
        && (newChar != EOF));
      return (char)lastChar;
    }
    bool HandleStatus(nite::Status status)
    {
      if (status == nite::STATUS_OK)
        return true;
      printf("ERROR: #%d, %s", status,
        openni::OpenNI::getExtendedError());
      ReadLastCharOfLine();
      return false;
    }
  2. Then locate the following line:
    int _tmain(int argc, _TCHAR* argv[])
    {
  3. Now add the following inside this function:
      nite::Status status = nite::STATUS_OK;
      status = nite::NiTE::initialize();
      if (!HandleStatus(status)) return 1;
      printf("Creating user tracker ...
    ");
      nite::UserTracker uTracker;
      status = uTracker.create();
      if (!HandleStatus(status)) return 1;
      printf("Reading data from user tracker ...
    ");
      while(!_kbhit())
      {
        nite::UserTrackerFrameRef newFrame;
        status = uTracker.readFrame(&newFrame);
        if (!HandleStatus(status) ||
          !newFrame.isValid()) return 1;
        system("cls");
        const nite::Array<nite::UserData>& users =
          newFrame.getUsers();
        for (int i = 0; i < users.getSize(); ++i)
        {
          if (users[i].isNew()){
            uTracker.startPoseDetection(
              users[i].getId(),
              nite::POSE_PSI);
          }
          printf("User #%d %s - %s 
    ",
            users[i].getId(), 
            (users[i].isVisible()) ?
            "is Visible" : "is not Visible",
            (users[i].getPose(nite::POSE_PSI).isHeld()) ?
              "In PSI Pose" : "In No Pose");
        }
      }
      uTracker.destroy();
      nite::NiTE::shutdown();
      return 0;

How it works...

This is a fairly simple recipe. As you can see in step one, we have nothing except two of our famous functions: ReadLastCharOfLine() for reading input from the console and HandleStatus() for checking if a nite::Status object is indicating an error.

Also, in the initial lines of step two, we have the same lines of code as given in the previous recipes. We initialized NiTE and created a nite::UserTracker object. But just after that we entered a while loop to read data from nite::UserTracker until a user pressed a key in the console. In our while loop, we have the code for reading a frame of data; this can be seen in the second line of the following code:

    nite::UserTrackerFrameRef newFrame;
    status = uTracker.readFrame(&newFrame);

And then we cleared the console by calling a system command:

    system("cls");

Then, to get the status of each user's pose information, we read the list of all the recognized users and their properties, including their poses, by defining an array of the nite::UserData variable and calling the nite::UserTrackerFrameRef::getUsers() method:

    const nite::Array<nite::UserData>& users =
      newFrame.getUsers();

The next step is to loop through the users using another loop:

    for (int i = 0; i < users.getSize(); ++i)

Then we can show the status of each user's pose to the user via the console; however, how can we expect to recognize a pose when we didn't request a search for it? That's why we need to call the nite::UserTracker::startPoseDetection() method when a new user is recognized:

      if (users[i].isNew()){
        uTracker.startPoseDetection(
          users[i].getId(),
          nite::POSE_PSI);
      }

As you can see in the preceding code, we checked if this user is a newly recognized user and if so, asked for a search for the PSI pose on this user.

Note

From what we experienced, nite::POSE_CROSSED_HANDS is not recognizable before tracking begins, at least not in the current beta version. You will learn more about tracking in the next recipe.

Then we are going to show the current user's active pose to the user:

      printf("User #%d %s - %s 
",
        users[i].getId(), 
        (users[i].isVisible()) ?
          "is Visible" : "is not Visible",
        (users[i].getPose(nite::POSE_PSI).isHeld()) ?
          "In PSI Pose" : "In No Pose");

This is a little complicated because we tried to do all the things in one line. But as you can clearly see, we used the nite::UserData::getPose() method to retrieve the status of one of the poses of the user, and then using nite::PoseData::isHeld(), we found out if the user is currently in this pose.

Based on these two methods, we wrote an inline if to show the name of the active pose (the PSI pose in our case) and In No Pose if the user wasn't in the PSI pose.

The output of our application is as follows:

How it works...

See also

  • The Recognizing predefined hand gestures recipe in Chapter 6, NiTE and Hand Tracking
  • The Getting a user's skeleton joints and displaying their position in the depth map recipe
  • The Designing a simple pong game using skeleton tracking recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.31.67