OpenNI 1.5.4: NiRecordSynthetic.cpp - sample program

OpenNI

NiRecordSynthetic.cpp - sample program

Source file: Click the following link to view the source code file:

  • NiRecordSynthetic.cpp

This section describes an OpenNI sample program for generating and recording synthetic data.

The program opens a recording, performs a transformation on the data from the recording, and then re-records the transformed data.

The documentation describes the sample program's code from the top of the program file(s) to bottom.

Every OpenNI feature is described the first time it appears in this sample program. Further appearances of the same feature are not described again.

transformDepthMD() function

The following function provides the code for performing a transformation on the image data generated by the OpenNI nodes. The function is described further below feature by feature.

            void transformDepthMD(DepthMetaData& depthMD)
            {
                DepthMap& depthMap = depthMD.WritableDepthMap();
                for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
                {
                    for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
                    {
                        //Punch vertical cut lines in the depth image
                        if ((x % 2) == 0)
                        {
                            depthMap(x, y) = 0;
                        }
                    }
                }
            }       

In the above, the DepthMetaData object provides a frame object for the xn::DepthGenerator node. The frame object of a generator node contains a snapshot of generated data frame and all its associated properties. This data frame and its properties are accessible through the node's metadata object.

DepthMap is a Map Wrapper class. The Map Wrapper classes are light wrappers for Frame Objects maps.

The WritableDepthMap() method gets a light object to wrap the writable depth map. So this initializes the DepthMap map wrapper class.

            DepthMap& depthMap = depthMD.WritableDepthMap();

The following double loop provides the x and y indexes to access each pixel in the DepthMap. The XRes() and YRes() methods return the two dimensions of the data frame, width and height, respectively.

            for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
            {
                for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
                {
                 ...
                } 
            }

Here is the code that performs the data transformation. It punches vertical 'cut' lines in the depth image.

            if ((x % 2) == 0)
            {
                depthMap(x, y) = 0;
            }       

main() – Main Program

Main Program Declaration Block

Initializing the Log from an XML file

In the following, the xn::xnLogInitFromXmlFile() method function initializes the log from an XML file. It initializes only the log; not the context or production graph.

                nRetVal = nRetVal = xnLogInitFromXmlFile(SAMPLE_XML_PATH);
                if (nRetVal != XN_STATUS_OK)
                {
                    printf("Log couldn't be opened: %s. Running without log", xnGetStatusString(nRetVal));
                }

Creating and Setting up the Nodes

The following initializes the xn::Context object. This is where the application builds an OpenNI production graph. The production graph is a network of production nodes and is the principal OpenNI object structure.

                Context context;
                nRetVal = context.Init();

The OpenFileRecording() method replays a recorded file of a session of OpenNI data generation exactly as it was recorded. This includes recreating the whole production graph, with all its nodes, that was built to run the original data generation session. This method performs this replaying by also creating a 'mock node' for each node in the file, and populates it with the recorded configuration. For an example of a mock node, see xn::MockDepthGenerator.

                Player player;
                nRetVal = context.OpenFileRecording(strInputFile, player);

In the following code, the FindExistingNode() method call gets a reference to a production node in the production graph. This sample program passes the depth parameter to get a reference to a DepthGenerator node so that it can work with it. A xn::DepthGenerator node generates a depth map. Each map pixel value represents a distance from the sensor.

            DepthGenerator depth;
            nRetVal = context.FindExistingNode(XN_NODE_TYPE_DEPTH, depth);

Create mock node based on depth node from recording The following declares a mock node. This is to simulate an actual node when recording or playing data from a recording. A mock node does not contain any logic for generating data. Instead, it allows an outside component (such as an application or a real node implementation) to feed it configuration changes and data.

                MockDepthGenerator mockDepth;

In the following statement, the xn::MockDepthGenerator node::CreateBasedOn() "CreateBasedOn()" method creates a "mock" DepthGenerator node based on the type and properties of the base node, in this case the depth node. This node does not represent an actual node, but only keeps a state and implements an interface above it. Mock nodes are specifically used for simulating nodes for playing recordings, or for use in tests.

                nRetVal = mockDepth.CreateBasedOn(depth);

In the following, the call to Create() initalizes a Recorder object. This object records to a specified destination medium the frames of data from each node that was added to it.

                Recorder recorder;
                nRetVal = recorder.Create(context);

In the following statement, the call to SetDestination() specifies to where the recorder must send its recording. This is a disk file of ONI type.

                nRetVal = recorder.SetDestination(XN_RECORD_MEDIUM_FILE, strOutputFile);

The following statement adds the node to the recording, and starts recording it.

                nRetVal = recorder.AddNodeToRecording(mockDepth);

The following statement specifies that the player will not automatically rewind to the beginning of the recording after reaching the end of the recording (the default behavior is to rewind).

                nRetVal = player.SetRepeat(FALSE);

The next code block gets the number of frames of a specific node played. In the case of this sample program this is just a statistic to print later on the console.

                XnUInt32 nNumFrames = 0;
                nRetVal = player.GetNumFrames(depth.GetName(), nNumFrames);

The following declares a metadata object for the DepthGenerator node. The metadata object is described above in the transformDepthMD() function transformDepthMD() function.

                DepthMetaData depthMD;

Main Program Loop

Following is the main program loop. It waits for available data from the generator and prints it out. The call to the n::Generator::WaitAndUpdateData() "WaitAndUpdateData()" method updates the node's application buffer to the latest available data, first waiting for the node to have new data available. Since this method is being fed from a recording, the end of the recording is indicated by returning the XN_STATUS_EOF value.

Note that the WaitAndUpdateData() method has to be called for each and every iteration to refresh the node's data.

                while ((nRetVal = depth.WaitAndUpdateData()) != XN_STATUS_EOF)
                {
                    ...
                }

The statements of body of the main loop are presented and explained, in the following.

The following statement gets the DepthGenerator node's frame object (the xn::DepthMetaData frame object). The metadata object is described above in the transformDepthMD() function transformDepthMD() function.

                depth.GetMetaData(depthMD);

Enable the depth map to be modified. In the following statement, the call to the MakeDataWritable() allocates a buffer and copies current data to it, so that the data can be edited.

                nRetVal = depthMD.MakeDataWritable();

The following statement makes a call to the transformDepthMD(), already described above in transformDepthMD() function. This call transforms the data.

                transformDepthMD(depthMD);

The following statement passes the transformed data to the xn::MockDepthGenerator object. The call to the SetData() method sets the data of the mock node from a metadata object.

                nRetVal = mockDepth.SetData(depthMD);

The following statement records one frame of data from each node that was added to the recorder by the AddNodeToRecording() method. To record continually, the Recorder node must be called repeatedly for each frame.

                nRetVal = Recorder.Record();

Finally, this sample program prints status information. In the statement below, the FrameID() method gets the frame ID of frame object. Frame IDs are a sequential unique number.

                printf("Recorded: frame %u out of %u\r", depthMD.FrameID(), nNumFrames);
Generated on Wed May 16 2012 10:16:06 for OpenNI 1.5.4 by   doxygen 1.7.5.1