OpenNI/NiTE 2 Migration Guide – Transitioning from OpenNI/NiTE 1.5 to OpenNI/NiTE 2
Document Version 1.1
Disclaimer and Proprietary Information Notice
The information contained in this document is subject to change without notice and does not represent
a commitment by PrimeSense Ltd. PrimeSense Ltd.
and its subsidiaries make no warranty of any kind with regard to this material,
including, but not limited to implied warranties of merchantability
and fitness for a particular purpose whether arising out of law, custom, conduct or otherwise.
While the information contained herein is assumed to be accurate, PrimeSense Ltd. assumes no responsibility
for any errors or omissions
contained herein, and assumes no liability for special, direct, indirect
or consequential damage, losses, costs, charges, claims, demands, fees or
expenses, of any nature or kind, which are incurred in connection with the
furnishing, performance or use of this material.
This document contains proprietary information, which is protected by U.S. and international copyright laws.
All rights reserved. No part of this document may be reproduced, photocopied or translated into another language
without the prior written consent of PrimeSense Ltd.
OpenNI is written and distributed under the Apache License, which means that its source code is freely-distributed and available to the general public.
You may obtain a copy of the License at:http://www.apache.org/licenses/LICENSE-2.0
NiTE is a proprietary software item of PrimeSense and is written and licensed under the NiTE License terms, which might be amended from time to time. You should have received a copy of the NiTE License along with NiTE.
The latest version of the NiTE License can be accessed at:http://www.primesense.com/solutions/nite-middleware/nite-licensing-terms/
PrimeSense, the PrimeSense logo, Natural Interaction, OpenNI, and NiTE are trademarks and registered trademarks of PrimeSense Ltd. Other brands and their products are trademarks or registered trademarks of their respective holders and should be noted as such.
This migration guide is targeted at developers using OpenNI versions that came before OpenNI 2, with particular emphasis on those developers using OpenNI1.5.2 who are interested in transitioning to OpenNI 2. This guide is designed as both an aid to porting existing applications from the old API to the new API, as well as to enable experienced OpenNI developers to learn and understand the concepts that have changed in this new API.
This guide provides a general overview to all programming features that have changed. Included also is a lookup table of all classes and structures in OpenNI 1.5, showing the equivalent functionality in OpenNI 2.
1.2 Related Documentation
 NiTE 2 Programmer Guide, PrimeSense.
