OpenNI 1.5.4
SimpleViewer.java - sample program (Java)

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

This section describes the SimpleViewer sample program in the Java language. This sample program uses a DepthGenerator node to build an accumulative histogram from depth values.

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 decribed again.

Global Declaration Block

The following declaration block declares the OpenNI objects required for building the OpenNI production graph. 
@code 
    private OutArg<ScriptNode> scriptNode;
    private Context context;
    private DepthGenerator depthGen;
    private byte[] imgbytes;
@endcode

Each of these declarations is described separately in the following paragraphs. 

The @ref xn::ScriptNode "ScriptNode" object loads an XML script from a file or string, and then runs the XML script to build a production graph . . The ScriptNode object keeps references to all nodes created from the script, so they will not be destroyed. (This is since OpenNI will delete a node that has no remaining references to it.)

A @ref xn::Context "Context" object is a workspace in which the application builds an OpenNI production graph.  

The @ref xn::DepthGenerator "DepthGenerator" node generates a depth map. Each map pixel value represents a distance from the sensor.                        

The @ref xn::DepthMetaData "DepthMetaData" object provides a @ref glos_frame_object "frame object" for the @ref xn::DepthGenerator "DepthGenerator" node. A @ref dict_gen_node "generator node's" frame object contains the generated data frame and all its associated properties. This frame object, comprising the data frame and its properties, is accessible through the node's metadata object.  

The following definition is for the path to an OpenNI XML script file for inputting and building a stored production graph. The <i>production graph</i> is a network of <i>production nodes</i> and is the principal OpenNI object model. The identifies blobs as hands or human users. 
@code 
    #define SAMPLE_XML_PATH "../../../../Data/SamplesConfig.xml"
@endcode        

Main Program

@subsection svj_scrpt_sets_up_pg Uses a Script to Set up a Context and Production Graph             

    The following code block uses a script to set up a context and a production graph. The <b>Context.createFromXmlFile()</b> method is a shorthand combination of two other initialization methods, which initializes the context object and then creates a production graph from an XML file. The XML script file describes all the nodes you want to create. For each node description in the XML file, this method creates a node in the production graph.      
    @code 
        scriptNode = new OutArg<ScriptNode>();
        context = Context.createFromXmlFile(SAMPLE_XML_FILE, scriptNode);               
    @endcode            

@subsection svj_get_dg_node_from_pg Get a DepthGenerator Node from the Production Graph

    The following statement creates and returns a reference to a @ref xn::DepthGenerator "DepthGenerator" node. The create() method can return a reference to an existing DepthGenerator node if one already exists in the production graph created from the XML. If no DepthGenerator node already exists, this method creates a new DepthGenerator node and returns a reference to the new node.      
    @code 
        depthGen = DepthGenerator.create(context);
    @endcode

    The following statement gets the latest generated depth @ref glos_frame_object "frame object", saving it as a metadata object. 
    @code 
        DepthMetaData depthMD = depthGen.getMetaData();
    @endcode        

    The following sets up the array for the histogram array that is a key part of this sample program. (This is not OpenNI specific.)
    @code 
        histogram = new float[10000];
    @endcode                

    The following code accesses some attributes of the frame data's associated configuration properties: getFullXRes() and getFullYRes() are the full frame resolution, i.e., the entire field-of-view, ignoring cropping of the FOV in the scene.
    @code 
        width = depthMD.getFullXRes();
        height = depthMD.getFullYRes();
    @endcode        

    The remaining statements in this method are not OpenNI specific.            
    @code 
        imgbytes = new byte[width*height];

        DataBufferByte dataBuffer = new DataBufferByte(imgbytes, width*height);
        Raster raster = Raster.createPackedRaster(dataBuffer, width, height, 8, null);
        bimg = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        bimg.setData(raster);
    @endcode    

CalcHist() - Using the Depth Values to Build an Accumulative Histogram

The following code block uses the depth values to build an accumulative histogram of frequency of occurrence of each depth value. The <code>depthMD.DepthMapPtrgetData().createShortBuffer()</code>method returns a buffer that can be easily processed. The depth value is then used as an index into the histogram[] array.
@code 
    private void calcHist(DepthMetaData depthMD)
    {
        ...         
        ShortBuffer depth = depthMD.getData().createShortBuffer();
        depth.rewind();

        int points = 0;
        while(depth.remaining() > 0)
        {
            short depthVal = depth.get();
            if (depthVal != 0)
            {
                histogram[depthVal]++;
                points++;
            }
        }   
        ...
        ...
    } 
@endcode

updateDepth() method - Updating the Depth Map

The following statement sets up the frame object. It is described in the <a href="#getMetaData">HandTracker() method above</a>.  For more explanation on this, see @ref conc_meta_data, @ref glos_frame_object, and @ref frame_data.
@code 
    DepthMetaData depthMD = depthGen.getMetaData();
@endcode    

The following method call waits for any node to have generated new data. This method then 'updates' each and every node in the entire production graph. For an overview to reading data and the <b>WaitXUpdateAll</b> methods, see <i>@ref conc_updating_data__summary_of_wait_fns</i>. 

the @ref xn::Context::WaitAnyUpdateAll() "waitAnyUpdateAll()" method in the following statement updates all generator nodes in the context that have new data available, first waiting for any of the nodes to have new data available. The application can then get the data (for example, using a metadata GetData() method). This method has a timeout.      
@code 
    context.waitAnyUpdateAll();
@endcode

The following code block creates a convenient buffer for the depth map and then calls the calcHist() method to calculate the histogram.
@code 
    calcHist(depthMD);
    ShortBuffer depth = depthMD.getData().createShortBuffer();              
    depth.rewind();     
@endcode

The following code block builds an image buffer according to the frequency of each depth value in the histogram. 
@code 
while(depth.remaining() > 0)
    {
        int pos = depth.position();
        short pixel = depth.get();
        imgbytes[pos] = (byte)histogram[pixel];
    }       
@endcode

Dimension() method

There are no OpenNI-specific declarations in this routine.

paint() method

There are no OpenNI-specific declarations in this routine.