Thursday, April 19, 2012

Running ROS Openni Tracker (Offline) with Recorded data '.oni' files

It is always more convenient to run the tracker on a recorded data.  I recorded an '.oni' file using Openni Sample 'NiViewer'. Initialized the Context manually rather than from the 'xml' file.

You need to make the following changes in your openni_tracker.cpp

Note:
I had created a ros package mimicking the openni_tracker {i.e with same dependencies}. Then i created an Eclipse project for it. It makes debugging and changing the code easier.



// Declare .oni player

xn::Player   g_Player;  




Instead of

/*
    string configFilename = ros::package::getPath("openni_tracker") + "/openni_tracker.xml";
    XnStatus nRetVal = g_Context.InitFromXmlFile(configFilename.c_str());
    CHECK_RC(nRetVal, "InitFromXml");

*/


    // added for Reading '.oni' file

    XnStatus nRetVal = g_Context.Init();
    CHECK_RC(nRetVal, "Init");
    nRetVal = g_Context.OpenFileRecording("your .oni file", g_Player);
    if (nRetVal != XN_STATUS_OK)
    {
    printf("Can't open recording %s\n", xnGetStatusString(nRetVal));
    return 1;
    }

  • make
  •  run openni_tracker
  • rosrun rviz rviz 
Hopefully you will see the skeleton.
Following video shows ros openni tracker on recorded data :)




Running OpenNi tracker on ROS Bag files/ Subscribed Depth topics
/ / OpenNI Context
xn::Context g_context;
g_context.Init ();
// OR initialize from an XML file
nRetVal = nRetVal = xnLogInitFromXmlFile(SAMPLE_XML_PATH);
/ / Depth generator
xn::DepthGenerator depth_generator;
depth_generator.Create (g_context);
/ / Mock depth generator
xn::MockDepthGenerator g_mock_depth;
g_mock_depth.CreateBasedOn (depth_generator, "the mock-depth" );
/ / Create user generator using mock depth generator
xn::Query g_Query;
g_Query.AddNeededNode ( "mock-depth" );
xn::UserGenerator g_user;
g_user.Create (g_context, & g_Query);
//following runs in a while loop
while (ros::ok())
{
/ / Update data
g_context.WaitOneUpdateAll (depth_generator);
/ / Get original depth map
xn::DepthMetaData depthMD;
depth_generator.GetMetaData (depthMD);
/ / Make data writable and modify
depthMD.MakeDataWritable ();



/ / Modify data ....
//write a function which changes the depth data in your original depth map
transformDepthMD(DepthMetaData& depthMD)
/ / set the data of the mock-depth generator and pose will tracking will run on this
g_mock_depth.SetData (depthMD);
//rest of the code
.............
............
}
//the function for modifying depth data could like this
void transformDepthMD(DepthMetaData& depthMD)
{
          xn::Depthmap & depthMap = depthMD.WritableDepthMap ();
          for ( unsigned int y = 0; y < depthMap.YRes (); + + y)
                   for ( unsigned int x = 0; x < depthMap.XRes (); + + x)
                           depthMap (x, y) = 0; // replace the values of the depth map by recorded depth map
}




8 comments:

  1. Hi Tayyab,
    I am new to openni and not good in C++. I am interested in running the openni_tracker on rosbags. Should I use this code and update the openni_tracker.cpp? Which parts in that file are replace by this code? Is it possible to attach the file that worked for you.

    Thanks in advance,
    dksr

    ReplyDelete
    Replies
    1. Hi Krishna,
      This piece of code basically contains all the changes one needs to do in openni_tracker.cpp. I will upload the whole file soon as well.
      Cheers

      Delete
  2. Its easy run openni_tracker u openni_kinect with oni file, but i have problems with files of type .bag (rosbag). I don't know how make or configure the xml files or the connection. I need your help please (wpairo@gmail.com)

    ReplyDelete
    Replies
    1. Sorry for the late reply Ayanami, I was just quite busy with some stuff lately.
      Basically the changes which i have mentioned in the sample above should do the trick. The only thing you need to change is that instead of
      depthMap (x, y) = 0;
      just replace the value here with your subscribed depth topic value.
      depthMap (x,y) = subscribed_depth< data_type >.at(x,y)
      where data_type is the type of your depth data.
      Hope it helps.

      Delete
  3. Hello TAYYEB,

    Thanks for useful informations that you posted.

    I have a question in case that it is related to your field.

    I want to track human body with Openni_tracker but with two different Kinects.

    As far as I understood I should define two CONTEXCT and for each Context define a user generator which is related to each Camera.

    But I dont know how I could do this (I am very new in openni)

    Do you have any Idea?
    or maybe a useful link that I could read and learn how to do this?

    Thanks,
    Hamed

    ReplyDelete
  4. Hi Tayeeb,

    This is really useful. I tried this, but it raises runtime exception (segmentation fault) when user and calibration callbacks are registered. Would you be able to upload your openni_tracker.cpp file? I might be missing something.

    Thanks,

    Kalana

    ReplyDelete
  5. Hi Tayeeb,

    I am going to use Openni tracker in order to obtain skeleton joint positions and orientations. but the problem is my data is already recorded by kinect and now the only things that I have are video frames in png format.

    Is there any way that I can get skeleton joint positions and orientation from images, using openni tracker or another open source code?

    Thanks.
    Fahimeh

    ReplyDelete
  6. I am trying to obtain the skeleton data on rviz but a message pops up on rviz saying openni_depth_frame does not exist and no skeleton data appears.

    ReplyDelete