The first line of support for OpenNI/NiTE developers is the OpenNI.org web site. There you will find a wealth of development resources, including ready-made sample solutions and a large and lively community of OpenNI/NiTE developers. See:
If you have any questions or require assistance that you have not been able to obtain at OpenNI.org, please contact PrimeSense customer support at:
2.1 New OpenNI Design Philosophy
OpenNI 2 represents a major change in the underlying design philosophy of OpenNI. A careful analysis of the previous OpenNI API, version 1.5, revealed that it has many features that are rarely or never used by the developer community. When designing OpenNI 2, PrimeSense has endeavored to greatly reduce the complexity of the API. Features have been redesigned around basic functionality that was of most interest to the developer community. Of especial importance is that OpenNI 2 vastly simplifies the interface for communicating with depth sensors.
2.2 Simplified Middleware Interface
The plug-in architecture of the original OpenNI has been removed completely. OpenNI 2 is now strictly an API for communicating with sources of depth and image information via underlying drivers. PrimeSense NiTE middleware algorithms for interpreting depth information are now available as a standalone middleware package on top of OpenNI, complete with their own API. Previously, the API was through OpenNI only and you included NiTE functionality via plug-ins.
The following high level diagram compares the OpenNI/NiTE 2 architecture with the OpenNI/NiTE1.5 architecture.
Figure 2-1: Comparison of OpenNI/NiTE 2 architecture with OpenNI/NiTE1.5
NiTE 2 API is summarized in Chapter ?10, and is described in detail in the NiTE 2 Programmerӳ Guide.
PrimeSense is not aware of any third party middleware that actually made use of the provided OpenNI plug-In interfaces. All known third party middleware simply had been built to run on top of OpenNI. By simplifying the underlying interfaces that middleware developers are actually using, it is hoped that third party middleware providers will find it easier to implement their products on OpenNI.
2.3 Simplified Data Types
OpenNI 1.5 had a wide variety of complex data types. For example, depth maps were wrapped in metadata. This made it more complicated to work with many types of data that, in their raw form, are simply arrays. OpenNI 2 achieves the following:
- Unifies the data representations for IR, RGB, and depth data
- Provides access to the underlying array
- Eliminates unused or irrelevant metadata
- OpenNI 2 allows for the possibility of not needing to double buffer incoming data
OpenNI 2 solves the double buffering problem by performing implicit double buffering. Due to the way that frames were handled in OpenNI 1.5, the underlying SDK was always forced to double buffer all data coming in from the sensor. This had implementation issues, complexity problems and performance problems. The data type simplification in OpenNI 2 allows for the possibility of not needing to double buffer incoming data. However, if desired it is still possible to double-buffer. OpenNI 2 allocates one or more user buffers and a work buffer.
2.4 Transition from Data Centric to Device Centric
The overall design of the API can now be described as device centric, rather than data centric. The concepts of Production Nodes, Production Graphs, Generators, Capabilities, and other such data centric concepts, have been eliminated in favor of a much simpler model that provides simple and direct access to the underlying devices and the data they produce. The functionality provided by OpenNI 2 is generally the same as that provided by OpenNI 1.5.2, but the complicated metaphors for accessing that functionality are gone.
2.5 Easier to Learn and Understand
It is expected that the new API will be much easier for programmers to learn and begin using. OpenNI 1.5.2 had nearly one hundred classes, as well as over one hundred supporting data structures and enumerations. In OpenNI 2, this number has been reduced to roughly a dozen, with another dozen or so supporting data types. The core functionality of the API can be understood by learning about just four central classes:
Unfortunately, this redesign has required us to break backward compatibility with OpenNI 1.5.2. The decision to do this was not made lightly; however, it was deemed necessary in order to achieve the design goals of the new API.
2.6 Event Driven Depth Access
In OpenNI 1.5 and before, depth was accessed by placing a loop around a blocking function that provided new frames as they arrive. Until a new frame arrived the thread would be blocked. OpenNI 2 still has this functionality, but it also provides callback functions for event driven depth reading. These callback functions are invoked on sensors becoming available (further sensors can be connected to the host system while OpenNI is running), and on depth becoming available.
3 Summary of New Classes
4 Overall Context – The OpenNI Class
The OpenNI class provides the entry point and overall context for the library. The OpenNI class also provides access to devices, and to events related to devices entering and leaving the system. See the OpenNI 2 Programmerӳ Guide for a complete introduction to using the OpenNI Class.
4.2 Replaces the Context class
The openni::OpenNI class provides the same overall functionality as the Context class did in OpenNI1.5. The openni::OpenNI class provides a top level area where the overall state of the API is stored. Any OpenNI 2 based application will start by running the initialization function in this class.
In OpenNI 1.5, a complex system of Production Nodes, Generators, and Production Trees/Chains was used to access depth data. In OpenNI 2 this has been simplified to a model where various hardware sensors are represented by objects of Device class. Devices provide streams of data, which in turn are composed of sequential FrameRefs (single video frames). The OpenNI class is responsible for initializing the actual hardware drivers and making physical devices accessible by Device objects.
Note that openni::OpenNI is implemented as a collection of static functions. Unlike the Context class in OpenNI 1.5, it does not need to be instantiated. Simply call the initialize() function to make the API ready to use.
4.3 Device Events (New Functionality)
OpenNI 2 now provides the following device events:
- Device added to the system
- Device deleted from the system
- Device reconfigured
These events are implemented using an OpenNI::Listener class and various callback registration functions. See the OpenNI 2 Programmerӳ Guide for details. The EventBasedRead sample provided with OpenNI 2 provides example code showing how to use this functionality.
4.4 Miscellaneous Functionality
The various error types implemented in OpenNI 1.5 via the EnumerationErrors class have been replaced with simple return codes. Translation of these codes into human readable strings is handled by openni::OpenNI. This replaces the Xn::EnumerationErrors class from OpenNI 1.5.
OpenNI 1.5 provided a specific xn::Version class and XnVersion structure to deal with API version information. In OpenNI 2, the OniVersion structure is provided to store the API version. This information is accessed via a simple call to the openni::OpenNI::Version() function. This replaces the xn::Version class and the XnVersion structure from OpenNI 1.5.
5 The OpenNI Device Class
In OpenNI 1.5, data was produced by Ԑroduction NodesԮ There was a mechanism whereby individual Production Nodes could specify dependency on each other, but in principal there was (for example) no difference between a Depth Generator node that was providing data from a camera, and a Hands Generator node creating hand points from that same data. The end application was not supposed to care whether the hand points it was using were generated from a depth map, or some other data source.
The old approach had a certain symmetry in how data was accessed, but it ignored the underlying reality that in all real cases the raw data produced by a hardware device is either a RGB video stream, an IR stream, or a Depth stream. All other data is produced directly from these streams by middleware.
OpenNI 2 has switched to a metaphor that much more closely mimics the real life situation. In doing so, we were able to reduce the complexity of interacting with hardware, the data it produces, and the middleware that acts on that hardware.
The base of the new hierarchy is the Device class. A Device represents either:
- ޠphysical hardware device that is producing actual streams of data
– or -
- ޠfile device that contains a recording taken from a physical device.
The Device class is used to connect to a device, configure it, and to obtain video streams (implemented as VideoStream objects). For each device there is one stream each for Color, IR, and Depth.
The Device class in OpenNI 2 replaces the Device class in OpenNI 1.5, as well as replacing the Depth, IR, and Image Generator classes.
Please see the OpenNI 2 Programmerӳ Guide for a complete introduction to using the Device class.
5.2 Device Specific Capabilities
In OpenNI 1.5, there was a general Capability class that was intended to represent the capability of a ԇeneratorԠin an abstract sense. Any feature or data source, whether a device or algorithm or some other data source was supposed to be represented by some sort of capability. A long list of possible capabilities was defined.
The FrameSync and AlternativeViewPoint mechanisms in OpenNI 1.5 have been replaced by a simpler system in OpenNI 2. OpenNI 2 uses ‘DepthColorSync’ and ‘ImageRegistration’ to more closely follow how real devices are actually configured. These represent underlying flags that are set in firmware or hardware on a device wide basis
The ԁlternative Viewpoint CapabilityԠis now referred to as ԉmage RegistrationԮ
5.3 File Devices
In OpenNI 1.5, the playback of recorded data was handled by an explicit player object and the use of virtual ԍock NodesԠto produce the data. OpenNI 2 changes this to a system where a recording is specified in place of a physical device when the device is actually opened. The caller to the Device:open() function provides a parameter specifying whether it is a sensor device or a file device. If a recording is specified, after the initial call to the Device::open() function, a recording is in every way identical to the output from a physical device.
An openni::PlaybackControl class is also defined to control additional capabilities specific to file devices. The abilities to seek within a recording, loop the recording, and control the playback speed are all provided.
Recordings are made with the openni::Recorder class. See chapter ?8 for more information on the Recorder and PlaybackControl classes.
6 The OpenNI VideoStream Class
The VideoStream Class replaces the DepthGenerator, IRGenerator, and ImageGenerator as the direct source of data from the sensor. It provides the means to start data generation, read individual frames, obtain information about the streams, and configure the streams. It also encapsulates the functionality formerly contained in the CroppingCapability, MirrorCapability classes, and some of the functionality of the GeneralIntCapability class.
6.2 Changes to Access Approach
Since the Generator classes have been eliminated, data is obtained directly from devices. To create a video stream, simply create a VideoStream object, and call the openni::VideoStream::create() function, passing in a valid Device object that will supply the data.
Once initialized, there are two options for obtaining data: a polling loop, and event driven access.
Polling is most similar to the functionality of the WaitXUpdateX() family in OpenNI 1.5. To perform polling , call the openni::VideoStream::start() function on a properly initialized VideoStream object. (A properly initialized VideoStream object is where a device has been opened, a stream has been associated with the device, and the start command has been given. Then, call the openni::VideoStream::readframe() function. This function will block until a new frame of data is read.
To access data in an event driven manner, you need to implement a class that extends the openni::VideoStream::Listener class, and write a callback function to handle each new data frame. See the OpenNI 2 Programmerӳ Guide for more information.
6.3 Getting Stream Information
The openni::VideoStream::getSensorInfo() function is provided to obtain a SensorInfo object for an initialized video stream. This object allows enumeration of available video modes supported by the sensor.
The openni::VideoMode object encapsulates the resolution, frame rate, and pixel format of a given VideoMode. Openni::VideoStream::getVideoMode() will provide the current VideoMode setting for a given stream.
Functions are also provided by the VideoStream class that enable you to check resolution, and obtain minimum and maximum values for a depth stream.
6.4 Configuring Streams
To change the configuration of a stream, use the OpenNI::VideoStream:setVideoMode() function. A valid VideoMode should first be obtained from the list contained in a SensorInfo object associated with a VideoStream, and then passed in using setVideoMode().
6.5 Mirroring Data
Instead of a ԍirroring CapabilityԬ mirroring is now simply a flag set at the VideoStream level. Use the VideoStream::setMirroringEnabled() function to turn it on and off.
Instead of a ԃropping CapabilityԬ cropping is now set at the VideoStream level. This is done directly with the VideoStream::setCropping() function. The parameters to be passed are no longer encapsulated in a ԃroppingԠobject as they were in OpenNI 1.5 ֠they are now simply a collection of 4 integers.
6.7 Other Properties
The ԇeneral IntԠcapabilities have been replaced with simple get and set functions for integer based sensor settings. Use of these should be rare, however, since all of the commonly used properties
(i.e., mirroring, cropping, resolution, and others) are encapsulated by other functions rather than manipulated directly.
7 The OpenNI VideoFrameRef Class
In OpenNI 1.5.x, data was stored in a complex hierarchy of classes. There were separate classes for IR, Image, and Depth data, and a class hierarchy that was several layers deep. All of this overhead greatly obscured access to data that, at its heart, is simply a two dimensional array of pixel values.
In OpenNI 2 this complexity has been reduced by using a single ԖideoFrameRefԠclass to encapsulate all data relevant to a single frame of data, regardless of its type. Metadata has been reduced to the minimum required to work with the frames.
7.2 Accessing frame data
The VideoFrameRef class includes the VideoFrameRef::getData() function that returns a pointer directly to the underlying frame data. Use the VideoFrameRef::getSensorType() function to determine the type of data contained ֠Depth, IR or Color ֠if required.
Functions are provided to access the following metadata properties of a frame of data:
- Data size
- Type of Sensor used to create data
- Timestamp of the frame
- Video Mode of the data (resolution and frame rate)
- Frame index (a number assigned to each frame sequentially)
- Width of frame in pixels
- Height of frame in pixels
- Cropping settings
- Stride of the array containing the data
8 OpenNI Recordings
8.1 Recorder Class
All recordings are now taken by a Recorder class. The basic purpose of the recorder class is to capture the output of one or more streams in an ONI file. To make a recording, simply give the openni::Recorder class a list of valid streams that you would like to record from, the name of a file to record to, and then call the start() function. Once you are finished recording, call the stop() function.
The resulting ONI file can later be used to create a device that will behave almost exactly as a physical device would.
8.2 PlaybackControl Class
It is possible to perform certain operations with a recording that cannot be done with a regular physical device. OpenNI 2 provides functions encapsulated in the PlaybackControl class to perform these operations. These functions simplify the use of the Device class for physical devices. A PlaybackControl object is instantiated and attached to a device file, and can then be used to access specific recording functionality, e.g., speed change and looping.
The functionality provided includes seeking within a recording, determining how many frames a recording contains, changing playback speed, and looping playback.
9 OpenNI Classes no longer Exposed
Several classes and data structures were provided in OpenNI 1.5 that were not directly related to the central purpose of the API. These included data structures for handling points, planes, bounding boxes, etc. They also included miscellaneous structures for abstracting operating system functionality, as well as various other Ԩelper classesԠnot directly related to reading depth information. These items have been removed from the API in this revision. In some cases, they are retained behind the scenes for implementation of the API, in other cases they have been removed entirely.
OpenNI developers who need any of these OpenNI classes that are no longer exposed, i.e., those who wish to extend or change the code of OpenNI itself, can find them in the PSCommon folder in the OpenNI source code.
10 Functionality Moved to NiTE 2
In OpenNI 1.5, a specific set of interfaces was provided for gesture detection, skeleton tracking, hand point detection, and user detection. Binary middleware plugins could then provide algorithms to implement these specific interfaces. PrimeSense NiTE middleware was one such implementation.
It was, however, found that few developers actually used this framework, so in OpenNI 2 the approach has been completely changed. Any attempt at standardizing the interface between middleware and applications has been abandoned. As a result, OpenNI 2 includes no interfaces for higher level middleware.
NiTE is still provided, with all the same functionality. It is now a standalone package, with its own API. Thus there are now two separate installers, one for OpenNI and one for NiTE. See the NiTE 2 Programmerӳ Guide for more information.
10.2 Full Body Tracking
All functionality related to Scene Segmentation, Skeleton Tracking, Pose Detection, and User Tracking is now handled by a single User Tracker API ֠UserTrackerFrameRef. Each frame of User Tracker output is stored in an object of type UserTrackerFrameRef, which contains all scene segmentation, skeleton, and pose data. Data specific to a given user is stored in an object of type UserData. UserData is obtainable via accessor functions ֠get() ֠in UserTrackerFrameRef.
10.2.2 Scene Segmentation
The UserTracker now provides an opened and working device that provides depth data via a call to nite::UserTracker::create(), and scene segmentation begins immediately. The UserMap class is used to store user segmentation data.
Step by step instructions on how to do this in code are given in the NiTE 2 Programmerӳ Guide. Alternatively, see the sample entitled ԓimpleUserTrackerԠfor an easy to follow example of how to use all of the major User Tracker API functions. Scene segmentation now also includes a floor plane calculation.
10.2.3 Skeleton Tracking
Skeleton tracking has been incorporated into the User Tracker.
Starting the Skeleton for a given user now requires a single function call:
Once tracking has started, skeleton data is available as a nite::Skeleton object, obtained from UserData by calling nite::UserData::getSkeleton.
The Skeleton class itself simply provides access to a collection of joints. Position and orientation data for each joint is stored as a nite::SkeletonJoint object, which can be obtained by using nite::Skeleton::getJoint(). Possible types for SkeletonJoint are enumerated in nite::JointType. Joint orientation is now stored using the more standard Quaternions, instead of transformation matrices.
The Skeleton class also provides access to calibration status data via nite::Skeleton::getState(). Possible calibration states, including a few informative error states, are enumerated in nite::SkeletonState.
10.2.4 Pose Detection
Explicit Pose detection is now available by calling nite::UserTracker::startPoseDetection(). The list of available poses is enumerated in nite::PoseTypes.
10.3 Hand Tracking
Hand tracking is now performed via the HandTracker API. This API also includes gesture detection calls.
The HandTracker needs to be given a working device with the nite::HandTracker::create() call, and then hand tracking can be started by calling nite::HandTracker::startHandTracking(). All hand points and gestures detected in a given frame are encapsulated in HandTrackerFrameRef objects. The actual HandPoint data is stored as objects of type HandData, and gestures recognized are stored as type GestureData.
An enumeration of available gesture types is available in nite::GestureTypes.
Step by step instructions on how to do this in code are given in the NiTE 2 Programmerӳ Guide. Alternatively, see the sample entitled ԓimpleHandTrackerԼ/strong> for an easy to follow example of how to use all of the major Hand Tracker API functions.
10.4 Event Driven Programming
Both the User Tracker and Hand Tracker have associated listener class types that can be used to assign callback functions. Every new frame of data generates an event that calls these listeners. The UserTracker and HandTracker now completely encapsulate the link between NiTE and OpenNI (other than the initial function call to create()). It is therefore now possible to write a completely event driven application with NiTE. There is no need to set up a polling loop to read sensor data ֠that is all handled behind the scenes. Each frame of output from either the UserTracker or HandTracker provides a direct link to the depth frame that it was generated from, easing the process of combining NiTE output with raw depth data.
NiTE 2 includes classes for representing points, planes, bounding boxes, quaternions, and arrays.
In NiTE 2, quaternions replace transformation matrices when manipulating skeleton joints.
11 Obsolete Concepts
The architecture changes in OpenNI 2 have caused a number of specific concepts to be no longer necessary. As a result, there are a number of classes and structures in OpenNI 1.5 that have no equivalent in OpenNI 2. This chapter discusses each group of items that have been removed, and the reasons behind these decisions.
11.2 Mock Generators
Mock Generators were used to implement the recording system in OpenNI 1.5 and to implement third party depth drivers. In OpenNI 2, recordings are created and simulated at the Device level. There is no longer any need for a special class of items to play back the data.
The elimination of Production Nodes and Production Chains has rendered the xn::Query object obsolete.
OpenNI 1.5 provided a large number of classes devoted to implementing its plug-in architecture. OpenNI plug-ins were referred to as ԭodulesԮ Since this architecture no longer exists, none of these items are required.
11.5 Licensing Infrastructure
OpenNI 1.5 provided a key-value based licensing infrastructure for middleware developers to use with their code. Since OpenNI no longer directly supports middleware plug-ins, there is no reason to leave in the licensing functionality. Middleware developers are of course free to develop their own licensing mechanisms for use with their standalone middleware packages. The elimination of a licensing mechanism means that there is no longer any need for the xn::License class.
11.6 Script Nodes
Script nodes were a little used Production Node type. No equivalent for them has been provided in OpenNI 2.
11.7 Log Objects
OpenNI 1.5 provided a complex logging mechanism for errors. Since OpenNI 2 simplifies error reporting the log objects have been rendered unnecessary. Logging status codes in whatever form the application developer finds convenient should now be very easy to implement in the application itself.
OpenNI 1.5 provided support for a proprietary audio format via OpenNI. The only functionality provided by this audio system was a simple recording of PCM formatted sounds, with the expectation that audio would be recorded or analyzed using third party middleware. It was decided that the much more common USB-UAC (Universal Audio Class) would provide an easier to use interface for a wider number of tools. For this reason, the OpenNI 1.5 audio streams have been eliminated in favor of embracing the UAC standard. This prompted the removal of the following items from the API:
11.9 Abstract Data Types
OpenNI 1.5 had an extensive hierarchy of data types. For example, there were three different types of video frames (Depth, IR, RGB). Each of these types of video had its own Generator class to create the data, and its own metadata class to hold the data. The various generators had a MapGenerator ancestor class to abstract functionality common to each, which in turn had a Generator ancestor, itself derived from a ProductionNode.
The simplification in OpenNI 2 has eliminated most of this hierarchy. OpenNI 2 factors out the NiTE middleware and now creates separate objects for devices and video streams. This has eliminated much of the common functionality. Merging the various video types into a single VideoFrameRef type provided further simplification. The end result is a completely flat class hierarchy. This has caused the complete elimination of many classes that served only to provide abstraction.
The concept of a generic ԃapabilityԠhas been eliminated. In its place, various objects have simple get/set functions to activate appropriate functionality. Mirror and Cropping capabilities are now found in the VideoStream class. ImageRegistration and FrameSync capabilities are now managed from the Device class. The ԇeneral IntԠcapabilities have been replaced with get property and set property functions in either VideoStream or Device, depending on whether the setting in question affects a single stream or the entire device.
11.9.3 Production Nodes
The attempt at unifying middleware and hardware data sources has been abandoned. This has made the concept of a Ԑroduction NodeԠno longer necessary. Equivalent functionality to specific Product Node types has been retained in the VideoStream and Device classes, but the abstract hierarchy above the specific types is now gone.
Generators, including the specific types such as MapGenerators, have been eliminated. The ԭapԠtypes have all been retained as VideoStreams. Audio is now handled via UAC. The abstract hierarchy that attempted to unify these various types has been eliminated in favor of simply using VideoStreams for everything with a type code to indicate the data type.
The various specific MetaData types (IRMetaData, ImageMetaData, DepthMetaData) are all handled by the openni::VideoFrameRef class. The hierarchy of abstract types (i.e., MapMetaData) has been eliminated.
Appendix A Index of OpenNI 1.5 – 2.0 Equivalents
This appendix provides a list of all classes and structures in OpenNI 1.5, along with a brief description of where to find the equivalent functionality in OpenNI 2. See the relevant chapters of this guide, the OpenNI 2 Programmerӳ Guide, or the HTML based SDK reference for additional details.
The overall structure of the two versions is different enough that a true one-to-one mapping of functions is not practical. This table is primarily intended to help you find the right area of the documentation to get the functionality you are looking for. In particular, please do not simply replace the code in the left column with the code in the right column ֠that will not yield a functioning program.
The table is listed alphabetically by OpenNI 1.5.2 item name. See the object in the second column for the equivalent OpenNI 2 functionality. The third column gives the section or chapter of this document where the relevant concept is discussed.
Table A-1: Index of OpenNI 1.5 – 2 Equivalents