Skip to content

Commit 7aa52cf

Browse files
committed
Merge pull request #523 from xlz/openni2
OpenNI2 driver
2 parents fa464d2 + 98aaf46 commit 7aa52cf

16 files changed

+2017
-1
lines changed

CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SET(DEPENDS_DIR "${MY_DIR}/depends" CACHE STRING "dependency directory must be s
2929

3030
OPTION(BUILD_SHARED_LIBS "Build shared (ON) or static (OFF) libraries" ON)
3131
OPTION(BUILD_EXAMPLES "Build examples" ON)
32+
OPTION(BUILD_OPENNI2_DRIVER "Build OpenNI2 driver" ON)
3233
OPTION(ENABLE_CXX11 "Enable C++11 support" OFF)
3334
OPTION(ENABLE_OPENCL "Enable OpenCL support" ON)
3435
OPTION(ENABLE_OPENGL "Enable OpenGL support" ON)
@@ -272,3 +273,23 @@ IF(BUILD_EXAMPLES)
272273
MESSAGE(STATUS "Configurating examples")
273274
ADD_SUBDIRECTORY(${MY_DIR}/examples)
274275
ENDIF()
276+
277+
IF(BUILD_OPENNI2_DRIVER)
278+
FIND_PACKAGE(OpenNI2)
279+
IF(OpenNI2_FOUND)
280+
FILE(GLOB OPENNI2_DRIVER_SOURCES src/openni2/*.cpp)
281+
ADD_LIBRARY(freenect2-openni2 ${OPENNI2_DRIVER_SOURCES} ${LIBFREENECT2_THREADING_SOURCE})
282+
TARGET_INCLUDE_DIRECTORIES(freenect2-openni2 PRIVATE ${OpenNI2_INCLUDE_DIRS})
283+
TARGET_LINK_LIBRARIES(freenect2-openni2 freenect2 ${LIBFREENECT2_THREADING_LIBRARIES})
284+
SET_TARGET_PROPERTIES(freenect2-openni2 PROPERTIES SOVERSION 0)
285+
IF(NOT ${CMAKE_INSTALL_PREFIX} MATCHES "^/usr")
286+
SET_TARGET_PROPERTIES(freenect2-openni2 PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
287+
ENDIF()
288+
INSTALL(TARGETS freenect2-openni2 DESTINATION lib/OpenNI2/Drivers RUNTIME DESTINATION bin)
289+
ADD_CUSTOM_TARGET(install-openni2
290+
DEPENDS freenect2-openni2
291+
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_INSTALL_PREFIX}/lib/OpenNI2/Drivers/" "${OpenNI2_LIBRARY_DIR}/OpenNI2/Drivers/"
292+
VERBATIM
293+
)
294+
ENDIF()
295+
ENDIF()

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Virtual machines likely do not work, because USB 3.0 isochronous transfer is qui
4040
The following minimum requirements must be met in order to enable the optional features:
4141
* OpenGL depth processing: OpenGL 3.1 (Windows, Linux, Mac OS X). No OpenGL ES support at the moment.
4242
* OpenCL depth processing: OpenCL 1.1
43+
* OpenNI2 driver: OpenNI2 2.2.0.33
4344

4445
## FAQ
4546

@@ -165,6 +166,10 @@ Or `install_libusb_vs2015.cmd`. If you see some errors, you can always open the
165166

166167
* Intel GPU: Download `intel_sdk_for_ocl_applications_2014_x64_setup.msi` from http://www.softpedia.com/get/Programming/SDK-DDK/Intel-SDK-for-OpenCL-Applications.shtml (SDK official download is replaced by $$$ and no longer available) and install it. Then verify `INTELOCLSDKROOT` is set as an environment variable. You may need to download and install additional OpenCL runtime.
167168

169+
#### OpenNI2 (optional)
170+
171+
* Download OpenNI 2.2.0.33 (x64) from http://structure.io/openni, install it to default locations (`C:\Program Files...`).
172+
168173
#### Build
169174

170175
```
@@ -174,13 +179,15 @@ cmake --build . --config RelWithDebInfo --target install
174179
```
175180
Or `-G "Visual Studio 14 2015 Win64"`. Then you can run the program with `.\install\bin\Protonect.exe`, or start debugging in Visual Studio. `RelWithDebInfo` provides debug symbols with release performance. The default installation path is `install`, you may change it by editing `CMAKE_INSTALL_PREFIX`.
176181

182+
To try OpenNI2, copy freenect2-openni2.dll, and other dll files (libusb-1.0.dll, glfw.dll, etc.) in `install\bin` to `C:\Program Files\OpenNI2\Tools\OpenNI2\Drivers`. Then run `C:\Program Files\OpenNI\Tools\NiViewer.exe`.
183+
177184
### Mac OSX
178185

179186
Use your favorite package managers (brew, ports, etc.) to install most if not all dependencies:
180187

181188
1. ``cd`` into a directory where you want to keep libfreenect2 stuff in
182189
1. Make sure these build tools are available: wget, git, cmake, pkg-config. Xcode may provide some of them. Install the rest via package managers.
183-
1. Install dependencies: libusb, TurboJPEG, GLFW.
190+
1. Install dependencies: libusb, TurboJPEG, GLFW, OpenNI2 (optional).
184191

185192
```
186193
brew update
@@ -189,6 +196,9 @@ brew tap homebrew/science
189196
brew install jpeg-turbo
190197
brew tap homebrew/versions
191198
brew install glfw3
199+
brew install openni2
200+
export OPENNI2_REDIST=/usr/local/lib/ni2
201+
export OPENNI2_INCLUDE=/usr/local/include/ni2
192202
```
193203

194204
It **is** now recommended to install libusb from package managers instead of building from source locally. Previously it was not recommended but that is no longer the case.
@@ -209,6 +219,7 @@ mkdir build && cd build
209219
cmake ..
210220
make
211221
make install
222+
make install-openni2 # may need sudo
212223
```
213224

214225
1. Run the program
@@ -217,6 +228,8 @@ make install
217228
./bin/Protonect
218229
```
219230

231+
Use `NiViewer` to test OpenNI2.
232+
220233
### Debian/Ubuntu 14.04
221234

222235
1. Install libfreenect2
@@ -252,6 +265,8 @@ sudo dpkg -i libglfw3*_3.0.4-1_*.deb
252265
* Mali GPU (e.g. Odroid XU4): (with root) `mkdir -p /etc/OpenCL/vendors; echo /usr/lib/arm-linux-gnueabihf/mali-egl/libmali.so >/etc/OpenCL/vendors/mali.icd; apt-get install opencl-headers`.
253266
* Verify: You can install `clinfo` to verify if you have correctly set up the OpenCL stack.
254267

268+
1. OpenNI2 dependency (optional): `sudo apt-get install libopenni2-dev`.
269+
255270
1. Build the actual protonect executable
256271

257272
```
@@ -260,6 +275,7 @@ mkdir build && cd build
260275
cmake ..
261276
make
262277
sudo make install # without sudo if cmake -DCMAKE_INSTALL_PREFIX=$HOME/...
278+
sudo make install-openni2 # if OpenNI2 support is enabled
263279
```
264280

265281
1. Run the program
@@ -268,6 +284,8 @@ sudo make install # without sudo if cmake -DCMAKE_INSTALL_PREFIX=$HOME/...
268284
./bin/Protonect
269285
```
270286

287+
1. Run OpenNI2: `sudo apt-get install openni2-utils && NiViewer2`.
288+
271289
### Other operating systems
272290

273291
I'm not sure, but look for libusbx installation instructions for your OS. Figure out how to attach the driver to the Xbox NUI Sensor composite parent device, VID 045E PID 02C4, then contribute your procedure.

cmake_modules/FindOpenNI2.cmake

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# - Find OpenNI2
2+
#
3+
# If the OPENNI2_INCLUDE and OPENNI2_REDIST environment variables
4+
# are defined, they will be used as search path.
5+
# The following standard variables get defined:
6+
# OpenNI2_FOUND: true if found
7+
# OpenNI2_INCLUDE_DIRS: the directory that contains the include file
8+
# OpenNI2_LIBRARY_DIR: the directory that contains the library
9+
10+
IF(PKG_CONFIG_FOUND)
11+
PKG_CHECK_MODULES(OpenNI2 libopenni2)
12+
ENDIF()
13+
14+
FIND_PATH(OpenNI2_INCLUDE_DIRS
15+
NAMES Driver/OniDriverAPI.h
16+
PATHS
17+
"/opt/include"
18+
"/opt/local/include"
19+
"/usr/include"
20+
"/usr/local/include"
21+
ENV OPENNI2_INCLUDE
22+
ENV PROGRAMFILES
23+
ENV ProgramW6432
24+
HINTS ${OpenNI2_INCLUDE_DIRS}
25+
PATH_SUFFIXES
26+
ni2
27+
openni2
28+
OpenNI2/Include
29+
)
30+
31+
FIND_LIBRARY(OpenNI2_LIBRARY
32+
NAMES OpenNI2 ${OpenNI2_LIBRARIES}
33+
PATHS
34+
"/opt/lib"
35+
"/opt/local/lib"
36+
"/usr/lib"
37+
"/usr/local/lib"
38+
ENV OPENNI2_REDIST
39+
ENV PROGRAMFILES
40+
ENV ProgramW6432
41+
HINTS ${OpenNI2_LIBRARY_DIRS}
42+
PATH_SUFFIXES
43+
ni2/OpenNI2/Drivers
44+
OpenNI2/Drivers/lib
45+
OpenNI2/Lib
46+
)
47+
48+
GET_FILENAME_COMPONENT(OpenNI2_LIBRARY_DIR ${OpenNI2_LIBRARY} DIRECTORY)
49+
50+
INCLUDE(FindPackageHandleStandardArgs)
51+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenNI2 DEFAULT_MSG OpenNI2_LIBRARY_DIR OpenNI2_INCLUDE_DIRS)

src/openni2/ColorStream.cpp

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* This file is part of the OpenKinect Project. http://www.openkinect.org
3+
*
4+
* Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors.
5+
* See the CONTRIB file for details.
6+
*
7+
* This code is licensed to you under the terms of the Apache License, version
8+
* 2.0, or, at your option, the terms of the GNU General Public License,
9+
* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10+
* or the following URLs:
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
* http://www.gnu.org/licenses/gpl-2.0.txt
13+
*
14+
* If you redistribute this file in source form, modified or unmodified, you
15+
* may:
16+
* 1) Leave this header intact and distribute it under the same terms,
17+
* accompanying it with the APACHE20 and GPL20 files, or
18+
* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19+
* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20+
* In all cases you must keep the copyright notice intact and include a copy
21+
* of the CONTRIB file.
22+
*
23+
* Binary distributions must follow the binary distribution requirements of
24+
* either License.
25+
*/
26+
27+
#define _USE_MATH_DEFINES
28+
#include <cmath> // for M_PI
29+
#include "ColorStream.hpp"
30+
31+
using namespace Freenect2Driver;
32+
33+
// from NUI library & converted to radians
34+
const float ColorStream::DIAGONAL_FOV = 73.9 * (M_PI / 180);
35+
const float ColorStream::HORIZONTAL_FOV = 62 * (M_PI / 180);
36+
const float ColorStream::VERTICAL_FOV = 48.6 * (M_PI / 180);
37+
38+
ColorStream::ColorStream(libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg) : VideoStream(pDevice, reg)
39+
{
40+
video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 1920, 1080, 30);
41+
setVideoMode(video_mode);
42+
}
43+
44+
// Add video modes here as you implement them
45+
ColorStream::FreenectVideoModeMap ColorStream::getSupportedVideoModes() const
46+
{
47+
FreenectVideoModeMap modes;
48+
// pixelFormat, resolutionX, resolutionY, fps freenect_video_format, freenect_resolution
49+
modes[makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 512, 424, 30)] = 0;
50+
modes[makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 1920, 1080, 30)] = 1;
51+
52+
return modes;
53+
54+
/* working format possiblities
55+
FREENECT_VIDEO_RGB
56+
FREENECT_VIDEO_YUV_RGB
57+
FREENECT_VIDEO_YUV_RAW
58+
*/
59+
}
60+
61+
void ColorStream::populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const
62+
{
63+
dstFrame->sensorType = getSensorType();
64+
dstFrame->stride = dstFrame->width * 3;
65+
66+
// copy stream buffer from freenect
67+
switch (video_mode.pixelFormat)
68+
{
69+
default:
70+
LogError("Pixel format " + to_string(video_mode.pixelFormat) + " not supported by populateFrame()");
71+
return;
72+
73+
case ONI_PIXEL_FORMAT_RGB888:
74+
if (reg->isEnabled()) {
75+
libfreenect2::Frame registered(512, 424, 4);
76+
77+
reg->colorFrameRGB888(srcFrame, &registered);
78+
79+
copyFrame(static_cast<uint8_t*>(registered.data), srcX, srcY, registered.width * registered.bytes_per_pixel,
80+
static_cast<uint8_t*>(dstFrame->data), dstX, dstY, dstFrame->stride,
81+
width, height, mirroring);
82+
} else {
83+
copyFrame(static_cast<uint8_t*>(srcFrame->data), srcX, srcY, srcFrame->width * srcFrame->bytes_per_pixel,
84+
static_cast<uint8_t*>(dstFrame->data), dstX, dstY, dstFrame->stride,
85+
width, height, mirroring);
86+
}
87+
return;
88+
}
89+
}
90+
91+
void ColorStream::copyFrame(uint8_t* srcPix, int srcX, int srcY, int srcStride, uint8_t* dstPix, int dstX, int dstY, int dstStride, int width, int height, bool mirroring)
92+
{
93+
srcPix += srcX + srcY * srcStride;
94+
dstPix += dstX + dstY * dstStride;
95+
96+
for (int y = 0; y < height; y++) {
97+
uint8_t* dst = dstPix + y * dstStride;
98+
uint8_t* src = srcPix + y * srcStride;
99+
if (mirroring) {
100+
dst += dstStride - 1;
101+
for (int x = 0; x < srcStride; ++x)
102+
{
103+
if (x % 4 != 3)
104+
{
105+
*dst-- = *src++;
106+
}
107+
else
108+
{
109+
++src;
110+
}
111+
}
112+
} else {
113+
for (int x = 0; x < dstStride-2; x += 3)
114+
{
115+
*dst++ = src[2];
116+
*dst++ = src[1];
117+
*dst++ = src[0];
118+
src += 4;
119+
}
120+
}
121+
}
122+
}
123+
124+
OniSensorType ColorStream::getSensorType() const { return ONI_SENSOR_COLOR; }
125+
126+
OniStatus ColorStream::setImageRegistrationMode(OniImageRegistrationMode mode)
127+
{
128+
if (mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR) {
129+
// XXX, switch color resolution to 512x424 for registrarion here
130+
OniVideoMode video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 512, 424, 30);
131+
setProperty(ONI_STREAM_PROPERTY_VIDEO_MODE, &video_mode, sizeof(video_mode));
132+
}
133+
return ONI_STATUS_OK;
134+
}
135+
136+
// from StreamBase
137+
OniBool ColorStream::isPropertySupported(int propertyId)
138+
{
139+
switch(propertyId)
140+
{
141+
default:
142+
return VideoStream::isPropertySupported(propertyId);
143+
144+
case ONI_STREAM_PROPERTY_HORIZONTAL_FOV:
145+
case ONI_STREAM_PROPERTY_VERTICAL_FOV:
146+
case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE:
147+
case ONI_STREAM_PROPERTY_AUTO_EXPOSURE:
148+
return true;
149+
}
150+
}
151+
152+
OniStatus ColorStream::getProperty(int propertyId, void* data, int* pDataSize)
153+
{
154+
switch (propertyId)
155+
{
156+
default:
157+
return VideoStream::getProperty(propertyId, data, pDataSize);
158+
159+
case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians)
160+
{
161+
if (*pDataSize != sizeof(float))
162+
{
163+
LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV");
164+
return ONI_STATUS_ERROR;
165+
}
166+
*(static_cast<float*>(data)) = HORIZONTAL_FOV;
167+
return ONI_STATUS_OK;
168+
}
169+
case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians)
170+
{
171+
if (*pDataSize != sizeof(float))
172+
{
173+
LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV");
174+
return ONI_STATUS_ERROR;
175+
}
176+
*(static_cast<float*>(data)) = VERTICAL_FOV;
177+
return ONI_STATUS_OK;
178+
}
179+
180+
// camera
181+
case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool
182+
{
183+
if (*pDataSize != sizeof(OniBool))
184+
{
185+
LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE");
186+
return ONI_STATUS_ERROR;
187+
}
188+
*(static_cast<OniBool*>(data)) = auto_white_balance;
189+
return ONI_STATUS_OK;
190+
}
191+
case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool
192+
{
193+
if (*pDataSize != sizeof(OniBool))
194+
{
195+
LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_EXPOSURE");
196+
return ONI_STATUS_ERROR;
197+
}
198+
*(static_cast<OniBool*>(data)) = auto_exposure;
199+
return ONI_STATUS_OK;
200+
}
201+
}
202+
}
203+
204+
OniStatus ColorStream::setProperty(int propertyId, const void* data, int dataSize)
205+
{
206+
switch (propertyId)
207+
{
208+
case 0:
209+
default:
210+
return VideoStream::setProperty(propertyId, data, dataSize);
211+
}
212+
}

0 commit comments

Comments
 (0)