├── tests ├── __init__.py └── test_libfreenect2.py ├── setup.cfg ├── pylibfreenect2 ├── libfreenect2 │ ├── __init__.pxd │ └── libfreenect2.pxd ├── cuda_packet_pipeline.pxi ├── opencl_packet_pipeline.pxi ├── opengl_packet_pipeline.pxi ├── opencl_kde_packet_pipeline.pxi ├── __init__.py └── libfreenect2.pyx ├── docs ├── api.rst ├── getstarted.rst ├── dev.rst ├── index.rst ├── installation.rst ├── Makefile └── conf.py ├── MANIFEST.in ├── NEWS.md ├── README.md ├── LICENSE.md ├── appveyor.yml ├── examples ├── selective_streams.py └── multiframe_listener.py ├── .travis.yml ├── .gitignore └── setup.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | -------------------------------------------------------------------------------- /pylibfreenect2/libfreenect2/__init__.pxd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pylibfreenect2.libfreenect2 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include pylibfreenect2 *.cpp *.pxd *.pyx *.pxi 2 | -------------------------------------------------------------------------------- /docs/getstarted.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | See `examples/multiframe_listener.py `_. 5 | 6 | The example code demonstrates basic usage of pylibfreenect2. It requires a python binding of opencv for visualization. 7 | If you are using `Anaconda `_, you can install it by: 8 | 9 | .. code:: 10 | 11 | conda install opencv 12 | 13 | Have fun! 14 | -------------------------------------------------------------------------------- /docs/dev.rst: -------------------------------------------------------------------------------- 1 | Developer Documentation 2 | ======================= 3 | 4 | Run tests 5 | --------- 6 | 7 | Assuming that you have installed ``nose``, you can run unittests by: 8 | 9 | .. code:: 10 | 11 | nosetests -v -w tests/ 12 | 13 | 14 | If you don't have kinect v2 connected, you can run unittests that doesn't require devices by: 15 | 16 | .. code:: 17 | 18 | nosetests -v -w tests/ -a '!require_device' 19 | 20 | This is exactly what CI does for automatic testing. 21 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # News for pylibfreenect2 2 | 3 | ## v0.2.0 4 | 5 | - Add startStrems and undistortDepth [#31] 6 | - Add new KDE depth packet processing pipeline [#26] 7 | - Add getPointXYZ and getPointXYZRGB [#23] 8 | 9 | ## v0.1.1 10 | 11 | - Fix installation issue with old cython [#12] 12 | - Fix packet pipelines detection bug on windows [#21] 13 | 14 | ## v0.1.0 15 | 16 | - Initial release 17 | 18 | [#12]: https://github.com/r9y9/pylibfreenect2/issues/12 19 | [#21]: https://github.com/r9y9/pylibfreenect2/issues/21 20 | [#23]: https://github.com/r9y9/pylibfreenect2/pull/23 21 | [#26]: https://github.com/r9y9/pylibfreenect2/pull/26 22 | [#31]: https://github.com/r9y9/pylibfreenect2/pull/31 23 | -------------------------------------------------------------------------------- /pylibfreenect2/cuda_packet_pipeline.pxi: -------------------------------------------------------------------------------- 1 | cdef class CudaPacketPipeline(PacketPipeline): 2 | """Pipeline with Cuda depth processing. 3 | 4 | Attributes 5 | ---------- 6 | pipeline : `libfreenect2::CudaPacketPipeline*` 7 | 8 | Parameters 9 | ---------- 10 | device_id : int, optional 11 | Device id. Default is -1. 12 | 13 | """ 14 | cdef libfreenect2.CudaPacketPipeline * pipeline 15 | 16 | def __cinit__(self, int device_id=-1): 17 | self.pipeline = new libfreenect2.CudaPacketPipeline(device_id) 18 | self.pipeline_ptr_alias = self.pipeline 19 | self.owned_by_device = False 20 | 21 | def __dealloc__(self): 22 | if not self.owned_by_device: 23 | if self.pipeline is not NULL: 24 | del self.pipeline 25 | -------------------------------------------------------------------------------- /pylibfreenect2/opencl_packet_pipeline.pxi: -------------------------------------------------------------------------------- 1 | cdef class OpenCLPacketPipeline(PacketPipeline): 2 | """Pipeline with OpenCL depth processing. 3 | 4 | Attributes 5 | ---------- 6 | pipeline : `libfreenect2::OpenCLPacketPipeline*` 7 | 8 | Parameters 9 | ---------- 10 | device_id : int, optional 11 | Device id. Default is -1. 12 | 13 | """ 14 | cdef libfreenect2.OpenCLPacketPipeline * pipeline 15 | 16 | def __cinit__(self, int device_id=-1): 17 | self.pipeline = new libfreenect2.OpenCLPacketPipeline(device_id) 18 | self.pipeline_ptr_alias = self.pipeline 19 | self.owned_by_device = False 20 | 21 | def __dealloc__(self): 22 | if not self.owned_by_device: 23 | if self.pipeline is not NULL: 24 | del self.pipeline 25 | -------------------------------------------------------------------------------- /pylibfreenect2/opengl_packet_pipeline.pxi: -------------------------------------------------------------------------------- 1 | cdef class OpenGLPacketPipeline(PacketPipeline): 2 | """Pipeline with OpenGL depth processing. 3 | 4 | Attributes 5 | ---------- 6 | pipeline : `libfreenect2::OpenGLPacketPipeline*` 7 | 8 | Parameters 9 | ---------- 10 | debug : bool, optional 11 | Debugging mode. Default is False. 12 | 13 | """ 14 | cdef libfreenect2.OpenGLPacketPipeline* pipeline 15 | 16 | def __cinit__(self, bool debug=False): 17 | self.pipeline = new libfreenect2.OpenGLPacketPipeline(NULL, debug) 18 | self.pipeline_ptr_alias = self.pipeline 19 | self.owned_by_device = False 20 | 21 | def __dealloc__(self): 22 | if not self.owned_by_device: 23 | if self.pipeline is not NULL: 24 | del self.pipeline 25 | -------------------------------------------------------------------------------- /pylibfreenect2/opencl_kde_packet_pipeline.pxi: -------------------------------------------------------------------------------- 1 | cdef class OpenCLKdePacketPipeline(PacketPipeline): 2 | """Depth packet processing pipeline using KDE depth unwrapping algorithms 3 | 4 | Attributes 5 | ---------- 6 | pipeline : `libfreenect2::OpenCLKdePacketPipeline*` 7 | 8 | Parameters 9 | ---------- 10 | device_id : int, optional 11 | Device id. Default is -1. 12 | 13 | References 14 | ---------- 15 | https://github.com/OpenKinect/libfreenect2/pull/742 16 | 17 | """ 18 | cdef libfreenect2.OpenCLKdePacketPipeline * pipeline 19 | 20 | def __cinit__(self, int device_id=-1): 21 | self.pipeline = new libfreenect2.OpenCLKdePacketPipeline(device_id) 22 | self.pipeline_ptr_alias = self.pipeline 23 | self.owned_by_device = False 24 | 25 | def __dealloc__(self): 26 | if not self.owned_by_device: 27 | if self.pipeline is not NULL: 28 | del self.pipeline 29 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. pylibfreenect2 documentation master file, created by 2 | sphinx-quickstart on Fri Sep 4 18:38:55 2015. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | pylibfreenect2 7 | ============== 8 | 9 | .. automodule:: pylibfreenect2 10 | 11 | Installation 12 | ************ 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | installation 18 | 19 | Getting Started 20 | *************** 21 | 22 | .. toctree:: 23 | :maxdepth: 1 24 | 25 | getstarted 26 | 27 | libfreenect2 documentation 28 | ************************** 29 | 30 | https://openkinect.github.io/libfreenect2/ 31 | 32 | Python API documentation 33 | ************************ 34 | 35 | .. toctree:: 36 | :maxdepth: 2 37 | 38 | api 39 | 40 | Developer Documentation 41 | *********************** 42 | 43 | .. toctree:: 44 | :maxdepth: 2 45 | 46 | dev 47 | 48 | Indices and tables 49 | ================== 50 | 51 | * :ref:`genindex` 52 | * :ref:`search` 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pylibfreenect2 2 | 3 | 4 | [![PyPI](https://img.shields.io/pypi/v/pylibfreenect2.svg)](https://pypi.python.org/pypi/pylibfreenect2) 5 | [![Build Status](https://travis-ci.org/r9y9/pylibfreenect2.svg?branch=master)](https://travis-ci.org/r9y9/pylibfreenect2) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/ntqppmboac6yti8s/branch/master?svg=true)](https://ci.appveyor.com/project/r9y9/pylibfreenect2/branch/master) 7 | [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) 8 | [![DOI](https://zenodo.org/badge/52707531.svg)](https://zenodo.org/badge/latestdoi/52707531) 9 | 10 | A python interface for [libfreenect2](https://github.com/OpenKinect/libfreenect2). The package is compatible with python 2.7-3.5. 11 | 12 | ## Documentation 13 | 14 | - [**STABLE**][docs-stable-url] — **most recently tagged version of the documentation.** 15 | - [**LATEST**][docs-latest-url] — *in-development version of the documentation.* 16 | 17 | [docs-latest-url]: http://r9y9.github.io/pylibfreenect2/latest/ 18 | [docs-stable-url]: http://r9y9.github.io/pylibfreenect2/stable/ 19 | 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The pylibfreenect2 package is licensed under the MIT "Expat" License: 2 | 3 | > Copyright (c) 2015: Ryuichi Yamamoto. 4 | > 5 | > Permission is hereby granted, free of charge, to any person obtaining 6 | > a copy of this software and associated documentation files (the 7 | > "Software"), to deal in the Software without restriction, including 8 | > without limitation the rights to use, copy, modify, merge, publish, 9 | > distribute, sublicense, and/or sell copies of the Software, and to 10 | > permit persons to whom the Software is furnished to do so, subject to 11 | > the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be 14 | > included in all copies or substantial portions of the Software. 15 | > 16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - PYTHON_VERSION: "3.5" 4 | PYTHON_ARCH: "64" 5 | MINICONDA: C:\Miniconda3-x64 6 | LIBFREENECT2_ARCHIVE_NAME: libfreenect2-0.2.0-libusbk-vs2015-x64 7 | LIBFREENECT2_VERSION: v0.2.0 8 | 9 | branches: 10 | only: 11 | - master 12 | - /release-.*/ 13 | 14 | skip_commits: 15 | message: /\[av skip\]/ 16 | 17 | notifications: 18 | - provider: Email 19 | on_build_success: false 20 | on_build_failure: false 21 | on_build_status_changed: false 22 | 23 | init: 24 | - "ECHO %PYTHON_VERSION% %PYTHON_ARCH% %MINICONDA%" 25 | 26 | install: 27 | - "SET PATH=%MINICONDA%;%MINICONDA%\\Scripts;%PATH%" 28 | - conda config --set always_yes yes --set changeps1 no 29 | - conda update -q conda 30 | - conda config --add channels pypi 31 | - conda info -a 32 | - "conda create -q -n test-environment python=%PYTHON_VERSION% numpy cython nose" 33 | - activate test-environment 34 | 35 | build_script: 36 | - set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% 37 | - set LIBFREENECT2_BIN=https://github.com/OpenKinect/libfreenect2/releases/download/%LIBFREENECT2_VERSION%/%LIBFREENECT2_ARCHIVE_NAME%.zip 38 | - curl -sLO %LIBFREENECT2_BIN% 39 | - 7z x %LIBFREENECT2_ARCHIVE_NAME%.zip 40 | - set LIBFREENECT2_INSTALL_PREFIX=C:\\projects\\pylibfreenect2\\%LIBFREENECT2_ARCHIVE_NAME% 41 | - set PATH=%LIBFREENECT2_INSTALL_PREFIX%\\bin;%PATH% 42 | - pip install -e . 43 | 44 | test_script: 45 | - nosetests -v -w tests -a "!require_device" 46 | 47 | after_test: 48 | - python setup.py bdist_wheel 49 | 50 | artifacts: 51 | - path: dist\* 52 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | Supported platforms 5 | ------------------- 6 | 7 | This package is tested with the following platforms: 8 | 9 | - Mac OS X 10.11.4 with clang (Apple LLVM version 7.3.0) (locally) 10 | - Ubuntu 14.04 with gcc 4.8.4 (Travis CI) 11 | - Windows with Visual Studio 2015 x64 (AppVeyor CI, only for python 3.5) 12 | 13 | Others might be supported, but not guaranteed yet. 14 | 15 | Build requirements 16 | ------------------ 17 | 18 | - `libfreenect2 `_ (0.2.0 or later) 19 | - python (2.7, 3.4 or 3.5) 20 | - numpy 21 | - cython 22 | - C++ compiler (clang, gcc or MSVC) 23 | 24 | Building pylibfreenect2 25 | ----------------------- 26 | 27 | The package requires libfreenect2 installed and its location in advance. Please make sure that: 28 | 29 | - You have installed `libfreenect2 `_ correctly and confirm that Protonect works. 30 | - You have set ``LIBFREENECT2_INSTALL_PREFIX`` environmental variable (default: ``/usr/local/``) and confirm that ``${LIBFREENECT2_INSTALL_PREFIX}include/libfreenect2/config.h`` exists. 31 | 32 | 33 | After that, you should be able to install pylibfreenect2 as follows: 34 | 35 | .. code:: 36 | 37 | pip install pylibfreenect2 38 | 39 | If you want the development version of pylibfreenect2, 40 | 41 | .. code:: 42 | 43 | pip install git+https://github.com/r9y9/pylibfreenect2 44 | 45 | or clone the repository and then: 46 | 47 | .. code:: 48 | 49 | python setup.py install 50 | 51 | This should resolve the package dependencies and install ``pylibfreenect2`` property. 52 | 53 | .. note:: 54 | If you have installed libfreenect2 in your custom path (e.g. ~/freenect2), 55 | make sure that the libfreenect2 shared library is in your library search 56 | path (``DYLD_LIBRARY_PATH`` for osx and ``LD_LIBRARY_PATH`` for linux). 57 | -------------------------------------------------------------------------------- /examples/selective_streams.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # An example using startStreams 4 | 5 | import numpy as np 6 | import cv2 7 | import sys 8 | from pylibfreenect2 import Freenect2, SyncMultiFrameListener 9 | from pylibfreenect2 import FrameType, Registration, Frame 10 | 11 | try: 12 | from pylibfreenect2 import OpenGLPacketPipeline 13 | pipeline = OpenGLPacketPipeline() 14 | except: 15 | try: 16 | from pylibfreenect2 import OpenCLPacketPipeline 17 | pipeline = OpenCLPacketPipeline() 18 | except: 19 | from pylibfreenect2 import CpuPacketPipeline 20 | pipeline = CpuPacketPipeline() 21 | print("Packet pipeline:", type(pipeline).__name__) 22 | 23 | enable_rgb = True 24 | enable_depth = True 25 | 26 | fn = Freenect2() 27 | num_devices = fn.enumerateDevices() 28 | if num_devices == 0: 29 | print("No device connected!") 30 | sys.exit(1) 31 | 32 | serial = fn.getDeviceSerialNumber(0) 33 | device = fn.openDevice(serial, pipeline=pipeline) 34 | 35 | types = 0 36 | if enable_rgb: 37 | types |= FrameType.Color 38 | if enable_depth: 39 | types |= (FrameType.Ir | FrameType.Depth) 40 | listener = SyncMultiFrameListener(types) 41 | 42 | # Register listeners 43 | device.setColorFrameListener(listener) 44 | device.setIrAndDepthFrameListener(listener) 45 | 46 | if enable_rgb and enable_depth: 47 | device.start() 48 | else: 49 | device.startStreams(rgb=enable_rgb, depth=enable_depth) 50 | 51 | # NOTE: must be called after device.start() 52 | if enable_depth: 53 | registration = Registration(device.getIrCameraParams(), 54 | device.getColorCameraParams()) 55 | 56 | undistorted = Frame(512, 424, 4) 57 | registered = Frame(512, 424, 4) 58 | 59 | while True: 60 | frames = listener.waitForNewFrame() 61 | 62 | if enable_rgb: 63 | color = frames["color"] 64 | if enable_depth: 65 | ir = frames["ir"] 66 | depth = frames["depth"] 67 | 68 | if enable_rgb and enable_depth: 69 | registration.apply(color, depth, undistorted, registered) 70 | elif enable_depth: 71 | registration.undistortDepth(depth, undistorted) 72 | 73 | if enable_depth: 74 | cv2.imshow("ir", ir.asarray() / 65535.) 75 | cv2.imshow("depth", depth.asarray() / 4500.) 76 | cv2.imshow("undistorted", undistorted.asarray(np.float32) / 4500.) 77 | if enable_rgb: 78 | cv2.imshow("color", cv2.resize(color.asarray(), 79 | (int(1920 / 3), int(1080 / 3)))) 80 | if enable_rgb and enable_depth: 81 | cv2.imshow("registered", registered.asarray(np.uint8)) 82 | 83 | listener.release(frames) 84 | 85 | key = cv2.waitKey(delay=1) 86 | if key == ord('q'): 87 | break 88 | 89 | device.stop() 90 | device.close() 91 | 92 | sys.exit(0) 93 | -------------------------------------------------------------------------------- /pylibfreenect2/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | """ 4 | A python interface for `libfreenect2 `_. 5 | 6 | https://github.com/r9y9/pylibfreenect2 7 | 8 | The package is compatible with python 2.7, 3.4 and 3.5. 9 | 10 | """ 11 | 12 | from __future__ import division, print_function, absolute_import 13 | 14 | import pkg_resources 15 | 16 | __version__ = pkg_resources.get_distribution('pylibfreenect2').version 17 | 18 | from enum import IntEnum 19 | 20 | 21 | class FrameType(IntEnum): 22 | """Python-side enum for ``libfreenect::Frame::Type`` in C++. 23 | 24 | The value can be Color, Ir or Depth. 25 | 26 | .. warning:: 27 | The name is slightly different between Python and C++ ( 28 | ``Frame::Type`` -> ``FrameType``). 29 | 30 | Examples 31 | -------- 32 | 33 | Suppose the following C++ code: 34 | 35 | .. code-block:: c++ 36 | 37 | libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color]; 38 | libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir]; 39 | libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth]; 40 | 41 | This can be translated in Python like: 42 | 43 | .. code-block:: python 44 | 45 | rgb = frames[pylibfreenect2.FrameType.Color] 46 | ir = frames[pylibfreenect2.FrameType.Ir] 47 | depth = frames[pylibfreenect2.FrameType.Depth] 48 | 49 | or you can use str key: 50 | 51 | .. code-block:: python 52 | 53 | rgb = frames["color"] 54 | ir = frames["ir"] 55 | depth = frames["depth"] 56 | 57 | See also 58 | -------- 59 | 60 | pylibfreenect2.libfreenect2.Frame 61 | pylibfreenect2.libfreenect2.FrameMap 62 | pylibfreenect2.libfreenect2.SyncMultiFrameListener 63 | 64 | """ 65 | Color = 1 66 | Ir = 2 67 | Depth = 4 68 | 69 | 70 | class LoggerLevel(IntEnum): 71 | """Python-side enum for ``libfreenect::Logger::Level`` in C++. 72 | 73 | .. warning:: 74 | The name is slightly different between Python and C++ ( 75 | ``Logger::Level`` -> ``LoggerLevel``). 76 | 77 | Examples 78 | -------- 79 | 80 | Suppose the following C++ code: 81 | 82 | .. code-block:: c++ 83 | 84 | libfreenect2::Logger* logger = libfreenect2::createConsoleLogger( 85 | libfreenect2::Logger::Level::Debug); 86 | 87 | 88 | This can be translated in Python like: 89 | 90 | .. code-block:: python 91 | 92 | logger = pylibfreenect2.createConsoleLogger( 93 | pylibfreenect2.LoggerLevel.Debug) 94 | 95 | 96 | See also 97 | -------- 98 | 99 | pylibfreenect2.libfreenect2.createConsoleLogger 100 | 101 | """ 102 | NONE = 0 103 | Error = 1 104 | Warning = 2 105 | Info = 3 106 | Debug = 4 107 | 108 | from .libfreenect2 import * 109 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | matrix: 4 | include: 5 | - os: linux 6 | sudo: required 7 | dist: trusty 8 | python: "2.7" 9 | env: LIBFREENECT2_VERSION="v0.2.0" 10 | 11 | - os: linux 12 | sudo: required 13 | dist: trusty 14 | python: "3.4" 15 | env: LIBFREENECT2_VERSION="v0.2.0" 16 | 17 | - os: linux 18 | sudo: required 19 | dist: trusty 20 | python: "3.5" 21 | env: LIBFREENECT2_VERSION="v0.2.0" 22 | 23 | - os: linux 24 | sudo: required 25 | dist: trusty 26 | python: "3.5" 27 | env: LIBFREENECT2_VERSION="master" 28 | # TODO: python for osx is not supported for now 29 | # ref: https://github.com/travis-ci/travis-ci/issues/4729 30 | # - os: osx 31 | # python: "2.7" 32 | 33 | notifications: 34 | email: false 35 | 36 | before_install: 37 | - cd $HOME 38 | - git clone https://github.com/OpenKinect/libfreenect2.git 39 | - cd libfreenect2 40 | - git checkout $LIBFREENECT2_VERSION 41 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then 42 | export LD_LIBRARY_PATH=/usr/local/lib 43 | sudo apt-get update; 44 | cd depends; 45 | ./download_debs_trusty.sh; 46 | sudo apt-get install -y build-essential cmake pkg-config; 47 | sudo dpkg -i debs/libusb*deb; 48 | sudo apt-get install -y libturbojpeg libjpeg-turbo8-dev; 49 | sudo apt-get install -y libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev; 50 | sudo dpkg -i debs/libglfw3*deb; 51 | sudo apt-get install -f; 52 | sudo apt-get install -y libgl1-mesa-dri-lts-vivid; 53 | MINICONDA_OSNAME="Linux"; 54 | elif [ "$TRAVIS_OS_NAME" == "osx" ]; then 55 | export DYLD_LIBRARY_PATH=/usr/local/lib 56 | brew update; 57 | brew install cmake pkg-config; 58 | brew install libusb; 59 | brew tap homebrew/versions; 60 | brew install glfw3; 61 | MINICONDA_OSNAME="MacOSX"; 62 | fi 63 | - cd $HOME/libfreenect2 64 | - mkdir build && cd build 65 | - cmake .. 66 | - make 67 | - sudo make install 68 | - if [["$TRAVIS_PYTHON_VERSION" == "2.7"]]; then 69 | wget http://repo.continuum.io/miniconda/Miniconda-3.8.3-$MINICONDA_OSNAME-x86_64.sh -O miniconda.sh; 70 | else 71 | wget http://repo.continuum.io/miniconda/Miniconda3-3.8.3-$MINICONDA_OSNAME-x86_64.sh -O miniconda.sh; 72 | fi 73 | - bash miniconda.sh -b -p $HOME/miniconda 74 | - export PATH="$HOME/miniconda/bin:$PATH" 75 | - conda config --set always_yes yes --set changeps1 no 76 | - conda update -q conda 77 | # Useful for debugging any issues with conda 78 | - conda config --add channels pypi 79 | - conda info -a 80 | - deps='numpy cython nose' 81 | - conda create -q -n test-environment "python=$TRAVIS_PYTHON_VERSION" $deps 82 | - source activate test-environment 83 | - cd $TRAVIS_BUILD_DIR 84 | 85 | install: 86 | - pip install -e . 87 | 88 | script: 89 | - nosetests -v -w tests/ -a '!require_device' 90 | -------------------------------------------------------------------------------- /examples/multiframe_listener.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | import numpy as np 4 | import cv2 5 | import sys 6 | from pylibfreenect2 import Freenect2, SyncMultiFrameListener 7 | from pylibfreenect2 import FrameType, Registration, Frame 8 | from pylibfreenect2 import createConsoleLogger, setGlobalLogger 9 | from pylibfreenect2 import LoggerLevel 10 | 11 | try: 12 | from pylibfreenect2 import OpenGLPacketPipeline 13 | pipeline = OpenGLPacketPipeline() 14 | except: 15 | try: 16 | from pylibfreenect2 import OpenCLPacketPipeline 17 | pipeline = OpenCLPacketPipeline() 18 | except: 19 | from pylibfreenect2 import CpuPacketPipeline 20 | pipeline = CpuPacketPipeline() 21 | print("Packet pipeline:", type(pipeline).__name__) 22 | 23 | # Create and set logger 24 | logger = createConsoleLogger(LoggerLevel.Debug) 25 | setGlobalLogger(logger) 26 | 27 | fn = Freenect2() 28 | num_devices = fn.enumerateDevices() 29 | if num_devices == 0: 30 | print("No device connected!") 31 | sys.exit(1) 32 | 33 | serial = fn.getDeviceSerialNumber(0) 34 | device = fn.openDevice(serial, pipeline=pipeline) 35 | 36 | listener = SyncMultiFrameListener( 37 | FrameType.Color | FrameType.Ir | FrameType.Depth) 38 | 39 | # Register listeners 40 | device.setColorFrameListener(listener) 41 | device.setIrAndDepthFrameListener(listener) 42 | 43 | device.start() 44 | 45 | # NOTE: must be called after device.start() 46 | registration = Registration(device.getIrCameraParams(), 47 | device.getColorCameraParams()) 48 | 49 | undistorted = Frame(512, 424, 4) 50 | registered = Frame(512, 424, 4) 51 | 52 | # Optinal parameters for registration 53 | # set True if you need 54 | need_bigdepth = False 55 | need_color_depth_map = False 56 | 57 | bigdepth = Frame(1920, 1082, 4) if need_bigdepth else None 58 | color_depth_map = np.zeros((424, 512), np.int32).ravel() \ 59 | if need_color_depth_map else None 60 | 61 | while True: 62 | frames = listener.waitForNewFrame() 63 | 64 | color = frames["color"] 65 | ir = frames["ir"] 66 | depth = frames["depth"] 67 | 68 | registration.apply(color, depth, undistorted, registered, 69 | bigdepth=bigdepth, 70 | color_depth_map=color_depth_map) 71 | 72 | # NOTE for visualization: 73 | # cv2.imshow without OpenGL backend seems to be quite slow to draw all 74 | # things below. Try commenting out some imshow if you don't have a fast 75 | # visualization backend. 76 | cv2.imshow("ir", ir.asarray() / 65535.) 77 | cv2.imshow("depth", depth.asarray() / 4500.) 78 | cv2.imshow("color", cv2.resize(color.asarray(), 79 | (int(1920 / 3), int(1080 / 3)))) 80 | cv2.imshow("registered", registered.asarray(np.uint8)) 81 | 82 | if need_bigdepth: 83 | cv2.imshow("bigdepth", cv2.resize(bigdepth.asarray(np.float32), 84 | (int(1920 / 3), int(1082 / 3)))) 85 | if need_color_depth_map: 86 | cv2.imshow("color_depth_map", color_depth_map.reshape(424, 512)) 87 | 88 | listener.release(frames) 89 | 90 | key = cv2.waitKey(delay=1) 91 | if key == ord('q'): 92 | break 93 | 94 | device.stop() 95 | device.close() 96 | 97 | sys.exit(0) 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pylibfreenect2/libfreenect2.cpp 2 | docs/generated 3 | 4 | # Created by https://www.gitignore.io 5 | 6 | ### Python ### 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | env/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | 56 | # Sphinx documentation 57 | docs/_build/ 58 | 59 | # PyBuilder 60 | target/ 61 | 62 | 63 | ### IPythonNotebook ### 64 | # Temporary data 65 | .ipynb_checkpoints/ 66 | 67 | 68 | ### SublimeText ### 69 | # cache files for sublime text 70 | *.tmlanguage.cache 71 | *.tmPreferences.cache 72 | *.stTheme.cache 73 | 74 | # workspace files are user-specific 75 | *.sublime-workspace 76 | 77 | # project files should be checked into the repository, unless a significant 78 | # proportion of contributors will probably not be using SublimeText 79 | # *.sublime-project 80 | 81 | # sftp configuration file 82 | sftp-config.json 83 | 84 | 85 | ### Emacs ### 86 | # -*- mode: gitignore; -*- 87 | *~ 88 | \#*\# 89 | /.emacs.desktop 90 | /.emacs.desktop.lock 91 | *.elc 92 | auto-save-list 93 | tramp 94 | .\#* 95 | 96 | # Org-mode 97 | .org-id-locations 98 | *_archive 99 | 100 | # flymake-mode 101 | *_flymake.* 102 | 103 | # eshell files 104 | /eshell/history 105 | /eshell/lastdir 106 | 107 | # elpa packages 108 | /elpa/ 109 | 110 | # reftex files 111 | *.rel 112 | 113 | # AUCTeX auto folder 114 | /auto/ 115 | 116 | # cask packages 117 | .cask/ 118 | 119 | 120 | ### Vim ### 121 | [._]*.s[a-w][a-z] 122 | [._]s[a-w][a-z] 123 | *.un~ 124 | Session.vim 125 | .netrwhist 126 | *~ 127 | 128 | 129 | ### C++ ### 130 | # Compiled Object files 131 | *.slo 132 | *.lo 133 | *.o 134 | *.obj 135 | 136 | # Precompiled Headers 137 | *.gch 138 | *.pch 139 | 140 | # Compiled Dynamic libraries 141 | *.so 142 | *.dylib 143 | *.dll 144 | 145 | # Fortran module files 146 | *.mod 147 | 148 | # Compiled Static libraries 149 | *.lai 150 | *.la 151 | *.a 152 | *.lib 153 | 154 | # Executables 155 | *.exe 156 | *.out 157 | *.app 158 | 159 | 160 | ### OSX ### 161 | .DS_Store 162 | .AppleDouble 163 | .LSOverride 164 | 165 | # Icon must end with two \r 166 | Icon 167 | 168 | 169 | # Thumbnails 170 | ._* 171 | 172 | # Files that might appear on external disk 173 | .Spotlight-V100 174 | .Trashes 175 | 176 | # Directories potentially created on remote AFP share 177 | .AppleDB 178 | .AppleDesktop 179 | Network Trash Folder 180 | Temporary Items 181 | .apdisk 182 | 183 | 184 | ### Linux ### 185 | *~ 186 | 187 | # KDE directory preferences 188 | .directory 189 | 190 | # Linux trash folder which might appear on any partition or disk 191 | .Trash-* 192 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from __future__ import with_statement, print_function, absolute_import 4 | 5 | from setuptools import setup, find_packages, Extension 6 | from distutils.version import LooseVersion 7 | 8 | import platform 9 | 10 | import numpy as np 11 | import os 12 | from os.path import join, exists 13 | from subprocess import Popen, PIPE 14 | import sys 15 | 16 | libfreenect2_install_prefix = os.environ.get( 17 | "LIBFREENECT2_INSTALL_PREFIX", "/usr/local/") 18 | 19 | libfreenect2_include_top = join(libfreenect2_install_prefix, "include") 20 | libfreenect2_library_path = join(libfreenect2_install_prefix, "lib") 21 | libfreenect2_configh_path = join( 22 | libfreenect2_include_top, "libfreenect2", "config.h") 23 | 24 | if not exists(libfreenect2_configh_path): 25 | raise OSError("{}: is not found".format(libfreenect2_configh_path)) 26 | 27 | if platform.system() == "Windows": 28 | lib_candidates = list(filter(lambda l: l.startswith("freenect2."), 29 | os.listdir(join(libfreenect2_library_path)))) 30 | else: 31 | lib_candidates = list(filter(lambda l: l.startswith("libfreenect2."), 32 | os.listdir(join(libfreenect2_library_path)))) 33 | 34 | if len(lib_candidates) == 0: 35 | raise OSError("libfreenect2 library cannot be found") 36 | 37 | min_cython_ver = '0.21.0' 38 | try: 39 | import Cython 40 | ver = Cython.__version__ 41 | _CYTHON_INSTALLED = ver >= LooseVersion(min_cython_ver) 42 | except ImportError: 43 | _CYTHON_INSTALLED = False 44 | 45 | try: 46 | if not _CYTHON_INSTALLED: 47 | raise ImportError('No supported version of Cython installed.') 48 | from Cython.Distutils import build_ext 49 | from Cython.Build import cythonize 50 | cython = True 51 | except ImportError: 52 | cython = False 53 | 54 | if cython: 55 | ext = '.pyx' 56 | cmdclass = {'build_ext': build_ext} 57 | else: 58 | ext = '.cpp' 59 | cmdclass = {} 60 | if not os.path.exists(join("pylibfreenect2", "libfreenect2" + ext)): 61 | raise RuntimeError("Cython is required to generate C++ codes.") 62 | 63 | 64 | def has_define_in_config(key, close_fds=None): 65 | if close_fds is None: 66 | if platform.system() == "Windows": 67 | close_fds = False 68 | else: 69 | close_fds = True 70 | 71 | if platform.system() == "Windows": 72 | lines = [] 73 | with open(libfreenect2_configh_path, 'r') as f: 74 | for line in f: 75 | if key in line: 76 | lines.append(line) 77 | else: 78 | p = Popen("cat {0} | grep {1}".format(libfreenect2_configh_path, key), 79 | stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=close_fds, shell=True) 80 | p.wait() 81 | lines = p.stdout.readlines() 82 | 83 | if sys.version_info.major >= 3 and not platform.system() == "Windows": 84 | return len(lines) == 1 and lines[0].startswith(b"#define") 85 | else: 86 | return len(lines) == 1 and lines[0].startswith("#define") 87 | 88 | 89 | if platform.system() == "Darwin": 90 | extra_compile_args = ["-std=c++11", "-stdlib=libc++", 91 | "-mmacosx-version-min=10.8"] 92 | else: 93 | # should work with Ubuntu 14.04 with anaconda python3 instaleld 94 | extra_compile_args = ["-std=c++11"] 95 | 96 | ext_modules = cythonize( 97 | [Extension( 98 | name="pylibfreenect2.libfreenect2", 99 | sources=[ 100 | join("pylibfreenect2", "libfreenect2" + ext), 101 | ], 102 | include_dirs=[np.get_include(), 103 | join(libfreenect2_include_top)], 104 | library_dirs=[libfreenect2_library_path], 105 | libraries=["freenect2"], 106 | extra_compile_args=extra_compile_args, 107 | extra_link_args=[], 108 | language="c++")], 109 | compile_time_env={ 110 | "LIBFREENECT2_WITH_OPENGL_SUPPORT": 111 | has_define_in_config("LIBFREENECT2_WITH_OPENGL_SUPPORT"), 112 | "LIBFREENECT2_WITH_OPENCL_SUPPORT": 113 | has_define_in_config("LIBFREENECT2_WITH_OPENCL_SUPPORT"), 114 | "LIBFREENECT2_WITH_CUDA_SUPPORT": 115 | has_define_in_config("LIBFREENECT2_WITH_CUDA_SUPPORT"), 116 | } 117 | ) 118 | 119 | install_requires = ['numpy >= 1.7.0'] 120 | if sys.version_info < (3, 4): 121 | install_requires.append('enum34') 122 | 123 | setup( 124 | name='pylibfreenect2', 125 | version='0.1.5-dev', 126 | description='A python interface for libfreenect2', 127 | author='Ryuichi Yamamoto', 128 | author_email='zryuichi@gmail.com', 129 | url='https://github.com/r9y9/pylibfreenect2', 130 | license='MIT', 131 | packages=find_packages(), 132 | ext_modules=ext_modules, 133 | cmdclass=cmdclass, 134 | install_requires=install_requires, 135 | tests_require=['nose', 'coverage'], 136 | extras_require={ 137 | 'docs': ['numpydoc', 'sphinx_rtd_theme', 'seaborn'], 138 | 'test': ['nose'], 139 | 'develop': ['cython >= ' + min_cython_ver], 140 | }, 141 | classifiers=[ 142 | "Operating System :: POSIX", 143 | "Operating System :: Unix", 144 | "Operating System :: MacOS", 145 | "Programming Language :: Cython", 146 | "Programming Language :: Python", 147 | "Programming Language :: Python :: 2", 148 | "Programming Language :: Python :: 2.7", 149 | "Programming Language :: Python :: 3", 150 | "Programming Language :: Python :: 3.4", 151 | "Programming Language :: Python :: 3.5", 152 | "License :: OSI Approved :: MIT License", 153 | "Topic :: Scientific/Engineering", 154 | "Topic :: Software Development", 155 | "Intended Audience :: Science/Research", 156 | "Intended Audience :: Developers", 157 | ], 158 | keywords=["pylibfreenect2", "libfreenect2", "freenect2"] 159 | ) 160 | -------------------------------------------------------------------------------- /pylibfreenect2/libfreenect2/libfreenect2.pxd: -------------------------------------------------------------------------------- 1 | # distutils: language = c++ 2 | 3 | """ 4 | libfreenect2 cdef externs 5 | """ 6 | 7 | from libc.stdint cimport uint32_t 8 | from libcpp cimport bool 9 | from libcpp.string cimport string 10 | from libcpp.map cimport map 11 | 12 | 13 | cdef extern from "libfreenect2/frame_listener.hpp" namespace "libfreenect2": 14 | # ugly but works 15 | cdef enum LibFreenect2FrameType "libfreenect2::Frame::Type": 16 | Color "libfreenect2::Frame::Type::Color" 17 | Ir "libfreenect2::Frame::Type::Ir" 18 | Depth "libfreenect2::Frame::Type::Depth" 19 | 20 | cdef cppclass Frame: 21 | uint32_t timestamp 22 | uint32_t sequence 23 | size_t width 24 | size_t height 25 | size_t bytes_per_pixel 26 | unsigned char* data 27 | float exposure 28 | float gain 29 | float gamma 30 | 31 | Frame(size_t width, size_t height, size_t bytes_per_pixel, unsigned char*) except + 32 | 33 | cdef cppclass FrameListener: 34 | bool onNewFrame(int, Frame*) 35 | 36 | cdef extern from "libfreenect2/frame_listener_impl.h" namespace "libfreenect2": 37 | cdef cppclass SyncMultiFrameListener: 38 | SyncMultiFrameListener(unsigned int) 39 | 40 | bool hasNewFrame() 41 | void waitForNewFrame(map[LibFreenect2FrameType, Frame*]&) nogil 42 | bool waitForNewFrame(map[LibFreenect2FrameType, Frame*]&, int milliseconds) nogil 43 | void release(map[LibFreenect2FrameType, Frame*]&) 44 | 45 | cdef extern from "libfreenect2/libfreenect2.hpp" namespace "libfreenect2": 46 | cdef cppclass Freenect2Device: 47 | unsigned int VendorId 48 | unsigned int ProductId 49 | unsigned int ProductIdPreview 50 | 51 | string getSerialNumber() 52 | string getFirmwareVersion() 53 | 54 | cppclass ColorCameraParams: 55 | float fx, fy, cx, cy 56 | 57 | float shift_d, shift_m 58 | 59 | float mx_x3y0 60 | float mx_x0y3 61 | float mx_x2y1 62 | float mx_x1y2 63 | float mx_x2y0 64 | float mx_x0y2 65 | float mx_x1y1 66 | float mx_x1y0 67 | float mx_x0y1 68 | float mx_x0y0 69 | 70 | float my_x3y0 71 | float my_x0y3 72 | float my_x2y1 73 | float my_x1y2 74 | float my_x2y0 75 | float my_x0y2 76 | float my_x1y1 77 | float my_x1y0 78 | float my_x0y1 79 | float my_x0y0 80 | 81 | cppclass IrCameraParams: 82 | float fx, fy, cx, cy, k1, k2, k3, p1, p2 83 | 84 | ColorCameraParams getColorCameraParams() 85 | IrCameraParams getIrCameraParams() 86 | 87 | # void setColorCameraParams(ColorCameraParams &) 88 | # void setIrCameraParams(const Freenect2Device::IrCameraParams &) 89 | 90 | void setColorFrameListener(FrameListener*) 91 | void setIrAndDepthFrameListener(FrameListener*) 92 | 93 | void start() 94 | bool startStreams(bool, bool) 95 | void stop() 96 | void close() 97 | 98 | cdef extern from "libfreenect2/registration.h" namespace "libfreenect2": 99 | cdef cppclass Registration: 100 | Registration(Freenect2Device.IrCameraParams, Freenect2Device.ColorCameraParams) except + 101 | 102 | # undistort/register a whole image 103 | void apply(const Frame*, const Frame*, Frame*, Frame*, const bool, Frame*, int*) const 104 | 105 | void undistortDepth(const Frame*, Frame*) 106 | 107 | # construct a 3-D point with color in a point cloud 108 | void getPointXYZRGB(const Frame*, const Frame*, int, int, float&, float&, float&, float&) const 109 | 110 | # construct a 3-D point in a point cloud 111 | void getPointXYZ(const Frame*, int, int, float&, float&, float&) const 112 | 113 | 114 | cdef extern from "libfreenect2/packet_pipeline.h" namespace "libfreenect2": 115 | cdef cppclass PacketPipeline: 116 | PacketPipeline *getRgbPacketParser() const 117 | PacketPipeline *getIrPacketParser() const 118 | 119 | cdef cppclass CpuPacketPipeline: 120 | CpuPacketPipeline() 121 | 122 | cdef cppclass OpenGLPacketPipeline: 123 | OpenGLPacketPipeline(void*, bool) 124 | 125 | cdef cppclass OpenCLPacketPipeline: 126 | OpenCLPacketPipeline(const int) 127 | 128 | cdef cppclass OpenCLKdePacketPipeline: 129 | OpenCLKdePacketPipeline(const int) 130 | 131 | cdef cppclass CudaPacketPipeline: 132 | CudaPacketPipeline(const int) 133 | 134 | 135 | cdef extern from "libfreenect2/libfreenect2.hpp" namespace "libfreenect2": 136 | cdef cppclass Freenect2: 137 | Freenect2() except + 138 | 139 | int enumerateDevices() 140 | 141 | string getDeviceSerialNumber(int) 142 | string getDefaultDeviceSerialNumber() 143 | 144 | Freenect2Device *openDevice(int) 145 | Freenect2Device *openDevice(int idx, const PacketPipeline *) 146 | Freenect2Device *openDevice(const string &) 147 | Freenect2Device *openDevice(const string &, const PacketPipeline *) 148 | 149 | Freenect2Device *openDefaultDevice() 150 | Freenect2Device *openDefaultDevice(const PacketPipeline *) 151 | 152 | cdef extern from "libfreenect2/logger.h" namespace "libfreenect2": 153 | # ugly but works 154 | cdef enum LoggerLevel "libfreenect2::Logger::Level": 155 | None "libfreenect2::Logger::Level::None" 156 | Error "libfreenect2::Logger::Level::Error" 157 | Warning "libfreenect2::Logger::Level::Warning" 158 | Info "libfreenect2::Logger::Level::Info" 159 | Debug "libfreenect2::Logger::Level::Debug" 160 | 161 | cdef cppclass Logger: 162 | LoggerLevel level() const 163 | void log(LoggerLevel, const string &) 164 | 165 | Logger* createConsoleLogger(LoggerLevel) 166 | Logger* createConsoleLoggerWithDefaultLevel() 167 | Logger* getGlobalLogger() 168 | void setGlobalLogger(Logger *logger) 169 | -------------------------------------------------------------------------------- /tests/test_libfreenect2.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | import numpy as np 4 | import sys 5 | 6 | from nose.tools import raises 7 | from nose.plugins.attrib import attr 8 | 9 | from pylibfreenect2 import Freenect2, SyncMultiFrameListener 10 | from pylibfreenect2 import FrameType, Registration, Frame, FrameMap 11 | from pylibfreenect2 import (Logger, 12 | createConsoleLogger, 13 | createConsoleLoggerWithDefaultLevel, 14 | getGlobalLogger, 15 | setGlobalLogger, 16 | LoggerLevel) 17 | 18 | 19 | def test_frame(): 20 | frame = Frame(512, 424, 4) 21 | assert frame.width == 512 22 | assert frame.height == 424 23 | assert frame.bytes_per_pixel == 4 24 | assert frame.exposure == 0 25 | assert frame.gain == 0 26 | assert frame.gamma == 0 27 | 28 | 29 | def test_logger(): 30 | logger_default = createConsoleLoggerWithDefaultLevel() 31 | assert isinstance(logger_default, Logger) 32 | 33 | for level in [LoggerLevel.NONE, LoggerLevel.Error, 34 | LoggerLevel.Warning, 35 | LoggerLevel.Info, 36 | LoggerLevel.Debug]: 37 | logger = createConsoleLogger(level) 38 | setGlobalLogger(logger) 39 | assert getGlobalLogger().level() == level 40 | 41 | # Turn logging off 42 | setGlobalLogger(None) 43 | # Set to default 44 | setGlobalLogger(logger_default) 45 | 46 | logger = getGlobalLogger() 47 | if sys.version_info.major >= 3: 48 | message = b"test debugging message" 49 | else: 50 | message = "test debugging message" 51 | logger.log(LoggerLevel.Debug, message) 52 | 53 | 54 | def test_enumerateDevices(): 55 | fn = Freenect2() 56 | fn.enumerateDevices() 57 | 58 | 59 | @attr('require_device') 60 | def test_openDefaultDevice(): 61 | fn = Freenect2() 62 | 63 | num_devices = fn.enumerateDevices() 64 | assert num_devices > 0 65 | 66 | device = fn.openDefaultDevice() 67 | 68 | device.stop() 69 | device.close() 70 | 71 | 72 | @attr('require_device') 73 | def test_startStreams(): 74 | def __test(enable_rgb, enable_depth): 75 | fn = Freenect2() 76 | num_devices = fn.enumerateDevices() 77 | assert num_devices > 0 78 | device = fn.openDefaultDevice() 79 | 80 | types = 0 81 | if enable_rgb: 82 | types |= FrameType.Color 83 | if enable_depth: 84 | types |= (FrameType.Ir | FrameType.Depth) 85 | listener = SyncMultiFrameListener(types) 86 | 87 | device.setColorFrameListener(listener) 88 | device.setIrAndDepthFrameListener(listener) 89 | 90 | device.startStreams(rgb=enable_rgb, depth=enable_depth) 91 | # test if we can get one frame at least 92 | frames = listener.waitForNewFrame() 93 | listener.release(frames) 94 | 95 | device.stop() 96 | device.close() 97 | 98 | __test(True, False) 99 | __test(False, True) 100 | 101 | 102 | @attr('require_device') 103 | def test_sync_multi_frame(): 104 | fn = Freenect2() 105 | 106 | num_devices = fn.enumerateDevices() 107 | assert num_devices > 0 108 | 109 | serial = fn.getDefaultDeviceSerialNumber() 110 | assert serial == fn.getDeviceSerialNumber(0) 111 | 112 | device = fn.openDevice(serial) 113 | 114 | assert fn.getDefaultDeviceSerialNumber() == device.getSerialNumber() 115 | device.getFirmwareVersion() 116 | 117 | listener = SyncMultiFrameListener( 118 | FrameType.Color | FrameType.Ir | FrameType.Depth) 119 | 120 | # Register listeners 121 | device.setColorFrameListener(listener) 122 | device.setIrAndDepthFrameListener(listener) 123 | 124 | device.start() 125 | 126 | # Registration 127 | registration = Registration(device.getIrCameraParams(), 128 | device.getColorCameraParams()) 129 | undistorted = Frame(512, 424, 4) 130 | registered = Frame(512, 424, 4) 131 | 132 | # optional parameters for registration 133 | bigdepth = Frame(1920, 1082, 4) 134 | color_depth_map = np.zeros((424, 512), np.int32) 135 | 136 | # test if we can get two frames at least 137 | frames = listener.waitForNewFrame() 138 | listener.release(frames) 139 | 140 | # frames as a first argment also should work 141 | frames = FrameMap() 142 | listener.waitForNewFrame(frames) 143 | 144 | color = frames[FrameType.Color] 145 | ir = frames[FrameType.Ir] 146 | depth = frames[FrameType.Depth] 147 | 148 | for frame in [ir, depth]: 149 | assert frame.exposure == 0 150 | assert frame.gain == 0 151 | assert frame.gamma == 0 152 | 153 | for frame in [color]: 154 | assert frame.exposure > 0 155 | assert frame.gain > 0 156 | assert frame.gamma > 0 157 | 158 | registration.apply(color, depth, undistorted, registered) 159 | 160 | # with optinal parameters 161 | registration.apply(color, depth, undistorted, registered, 162 | bigdepth=bigdepth, 163 | color_depth_map=color_depth_map.ravel()) 164 | 165 | registration.undistortDepth(depth, undistorted) 166 | 167 | assert color.width == 1920 168 | assert color.height == 1080 169 | assert color.bytes_per_pixel == 4 170 | 171 | assert ir.width == 512 172 | assert ir.height == 424 173 | assert ir.bytes_per_pixel == 4 174 | 175 | assert depth.width == 512 176 | assert depth.height == 424 177 | assert depth.bytes_per_pixel == 4 178 | 179 | assert color.asarray().shape == (color.height, color.width, 4) 180 | assert ir.asarray().shape == (ir.height, ir.width) 181 | assert depth.asarray(np.float32).shape == (depth.height, depth.width) 182 | 183 | listener.release(frames) 184 | 185 | def __test_cannot_determine_type_of_frame(frame): 186 | frame.asarray() 187 | 188 | for frame in [registered, undistorted]: 189 | yield raises(ValueError)(__test_cannot_determine_type_of_frame), frame 190 | 191 | # getPointXYZ 192 | x, y, z = registration.getPointXYZ(undistorted, 512 // 2, 424 // 2) 193 | if not np.isnan([x, y, z]).any(): 194 | assert z > 0 195 | 196 | # getPointXYZRGB 197 | x, y, z, b, g, r = registration.getPointXYZRGB(undistorted, registered, 198 | 512 // 2, 424 // 2) 199 | if not np.isnan([x, y, z]).any(): 200 | assert z > 0 201 | assert np.isfinite([b, g, r]).all() 202 | 203 | for pix in [b, g, r]: 204 | assert pix >= 0 and pix <= 255 205 | 206 | device.stop() 207 | device.close() 208 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pysptk.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pysptk.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/pysptk" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pysptk" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # pylibfreenect2 documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Sep 4 18:38:55 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import pkg_resources 16 | import os 17 | 18 | __version__ = pkg_resources.get_distribution('pylibfreenect2').version 19 | 20 | # If extensions (or modules to document with autodoc) are in another directory, 21 | # add these directories to sys.path here. If the directory is relative to the 22 | # documentation root, use os.path.abspath to make it absolute, like shown here. 23 | #sys.path.insert(0, os.path.abspath('.')) 24 | 25 | ON_RTD = os.environ.get('READTHEDOCS', None) == 'True' 26 | 27 | # -- General configuration ------------------------------------------------ 28 | 29 | # If your documentation needs a minimal Sphinx version, state it here. 30 | #needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = [ 36 | 'sphinx.ext.autodoc', 37 | 'sphinx.ext.autosummary', 38 | 'sphinx.ext.doctest', 39 | 'sphinx.ext.mathjax', 40 | 'sphinx.ext.viewcode', 41 | 'numpydoc', 42 | 'matplotlib.sphinxext.plot_directive', 43 | ] 44 | 45 | if ON_RTD: 46 | # Remove extensions not currently supported on RTD 47 | extensions.remove('matplotlib.sphinxext.plot_directive') 48 | 49 | autosummary_generate = True 50 | numpydoc_show_class_members = False 51 | 52 | # Most of plotting settings are copy and pasted from librosa 53 | # https://github.com/bmcfee/librosa 54 | 55 | if not ON_RTD: 56 | # Determine if the matplotlib has a recent enough version of the 57 | # plot_directive. 58 | try: 59 | from matplotlib.sphinxext import plot_directive 60 | except ImportError: 61 | use_matplotlib_plot_directive = False 62 | else: 63 | try: 64 | print("plot_directive.__version__:", plot_directive.__version__) 65 | use_matplotlib_plot_directive = (plot_directive.__version__ >= 2) 66 | except AttributeError: 67 | use_matplotlib_plot_directive = False 68 | 69 | if use_matplotlib_plot_directive: 70 | extensions.append('matplotlib.sphinxext.plot_directive') 71 | else: 72 | raise RuntimeError("You need a recent enough version of matplotlib") 73 | 74 | #------------------------------------------------------------------------------ 75 | # Plot 76 | #------------------------------------------------------------------------------ 77 | plot_pre_code = """ 78 | import seaborn 79 | seaborn.set(style='ticks') 80 | import numpy as np 81 | import pylibfreenect2 82 | np.random.seed(123) 83 | np.set_printoptions(precision=3, linewidth=64, edgeitems=2, threshold=200) 84 | """ 85 | plot_include_source = True 86 | plot_formats = [('png', 96), 'pdf'] 87 | plot_html_show_formats = False 88 | 89 | font_size = 13 * 72 / 96.0 # 13 px 90 | 91 | plot_rcparams = { 92 | 'font.size': font_size, 93 | 'axes.titlesize': font_size, 94 | 'axes.labelsize': font_size, 95 | 'xtick.labelsize': font_size, 96 | 'ytick.labelsize': font_size, 97 | 'legend.fontsize': font_size, 98 | 'figure.subplot.bottom': 0.2, 99 | 'figure.subplot.left': 0.2, 100 | 'figure.subplot.right': 0.9, 101 | 'figure.subplot.top': 0.85, 102 | 'figure.subplot.wspace': 0.4, 103 | 'text.usetex': False, 104 | } 105 | 106 | if not ON_RTD: 107 | import matplotlib 108 | matplotlib.rcParams.update(plot_rcparams) 109 | 110 | 111 | # Generate plots for example sections 112 | numpydoc_use_plots = True 113 | 114 | # Add any paths that contain templates here, relative to this directory. 115 | templates_path = ['_templates'] 116 | 117 | # The suffix(es) of source filenames. 118 | # You can specify multiple suffix as a list of string: 119 | # source_suffix = ['.rst', '.md'] 120 | source_suffix = '.rst' 121 | 122 | # The encoding of source files. 123 | #source_encoding = 'utf-8-sig' 124 | 125 | # The master toctree document. 126 | master_doc = 'index' 127 | 128 | # General information about the project. 129 | project = u'pylibfreenect2' 130 | copyright = u'2016, Ryuichi YAMAMOTO' 131 | author = u'Ryuichi YAMAMOTO' 132 | 133 | # The version info for the project you're documenting, acts as replacement for 134 | # |version| and |release|, also used in various other places throughout the 135 | # built documents. 136 | # 137 | # The short X.Y version. 138 | version = __version__ 139 | # The full version, including alpha/beta/rc tags. 140 | release = __version__ 141 | 142 | # The language for content autogenerated by Sphinx. Refer to documentation 143 | # for a list of supported languages. 144 | # 145 | # This is also used if you do content translation via gettext catalogs. 146 | # Usually you set "language" from the command line for these cases. 147 | language = None 148 | 149 | # There are two options for replacing |today|: either, you set today to some 150 | # non-false value, then it is used: 151 | #today = '' 152 | # Else, today_fmt is used as the format for a strftime call. 153 | #today_fmt = '%B %d, %Y' 154 | 155 | # List of patterns, relative to source directory, that match files and 156 | # directories to ignore when looking for source files. 157 | exclude_patterns = ['_build'] 158 | 159 | # The reST default role (used for this markup: `text`) to use for all 160 | # documents. 161 | #default_role = None 162 | 163 | # If true, '()' will be appended to :func: etc. cross-reference text. 164 | #add_function_parentheses = True 165 | 166 | # If true, the current module name will be prepended to all description 167 | # unit titles (such as .. function::). 168 | #add_module_names = True 169 | 170 | # If true, sectionauthor and moduleauthor directives will be shown in the 171 | # output. They are ignored by default. 172 | #show_authors = False 173 | 174 | # The name of the Pygments (syntax highlighting) style to use. 175 | pygments_style = 'sphinx' 176 | 177 | # A list of ignored prefixes for module index sorting. 178 | #modindex_common_prefix = [] 179 | 180 | # If true, keep warnings as "system message" paragraphs in the built documents. 181 | #keep_warnings = False 182 | 183 | # If true, `todo` and `todoList` produce output, else they produce nothing. 184 | todo_include_todos = False 185 | 186 | 187 | # -- Options for HTML output ---------------------------------------------- 188 | 189 | # The theme to use for HTML and HTML Help pages. See the documentation for 190 | # a list of builtin themes. 191 | html_theme = 'sphinx_rtd_theme' 192 | 193 | # Theme options are theme-specific and customize the look and feel of a theme 194 | # further. For a list of options available for each theme, see the 195 | # documentation. 196 | #html_theme_options = {} 197 | 198 | # Add any paths that contain custom themes here, relative to this directory. 199 | #html_theme_path = [] 200 | 201 | # The name for this set of Sphinx documents. If None, it defaults to 202 | # " v documentation". 203 | #html_title = None 204 | 205 | # A shorter title for the navigation bar. Default is the same as html_title. 206 | #html_short_title = None 207 | 208 | # The name of an image file (relative to this directory) to place at the top 209 | # of the sidebar. 210 | #html_logo = None 211 | 212 | # The name of an image file (within the static path) to use as favicon of the 213 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 214 | # pixels large. 215 | #html_favicon = None 216 | 217 | # Add any paths that contain custom static files (such as style sheets) here, 218 | # relative to this directory. They are copied after the builtin static files, 219 | # so a file named "default.css" will overwrite the builtin "default.css". 220 | html_static_path = ['_static'] 221 | 222 | # Add any extra paths that contain custom files (such as robots.txt or 223 | # .htaccess) here, relative to this directory. These files are copied 224 | # directly to the root of the documentation. 225 | #html_extra_path = [] 226 | 227 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 228 | # using the given strftime format. 229 | #html_last_updated_fmt = '%b %d, %Y' 230 | 231 | # If true, SmartyPants will be used to convert quotes and dashes to 232 | # typographically correct entities. 233 | #html_use_smartypants = True 234 | 235 | # Custom sidebar templates, maps document names to template names. 236 | #html_sidebars = {} 237 | 238 | # Additional templates that should be rendered to pages, maps page names to 239 | # template names. 240 | #html_additional_pages = {} 241 | 242 | # If false, no module index is generated. 243 | #html_domain_indices = True 244 | 245 | # If false, no index is generated. 246 | #html_use_index = True 247 | 248 | # If true, the index is split into individual pages for each letter. 249 | #html_split_index = False 250 | 251 | # If true, links to the reST sources are added to the pages. 252 | #html_show_sourcelink = True 253 | 254 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 255 | #html_show_sphinx = True 256 | 257 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 258 | #html_show_copyright = True 259 | 260 | # If true, an OpenSearch description file will be output, and all pages will 261 | # contain a tag referring to it. The value of this option must be the 262 | # base URL from which the finished HTML is served. 263 | #html_use_opensearch = '' 264 | 265 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 266 | #html_file_suffix = None 267 | 268 | # Language to be used for generating the HTML full-text search index. 269 | # Sphinx supports the following languages: 270 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 271 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' 272 | #html_search_language = 'en' 273 | 274 | # A dictionary with options for the search language support, empty by default. 275 | # Now only 'ja' uses this config value 276 | #html_search_options = {'type': 'default'} 277 | 278 | # The name of a javascript file (relative to the configuration directory) that 279 | # implements a search results scorer. If empty, the default will be used. 280 | #html_search_scorer = 'scorer.js' 281 | 282 | # Output file base name for HTML help builder. 283 | htmlhelp_basename = 'pypylibfreenect2doc' 284 | 285 | # -- Options for LaTeX output --------------------------------------------- 286 | 287 | latex_elements = { 288 | # The paper size ('letterpaper' or 'a4paper'). 289 | #'papersize': 'letterpaper', 290 | 291 | # The font size ('10pt', '11pt' or '12pt'). 292 | #'pointsize': '10pt', 293 | 294 | # Additional stuff for the LaTeX preamble. 295 | #'preamble': '', 296 | 297 | # Latex figure (float) alignment 298 | #'figure_align': 'htbp', 299 | } 300 | 301 | # Grouping the document tree into LaTeX files. List of tuples 302 | # (source start file, target name, title, 303 | # author, documentclass [howto, manual, or own class]). 304 | latex_documents = [ 305 | (master_doc, 'pylibfreenect2.tex', u'pylibfreenect2 Documentation', 306 | u'Ryuichi YAMAMOTO', 'manual'), 307 | ] 308 | 309 | # The name of an image file (relative to this directory) to place at the top of 310 | # the title page. 311 | #latex_logo = None 312 | 313 | # For "manual" documents, if this is true, then toplevel headings are parts, 314 | # not chapters. 315 | #latex_use_parts = False 316 | 317 | # If true, show page references after internal links. 318 | #latex_show_pagerefs = False 319 | 320 | # If true, show URL addresses after external links. 321 | #latex_show_urls = False 322 | 323 | # Documents to append as an appendix to all manuals. 324 | #latex_appendices = [] 325 | 326 | # If false, no module index is generated. 327 | #latex_domain_indices = True 328 | 329 | 330 | # -- Options for manual page output --------------------------------------- 331 | 332 | # One entry per manual page. List of tuples 333 | # (source start file, name, description, authors, manual section). 334 | man_pages = [ 335 | (master_doc, 'pylibfreenect2', u'pylibfreenect2 Documentation', 336 | [author], 1) 337 | ] 338 | 339 | # If true, show URL addresses after external links. 340 | #man_show_urls = False 341 | 342 | 343 | # -- Options for Texinfo output ------------------------------------------- 344 | 345 | # Grouping the document tree into Texinfo files. List of tuples 346 | # (source start file, target name, title, author, 347 | # dir menu entry, description, category) 348 | texinfo_documents = [ 349 | (master_doc, 'pylibfreenect2', u'pylibfreenect2 Documentation', 350 | author, 'pylibfreenect2', 'One line description of project.', 351 | 'Miscellaneous'), 352 | ] 353 | 354 | # Documents to append as an appendix to all manuals. 355 | #texinfo_appendices = [] 356 | 357 | # If false, no module index is generated. 358 | #texinfo_domain_indices = True 359 | 360 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 361 | #texinfo_show_urls = 'footnote' 362 | 363 | # If true, do not generate a @detailmenu in the "Top" node's menu. 364 | #texinfo_no_detailmenu = False 365 | -------------------------------------------------------------------------------- /pylibfreenect2/libfreenect2.pyx: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # cython: boundscheck=True, wraparound=True 3 | 4 | """ 5 | API 6 | === 7 | 8 | .. important:: 9 | Python API's are designed to minimize differences in C++ and Python; i.e. all 10 | classes and methods should have the same name; function signatures should 11 | also be same as possible. For the slight differences, see below in details. 12 | 13 | 14 | All functionality in ``pylibfreenect2.libfreenect2`` is directly accesible from 15 | the top-level ``pylibfreenect2.*`` namespace. 16 | 17 | The sections below are organized by following 18 | `the offical docs `_. 19 | 20 | 21 | Frame Listeners 22 | --------------- 23 | 24 | FrameType 25 | ^^^^^^^^^ 26 | 27 | .. autoclass:: pylibfreenect2.FrameType 28 | :members: 29 | 30 | Frame 31 | ^^^^^ 32 | 33 | .. autoclass:: Frame 34 | :members: 35 | 36 | FrameMap 37 | ^^^^^^^^ 38 | 39 | .. autoclass:: FrameMap 40 | :members: 41 | :special-members: __getitem__ 42 | 43 | SyncMultiFrameListener 44 | ^^^^^^^^^^^^^^^^^^^^^^ 45 | 46 | .. autoclass:: SyncMultiFrameListener 47 | :members: 48 | 49 | Initialization and Device Control 50 | --------------------------------- 51 | 52 | Freenect2Device 53 | ^^^^^^^^^^^^^^^ 54 | 55 | .. autoclass:: Freenect2Device 56 | :members: 57 | 58 | Freenect2 59 | ^^^^^^^^^ 60 | 61 | .. autoclass:: Freenect2 62 | :members: 63 | 64 | ColorCameraParams 65 | ^^^^^^^^^^^^^^^^^ 66 | 67 | .. autoclass:: ColorCameraParams 68 | :members: 69 | 70 | IrCameraParams 71 | ^^^^^^^^^^^^^^ 72 | 73 | .. autoclass:: IrCameraParams 74 | :members: 75 | 76 | Logging utilities 77 | ----------------- 78 | 79 | LoggerLevel 80 | ^^^^^^^^^^^ 81 | 82 | .. autoclass:: pylibfreenect2.LoggerLevel 83 | :members: 84 | 85 | Logger 86 | ^^^^^^ 87 | 88 | .. autoclass:: Logger 89 | :members: 90 | 91 | Functions 92 | ^^^^^^^^^ 93 | 94 | .. autosummary:: 95 | :toctree: generated/ 96 | 97 | createConsoleLogger 98 | createConsoleLoggerWithDefaultLevel 99 | getGlobalLogger 100 | setGlobalLogger 101 | 102 | Packet Pipelines 103 | ---------------- 104 | 105 | PacketPipeline 106 | ^^^^^^^^^^^^^^ 107 | 108 | .. autoclass:: PacketPipeline 109 | :members: 110 | 111 | CpuPacketPipeline 112 | ^^^^^^^^^^^^^^^^^ 113 | 114 | .. autoclass:: CpuPacketPipeline 115 | :members: 116 | 117 | OpenCLPacketPipeline 118 | ^^^^^^^^^^^^^^^^^^^^ 119 | 120 | .. autoclass:: OpenCLPacketPipeline 121 | :members: 122 | 123 | OpenCLKdePacketPipeline 124 | ^^^^^^^^^^^^^^^^^^^^^^^ 125 | 126 | .. autoclass:: OpenCLKdePacketPipeline 127 | :members: 128 | 129 | OpenGLPacketPipeline 130 | ^^^^^^^^^^^^^^^^^^^^ 131 | 132 | .. autoclass:: OpenGLPacketPipeline 133 | :members: 134 | 135 | CudaPacketPipeline 136 | ^^^^^^^^^^^^^^^^^^^^ 137 | 138 | .. autoclass:: CudaPacketPipeline 139 | :members: 140 | 141 | Registration and Geometry 142 | ------------------------- 143 | 144 | Registration 145 | ^^^^^^^^^^^^ 146 | 147 | .. autoclass:: Registration 148 | :members: 149 | """ 150 | 151 | 152 | import numpy as np 153 | 154 | cimport numpy as np 155 | np.import_array() 156 | 157 | cimport cython 158 | 159 | from libcpp cimport bool 160 | from libcpp.string cimport string 161 | from libcpp.map cimport map 162 | 163 | from libcpp.cast cimport reinterpret_cast 164 | from libc.stdint cimport uint8_t 165 | 166 | # Workaround for use of pointer type in reinterpret_cast 167 | # https://groups.google.com/forum/#!msg/cython-users/FgEf7Vrx4AM/dm7WY_bMCAAJ 168 | ctypedef uint8_t* uint8_pt 169 | 170 | # Import libfreenect2 definitions 171 | from .libfreenect2 cimport libfreenect2 172 | 173 | # A workaround to access nested cppclass that externed in a separate namespace. 174 | # Nested cppclass Freenect2Device::ColorCameraParams cannot be accesed 175 | # with chained ‘.‘ access (i.e. 176 | # `libfreenect2.Freenect2Device.ColorCameraParams`), here I explicitly import 177 | # Freenect2Device as _Freenect2Device (to avoid name conflict) and use 178 | # `_Freenect2Device.ColorCameraParams` to access nested cppclass 179 | # ColorCameraParams. 180 | from .libfreenect2.libfreenect2 cimport Freenect2Device as _Freenect2Device 181 | 182 | from pylibfreenect2 import FrameType 183 | 184 | cdef class Frame: 185 | """Python interface for ``libfreenect2::Frame``. 186 | 187 | The Frame is a container of the C++ pointer ``libfreenect2::Frame*``. 188 | 189 | .. note:: 190 | By default, Frame just keeps a pointer of ``libfreenect2::Frame`` that 191 | should be allocated and released by SyncMultiFrameListener (i.e. Frame 192 | itself doesn't own the allocated memory) as in C++. However, if Frame is 193 | created by providing ``width``, ``height`` and ``bytes_per_pixel``, then 194 | it allocates necessary memory in ``__cinit__`` and release it in 195 | ``__dealloc__`` method. 196 | 197 | Attributes 198 | ---------- 199 | ptr : libfreenect2::Frame* 200 | Pointer of Frame. 201 | 202 | take_ownership : bool 203 | If True, the class instance allocates memory for Frame* and release it 204 | in ``__dealloc__``. If `width`, `height` and `bytes_per_pixel` are given 205 | in ``__cinit__``, which is necessary to allocate how much memory we need, 206 | ``take_ownership`` is set to True internally, otherwise False. Note that 207 | the value itself cannot be set by users. 208 | 209 | frame_type : int 210 | Underlying frame type. 211 | 212 | Parameters 213 | ---------- 214 | width : int, optional 215 | Width of Frame. Default is None. 216 | 217 | height : int, optional 218 | Height of Frame. Default is None. 219 | 220 | bytes_per_pixel : int, optional 221 | Bytes per pixels of Frame. Default is None. 222 | 223 | frame_type : int, optional 224 | Underlying frame type. Default is -1. Used by ``asarray`` method. 225 | 226 | numpy_array : numpy.ndarray, optional 227 | Numpy array of depth or ir data with ndim=2, 228 | that will be converted to a frame class. 229 | Default is None. 230 | 231 | See also 232 | -------- 233 | 234 | pylibfreenect2.FrameType 235 | """ 236 | 237 | cdef libfreenect2.Frame* ptr 238 | cdef bool take_ownership 239 | cdef int frame_type 240 | 241 | def __cinit__(self, width=None, height=None, bytes_per_pixel=None, 242 | int frame_type=-1, np.ndarray[np.float32_t, ndim=2, mode="c"] numpy_array=None): 243 | w,h,b = width, height, bytes_per_pixel 244 | all_none = (w is None) and (h is None) and (b is None) 245 | all_not_none = (w is not None) and (h is not None) and (b is not None) 246 | assert all_none or all_not_none 247 | 248 | self.frame_type = frame_type 249 | 250 | if all_not_none: 251 | self.take_ownership = True 252 | if numpy_array is None: 253 | self.ptr = new libfreenect2.Frame( 254 | width, height, bytes_per_pixel, NULL) 255 | else: 256 | self.__instantiate_frame_with_bytes( 257 | width, height, bytes_per_pixel, numpy_array.reshape(-1)) 258 | else: 259 | self.take_ownership = False 260 | 261 | cdef __instantiate_frame_with_bytes(self, int width, int height, 262 | int bytes_per_pixel, np.ndarray[np.float32_t, ndim=1, mode="c"] numpy_array): 263 | cdef uint8_t* bytes_ptr = reinterpret_cast[uint8_pt](&numpy_array[0]) 264 | self.ptr = new libfreenect2.Frame( 265 | width, height, bytes_per_pixel, bytes_ptr) 266 | 267 | def __dealloc__(self): 268 | if self.take_ownership and self.ptr is not NULL: 269 | del self.ptr 270 | 271 | @property 272 | def timestamp(self): 273 | """Same as ``libfreenect2::Frame::timestamp``""" 274 | return self.ptr.timestamp 275 | 276 | @property 277 | def sequence(self): 278 | """Same as ``libfreenect2::Frame::sequence``""" 279 | return self.ptr.sequence 280 | 281 | @property 282 | def width(self): 283 | """Same as ``libfreenect2::Frame::width``""" 284 | return self.ptr.width 285 | 286 | @property 287 | def height(self): 288 | """Same as ``libfreenect2::Frame::height``""" 289 | return self.ptr.height 290 | 291 | @property 292 | def bytes_per_pixel(self): 293 | """Same as ``libfreenect2::Frame::bytes_per_pixel``""" 294 | return self.ptr.bytes_per_pixel 295 | 296 | @property 297 | def exposure(self): 298 | """Same as ``libfreenect2::Frame::exposure``""" 299 | return self.ptr.exposure 300 | 301 | @property 302 | def gain(self): 303 | """Same as ``libfreenect2::Frame::gain``""" 304 | return self.ptr.gain 305 | 306 | @property 307 | def gamma(self): 308 | """Same as ``libfreenect2::Frame::gamma``""" 309 | return self.ptr.gamma 310 | 311 | cdef __uint8_data(self): 312 | cdef np.npy_intp shape[3] 313 | shape[0] = self.ptr.height 314 | shape[1] = self.ptr.width 315 | shape[2] = 4 316 | cdef np.ndarray array = np.PyArray_SimpleNewFromData( 317 | 3, shape, np.NPY_UINT8, self.ptr.data) 318 | 319 | return array 320 | 321 | cdef __float32_data(self): 322 | cdef np.npy_intp shape[2] 323 | shape[0] = self.ptr.height 324 | shape[1] = self.ptr.width 325 | cdef np.ndarray array = np.PyArray_SimpleNewFromData( 326 | 2, shape, np.NPY_FLOAT32, self.ptr.data) 327 | 328 | return array 329 | 330 | def __asarray(self, dtype): 331 | if dtype != np.uint8 and dtype != np.float32: 332 | raise ValueError("np.uint8 or np.float32 is only supported") 333 | if dtype == np.uint8: 334 | return self.__uint8_data() 335 | else: 336 | return self.__float32_data() 337 | 338 | def asarray(self, dtype=None): 339 | """Frame to ``numpy.ndarray`` conversion 340 | 341 | Internal data of Frame can be represented as: 342 | 343 | - 3d array of ``numpy.uint8`` for color 344 | - 2d array of ``numpy.float32`` for IR and depth 345 | 346 | Parameters 347 | ---------- 348 | dtype : numpy dtype, optional 349 | Data type (``numpy.uint8`` or ``numpy.float32``). If None, data 350 | type is automatically selected if possible. Default is None. 351 | 352 | Returns 353 | ------- 354 | array : ``numpy.ndarray``, shape: ``(height, width)`` for IR and depth, 355 | ``(4, height, width)`` for Color. 356 | Array of internal frame. 357 | 358 | Raises 359 | ------ 360 | ValueError 361 | - If dtype is None and underlying frame type cannot be determined. 362 | - If dtype neither ``numpy.uint8`` nor ``numpy.float32`` is specified 363 | 364 | Examples 365 | -------- 366 | 367 | .. code-block:: python 368 | 369 | rgb_array = frames["color"].asarray() 370 | ir_array = frames["ir"].asarray() 371 | depth_array = frames["depth"].asarray() 372 | 373 | .. code-block:: python 374 | 375 | undistorted = Frame(512, 424, 4) 376 | registered = Frame(512, 424, 4) 377 | undistorted_arrray = undistorted.asarray(dtype=np.float32) 378 | registered_array = registered.asarray(dtype=np.uint8) 379 | 380 | """ 381 | if dtype is None and self.frame_type < 0: 382 | raise ValueError("Cannot determine type of data. Specify dtype explicitly.") 383 | 384 | if dtype is None: 385 | if self.frame_type == FrameType.Color: 386 | return self.__asarray(np.uint8) 387 | elif self.frame_type == FrameType.Ir or self.frame_type == FrameType.Depth: 388 | return self.__asarray(np.float32) 389 | else: 390 | assert False 391 | else: 392 | return self.__asarray(dtype) 393 | 394 | cdef class FrameListener: 395 | cdef libfreenect2.FrameListener* listener_ptr_alias 396 | 397 | 398 | cdef intenum_to_frame_type(int n): 399 | if n == FrameType.Color: 400 | return libfreenect2.Color 401 | elif n == FrameType.Ir: 402 | return libfreenect2.Ir 403 | elif n == FrameType.Depth: 404 | return libfreenect2.Depth 405 | else: 406 | raise ValueError("Not supported") 407 | 408 | cdef str_to_int_frame_type(str s): 409 | s = s.lower() 410 | if s == "color": 411 | return FrameType.Color 412 | elif s == "ir": 413 | return FrameType.Ir 414 | elif s == "depth": 415 | return FrameType.Depth 416 | else: 417 | raise ValueError("Not supported") 418 | 419 | cdef str_to_frame_type(str s): 420 | return intenum_to_frame_type(str_to_int_frame_type(s)) 421 | 422 | 423 | cdef class FrameMap: 424 | """Python interface for ``libfreenect2::FrameMap``. 425 | 426 | The FrameMap is a container of C++ value ``libfreenect2::FrameMap`` (aliased 427 | to ``std::map`` in C++). 428 | 429 | .. note:: 430 | By default, FrameMap just keeps a reference of ``libfreenect2::FrameMap`` 431 | that should be allcoated and released by SyncMultiFrameListener (i.e. 432 | FrameMap itself doesn't own the allocated memory) as in C++. 433 | 434 | Attributes 435 | ---------- 436 | internal_frame_map : std::map 437 | Internal FrameMap. 438 | 439 | """ 440 | cdef map[libfreenect2.LibFreenect2FrameType, libfreenect2.Frame*] internal_frame_map 441 | cdef bool take_ownership 442 | 443 | def __cinit__(self, bool take_ownership=False): 444 | self.take_ownership = take_ownership 445 | 446 | def __dealloc__(self): 447 | # Since libfreenect2 is for now designed to release FrameMap explicitly, 448 | # __dealloc__ do nothing by default (take_ownership = False) 449 | if self.take_ownership: 450 | # similar to SyncMultiFrameListener::release(FrameMap &frame) 451 | # do nothing if already released 452 | for key in self.internal_frame_map: 453 | if key.second != NULL: 454 | del key.second 455 | key.second = NULL 456 | 457 | def __getitem__(self, key): 458 | """Get access to the internal FrameMap. 459 | 460 | This allows the following dict-like syntax: 461 | 462 | .. code-block:: python 463 | 464 | color = frames[pylibfreenect2.FrameType.Color] 465 | 466 | .. code-block:: python 467 | 468 | color = frames['color'] 469 | 470 | .. code-block:: python 471 | 472 | color = frames[1] # with IntEnum value 473 | 474 | The key can be of ``FrameType`` (a subclass of IntEnum), str or int type 475 | as shown above. 476 | 477 | Parameters 478 | ---------- 479 | key : ``FrameType``, str or int 480 | Key for the internal FrameMap. available str keys are ``color``, 481 | ``ir`` and ``depth``. 482 | 483 | Returns 484 | ------- 485 | frame : Frame 486 | Frame for the specified key. 487 | 488 | Raises 489 | ------ 490 | KeyError 491 | if unknown key is specified 492 | 493 | See also 494 | -------- 495 | 496 | pylibfreenect2.FrameType 497 | 498 | """ 499 | cdef libfreenect2.LibFreenect2FrameType frame_type 500 | cdef intkey 501 | 502 | if isinstance(key, int) or isinstance(key, FrameType): 503 | frame_type = intenum_to_frame_type(key) 504 | intkey = key 505 | elif isinstance(key, str): 506 | frame_type = str_to_frame_type(key) 507 | intkey = str_to_int_frame_type(key) 508 | else: 509 | raise KeyError("") 510 | 511 | cdef libfreenect2.Frame* frame_ptr = self.internal_frame_map[frame_type] 512 | cdef Frame frame = Frame(frame_type=intkey) 513 | frame.ptr = frame_ptr 514 | return frame 515 | 516 | 517 | cdef class SyncMultiFrameListener(FrameListener): 518 | """Python interface for ``libfreenect2::SyncMultiFrameListener``. 519 | 520 | The SyncMultiFrameListener is a container of 521 | C++ pointer ``libfreenect2::SyncMultiFrameListener*``. The pointer of 522 | SyncMultiFrameListener is allocated in ``__cinit__`` and released in 523 | ``__dealloc__`` method. 524 | 525 | Parameters 526 | ---------- 527 | frame_types : unsigned int, optional 528 | Frame types that we want to listen. It can be logical OR of: 529 | 530 | - ``FrameType.Color`` 531 | - ``FrameType.Ir`` 532 | - ``FrameType.Depth`` 533 | 534 | Default is ``FrameType.Color | FrameType.Ir | FrameType.Depth`` 535 | 536 | Attributes 537 | ---------- 538 | ptr : libfreenect2.SyncMultiFrameListener* 539 | Pointer of ``libfreenect2::SyncMultiFrameListener`` 540 | 541 | listener_ptr_alias : libfreenect2.FrameListener* 542 | Pointer of ``libfreenect2::FrameListener``. This is necessary to call 543 | methods that operate on ``libfreenect2::FrameListener*``, not 544 | ``libfreenect2::SyncMultiFrameListener``. 545 | 546 | See also 547 | -------- 548 | 549 | pylibfreenect2.FrameType 550 | 551 | """ 552 | 553 | cdef libfreenect2.SyncMultiFrameListener* ptr 554 | 555 | def __cinit__(self, unsigned int frame_types=( 556 | FrameType.Color | FrameType.Ir | FrameType.Depth)): 557 | self.ptr = new libfreenect2.SyncMultiFrameListener(frame_types) 558 | self.listener_ptr_alias = self.ptr 559 | 560 | def __dealloc__(self): 561 | if self.ptr is not NULL: 562 | del self.ptr 563 | 564 | def hasNewFrame(self): 565 | """Same as ``libfreenect2::SyncMultiFrameListener::hasNewFrame()``. 566 | 567 | Returns 568 | ------- 569 | r : Bool 570 | True if SyncMultiFrameListener has a new frame, False otherwise. 571 | """ 572 | return self.ptr.hasNewFrame() 573 | 574 | def waitForNewFrame(self, FrameMap frame_map=None, int milliseconds=-1): 575 | """Same as ``libfreenect2::SyncMultiFrameListener::waitForNewFrame(Frame&)``. 576 | 577 | .. warning:: 578 | 579 | Function signature can be different between Python and C++. 580 | 581 | Parameters 582 | ---------- 583 | frame_map : FrameMap, optional 584 | If not None, SyncMultiFrameListener write to it inplace, otherwise 585 | a new FrameMap is allocated within the function and then returned. 586 | 587 | milliseconds : int, optional 588 | If >= 0, a timeout is set for getting the new frame. In case the 589 | new frame did not arrive beore the timeout, None will be returned. 590 | 591 | Returns 592 | ------- 593 | frame_map : FrameMap 594 | FrameMap, or None if timeout exceeded. 595 | 596 | .. note:: 597 | FrameMap must be releaseed by call-side by calling ``release`` 598 | function. 599 | 600 | Examples 601 | -------- 602 | 603 | Suppose the following C++ code: 604 | 605 | .. code-block:: c++ 606 | 607 | libfreenect2::FrameMap frames; 608 | listener->waitForNewFrame(frames); 609 | 610 | This can be translated in Python as follows: 611 | 612 | .. code-block:: python 613 | 614 | frames = listener.waitForNewFrame() 615 | 616 | or you can write it more similar to C++: 617 | 618 | .. code-block:: python 619 | 620 | frames = pylibfreenect2.FrameMap() 621 | listener.waitForNewFrame(frames) 622 | 623 | Example with millisecond timeout: 624 | 625 | .. code-block:: python 626 | 627 | frames = listener.waitForNewFrame(milliseconds=50) 628 | if frames: 629 | # frames should be set to a value. 630 | else: 631 | # Timeout happened. 632 | 633 | """ 634 | frame_map_owned = False 635 | if frame_map is None: 636 | frame_map_owned = True 637 | frame_map = FrameMap(take_ownership=False) 638 | 639 | cdef bool frame_map_set = True 640 | with nogil: 641 | if milliseconds >= 0: 642 | frame_map_set = self.ptr.waitForNewFrame( 643 | frame_map.internal_frame_map, milliseconds) 644 | else: 645 | self.ptr.waitForNewFrame(frame_map.internal_frame_map) 646 | 647 | if frame_map_set: 648 | return frame_map 649 | 650 | # The timeout happened. We should clean up if we allocated frame_map and 651 | # return None. 652 | if frame_map_owned: 653 | self.release(frame_map) 654 | return None 655 | 656 | def release(self, FrameMap frame_map): 657 | """Same as ``libfreenect2::SyncMultiFrameListener::release(Frame&)``. 658 | 659 | Parameters 660 | ---------- 661 | frame_map : FrameMap 662 | FrameMap. 663 | """ 664 | self.ptr.release(frame_map.internal_frame_map) 665 | 666 | 667 | cdef class ColorCameraParams: 668 | """Python interface for ``libfreenect2::Freenect2Device::ColorCameraParams``. 669 | 670 | Attributes 671 | ---------- 672 | params : ``libfreenect2::Freenect2Device::ColorCameraParams`` 673 | 674 | See also 675 | -------- 676 | pylibfreenect2.libfreenect2.Freenect2Device.getColorCameraParams 677 | """ 678 | cdef _Freenect2Device.ColorCameraParams params 679 | 680 | # TODO: wrap all instance variables 681 | @property 682 | def fx(self): 683 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::fx``""" 684 | return self.params.fx 685 | 686 | @fx.setter 687 | def fx(self, value): 688 | """Sets fx parameter""" 689 | self.params.fx = value 690 | 691 | @property 692 | def fy(self): 693 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::fy``""" 694 | return self.params.fy 695 | 696 | @fy.setter 697 | def fy(self, value): 698 | """Sets fy parameter""" 699 | self.params.fy = value 700 | 701 | @property 702 | def cx(self): 703 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::cx``""" 704 | return self.params.cx 705 | 706 | @cx.setter 707 | def cx(self, value): 708 | """Sets cx parameter""" 709 | self.params.cx = value 710 | 711 | @property 712 | def cy(self): 713 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::cy``""" 714 | return self.params.cy 715 | 716 | @cy.setter 717 | def cy(self, value): 718 | """Sets cx parameter""" 719 | self.params.cy = value 720 | 721 | @property 722 | def shift_d(self): 723 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::shift_d``""" 724 | return self.params.shift_d 725 | 726 | @shift_d.setter 727 | def shift_d(self, value): 728 | """Sets shift_d parameter""" 729 | self.params.shift_d = value 730 | 731 | 732 | @property 733 | def shift_m(self): 734 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::shift_m``""" 735 | return self.params.shift_m 736 | 737 | @shift_m.setter 738 | def shift_m(self, value): 739 | """Sets shift_m parameter""" 740 | self.params.shift_m = value 741 | 742 | 743 | @property 744 | def mx_x3y0(self): 745 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x3y0``""" 746 | return self.params.mx_x3y0 747 | 748 | @mx_x3y0.setter 749 | def mx_x3y0(self, value): 750 | """Sets mx_x3y0 parameter""" 751 | self.params.mx_x3y0 = value 752 | 753 | 754 | @property 755 | def mx_x0y3(self): 756 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x0y3``""" 757 | return self.params.mx_x0y3 758 | 759 | @mx_x0y3.setter 760 | def mx_x0y3(self, value): 761 | """Sets mx_x0y3 parameter""" 762 | self.params.mx_x0y3 = value 763 | 764 | 765 | @property 766 | def mx_x2y1(self): 767 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x2y1``""" 768 | return self.params.mx_x2y1 769 | 770 | @mx_x2y1.setter 771 | def mx_x2y1(self, value): 772 | """Sets mx_x2y1 parameter""" 773 | self.params.mx_x2y1 = value 774 | 775 | 776 | @property 777 | def mx_x1y2(self): 778 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x1y2``""" 779 | return self.params.mx_x1y2 780 | 781 | @mx_x1y2.setter 782 | def mx_x1y2(self, value): 783 | """Sets mx_x1y2 parameter""" 784 | self.params.mx_x1y2 = value 785 | 786 | 787 | @property 788 | def mx_x2y0(self): 789 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x2y0``""" 790 | return self.params.mx_x2y0 791 | 792 | @mx_x2y0.setter 793 | def mx_x2y0(self, value): 794 | """Sets mx_x2y0 parameter""" 795 | self.params.mx_x2y0 = value 796 | 797 | 798 | @property 799 | def mx_x0y2(self): 800 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x0y2``""" 801 | return self.params.mx_x0y2 802 | 803 | @mx_x0y2.setter 804 | def mx_x0y2(self, value): 805 | """Sets mx_x0y2 parameter""" 806 | self.params.mx_x0y2 = value 807 | 808 | 809 | @property 810 | def mx_x1y1(self): 811 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x1y1``""" 812 | return self.params.mx_x1y1 813 | 814 | @mx_x1y1.setter 815 | def mx_x1y1(self, value): 816 | """Sets mx_x1y1 parameter""" 817 | self.params.mx_x1y1 = value 818 | 819 | 820 | @property 821 | def mx_x1y0(self): 822 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x1y0``""" 823 | return self.params.mx_x1y0 824 | 825 | @mx_x1y0.setter 826 | def mx_x1y0(self, value): 827 | """Sets mx_x1y0 parameter""" 828 | self.params.mx_x1y0 = value 829 | 830 | 831 | @property 832 | def mx_x0y1(self): 833 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x0y1``""" 834 | return self.params.mx_x0y1 835 | 836 | @mx_x0y1.setter 837 | def mx_x0y1(self, value): 838 | """Sets mx_x0y1 parameter""" 839 | self.params.mx_x0y1 = value 840 | 841 | 842 | @property 843 | def mx_x0y0(self): 844 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::mx_x0y0``""" 845 | return self.params.mx_x0y0 846 | 847 | @mx_x0y0.setter 848 | def mx_x0y0(self, value): 849 | """Sets mx_x0y0 parameter""" 850 | self.params.mx_x0y0 = value 851 | 852 | 853 | @property 854 | def my_x3y0(self): 855 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x3y0``""" 856 | return self.params.my_x3y0 857 | 858 | @my_x3y0.setter 859 | def my_x3y0(self, value): 860 | """Sets my_x3y0 parameter""" 861 | self.params.my_x3y0 = value 862 | 863 | 864 | @property 865 | def my_x0y3(self): 866 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x0y3``""" 867 | return self.params.my_x0y3 868 | 869 | @my_x0y3.setter 870 | def my_x0y3(self, value): 871 | """Sets my_x0y3 parameter""" 872 | self.params.my_x0y3 = value 873 | 874 | 875 | @property 876 | def my_x2y1(self): 877 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x2y1``""" 878 | return self.params.my_x2y1 879 | 880 | @my_x2y1.setter 881 | def my_x2y1(self, value): 882 | """Sets my_x2y1 parameter""" 883 | self.params.my_x2y1 = value 884 | 885 | 886 | @property 887 | def my_x1y2(self): 888 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x1y2``""" 889 | return self.params.my_x1y2 890 | 891 | @my_x1y2.setter 892 | def my_x1y2(self, value): 893 | """Sets my_x1y2 parameter""" 894 | self.params.my_x1y2 = value 895 | 896 | 897 | @property 898 | def my_x2y0(self): 899 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x2y0``""" 900 | return self.params.my_x2y0 901 | 902 | @my_x2y0.setter 903 | def my_x2y0(self, value): 904 | """Sets my_x2y0 parameter""" 905 | self.params.my_x2y0 = value 906 | 907 | 908 | @property 909 | def my_x0y2(self): 910 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x0y2``""" 911 | return self.params.my_x0y2 912 | 913 | @my_x0y2.setter 914 | def my_x0y2(self, value): 915 | """Sets my_x0y2 parameter""" 916 | self.params.my_x0y2 = value 917 | 918 | 919 | @property 920 | def my_x1y1(self): 921 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x1y1``""" 922 | return self.params.my_x1y1 923 | 924 | @my_x1y1.setter 925 | def my_x1y1(self, value): 926 | """Sets my_x1y1 parameter""" 927 | self.params.my_x1y1 = value 928 | 929 | 930 | @property 931 | def my_x1y0(self): 932 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x1y0``""" 933 | return self.params.my_x1y0 934 | 935 | @my_x1y0.setter 936 | def my_x1y0(self, value): 937 | """Sets my_x1y0 parameter""" 938 | self.params.my_x1y0 = value 939 | 940 | 941 | @property 942 | def my_x0y1(self): 943 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x0y1``""" 944 | return self.params.my_x0y1 945 | 946 | @my_x0y1.setter 947 | def my_x0y1(self, value): 948 | """Sets my_x0y1 parameter""" 949 | self.params.my_x0y1 = value 950 | 951 | 952 | @property 953 | def my_x0y0(self): 954 | """Same as ``libfreenect2::Freenect2Device::ColorCameraParams::my_x0y0``""" 955 | return self.params.my_x0y0 956 | 957 | @my_x0y0.setter 958 | def my_x0y0(self, value): 959 | """Sets my_x0y0 parameter""" 960 | self.params.my_x0y0 = value 961 | 962 | 963 | 964 | cdef class IrCameraParams: 965 | """Python interface for ``libfreenect2::IrCameraParams``. 966 | 967 | Attributes 968 | ---------- 969 | params : ``libfreenect2::Freenect2Device::IrCameraParams`` 970 | 971 | See also 972 | -------- 973 | pylibfreenect2.libfreenect2.Freenect2Device.getIrCameraParams 974 | """ 975 | cdef _Freenect2Device.IrCameraParams params 976 | 977 | @property 978 | def fx(self): 979 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::fx``""" 980 | return self.params.fx 981 | 982 | @fx.setter 983 | def fx(self, value): 984 | """Sets fx parameter""" 985 | self.params.fx = value 986 | 987 | @property 988 | def fy(self): 989 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::fy``""" 990 | return self.params.fy 991 | 992 | @fy.setter 993 | def fy(self, value): 994 | """Sets fy parameter""" 995 | self.params.fy = value 996 | 997 | @property 998 | def cx(self): 999 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::cx``""" 1000 | return self.params.cx 1001 | 1002 | @cx.setter 1003 | def cx(self, value): 1004 | """Sets cx parameter""" 1005 | self.params.cx = value 1006 | 1007 | @property 1008 | def cy(self): 1009 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::cy``""" 1010 | return self.params.cy 1011 | 1012 | @cy.setter 1013 | def cy(self, value): 1014 | """Sets cx parameter""" 1015 | self.params.cy = value 1016 | 1017 | @property 1018 | def k1(self): 1019 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::k1``""" 1020 | return self.params.k1 1021 | 1022 | @k1.setter 1023 | def k1(self, value): 1024 | """Sets k1 parameter""" 1025 | self.params.k1 = value 1026 | 1027 | @property 1028 | def k2(self): 1029 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::k2``""" 1030 | return self.params.k2 1031 | 1032 | @k2.setter 1033 | def k2(self, value): 1034 | """Sets k2 parameter""" 1035 | self.params.k2 = value 1036 | 1037 | @property 1038 | def k3(self): 1039 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::k3``""" 1040 | return self.params.k3 1041 | 1042 | @k3.setter 1043 | def k3(self, value): 1044 | """Sets k3 parameter""" 1045 | self.params.k3 = value 1046 | 1047 | @property 1048 | def p1(self): 1049 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::p1``""" 1050 | return self.params.p1 1051 | 1052 | @p1.setter 1053 | def p1(self, value): 1054 | """Sets p1 parameter""" 1055 | self.params.p1 = value 1056 | 1057 | @property 1058 | def p2(self): 1059 | """Same as ``libfreenect2::Freenect2Device::IrCameraParams::p2``""" 1060 | return self.params.p2 1061 | 1062 | @p2.setter 1063 | def p2(self, value): 1064 | """Sets p2 parameter""" 1065 | self.params.p2 = value 1066 | 1067 | cdef class Registration: 1068 | """Python interface for ``libfreenect2::Registration``. 1069 | 1070 | The Registration is a container of C++ pointer 1071 | ``libfreenect2::Registration*``. The pointer of Registration is allocated 1072 | in ``__cinit__`` and released in ``__dealloc__`` method. 1073 | 1074 | Attributes 1075 | ---------- 1076 | ptr : ``libfreenect2::Registration*`` 1077 | 1078 | Parameters 1079 | ---------- 1080 | irparams : IrCameraParams 1081 | IR camera parameters. 1082 | 1083 | cparams : ColorCameraParams 1084 | Color camera parameters. 1085 | 1086 | See also 1087 | -------- 1088 | pylibfreenect2.libfreenect2.IrCameraParams 1089 | pylibfreenect2.libfreenect2.ColorCameraParams 1090 | pylibfreenect2.libfreenect2.Freenect2Device.getIrCameraParams 1091 | pylibfreenect2.libfreenect2.Freenect2Device.getColorCameraParams 1092 | """ 1093 | cdef libfreenect2.Registration* ptr 1094 | 1095 | def __cinit__(self, IrCameraParams irparams, ColorCameraParams cparams): 1096 | cdef _Freenect2Device.IrCameraParams i = irparams.params 1097 | cdef _Freenect2Device.ColorCameraParams c = cparams.params 1098 | self.ptr = new libfreenect2.Registration(i, c) 1099 | 1100 | def __dealloc__(self): 1101 | if self.ptr is not NULL: 1102 | del self.ptr 1103 | 1104 | def apply(self, Frame rgb, Frame depth, Frame undistorted, 1105 | Frame registered, enable_filter=True, Frame bigdepth=None, 1106 | np.ndarray[np.int32_t, ndim=1, mode="c"] color_depth_map=None): 1107 | """Same as ``libfreenect2::Registration::apply``. 1108 | 1109 | Parameters 1110 | ---------- 1111 | rgb : Frame 1112 | ``(1920, 1080)`` color frame 1113 | 1114 | depth : Frame 1115 | ``(512, 424)`` depth frame 1116 | 1117 | undistorted : Frame 1118 | ``(512, 424)`` registered depth frame 1119 | 1120 | registered : Frame 1121 | ``(512, 424)`` registered color frame 1122 | 1123 | enable_filter : Bool, optional 1124 | 1125 | bigdepth : Frame, optional 1126 | ``(1920, 1082)`` bigdepth frame 1127 | 1128 | color_depth_map : ``numpy.ndarray``, optional 1129 | Array of shape: ``(424*512,)``, dtype ``np.int32`` 1130 | 1131 | Raises 1132 | ------ 1133 | ValueError 1134 | If invalid shape of frame/array is provided 1135 | 1136 | """ 1137 | if rgb.width != 1920 or rgb.height != 1080: 1138 | raise ValueError( 1139 | "Shape of color frame {}x{} is invalid. Expected 1920x1080.".format( 1140 | rgb.width, rgb.height)) 1141 | if depth.width != 512 or depth.height != 424: 1142 | raise ValueError( 1143 | "Shape of depth frame {}x{} is invalid. Expected 512x424.".format( 1144 | depth.width, depth.height)) 1145 | if undistorted.width != 512 or undistorted.height != 424: 1146 | raise ValueError( 1147 | "Shape of undistorted frame {}x{} is invalid. Expected 512x424.".format( 1148 | undistorted.width, undistorted.height)) 1149 | if registered.width != 512 or registered.height != 424: 1150 | raise ValueError( 1151 | "Shape of registered frame {}x{} is invalid. Expected 512x424.".format( 1152 | registered.width, registered.height)) 1153 | 1154 | if bigdepth is not None: 1155 | if bigdepth.width != 1920 or bigdepth.height != 1082: 1156 | raise ValueError( 1157 | "Shape of bigdepth frame {}x{} is invalid. Expected 1920x1082.".format( 1158 | bigdepth.width, bigdepth.height)) 1159 | 1160 | if color_depth_map is not None: 1161 | if color_depth_map.shape[0] != 424*512: 1162 | raise ValueError( 1163 | "Shape of color_depth_map array ({},) is invalid. Expected (424*512,)".format( 1164 | color_depth_map.shape[0])) 1165 | 1166 | assert rgb.take_ownership == False 1167 | assert depth.take_ownership == False 1168 | assert undistorted.take_ownership == True 1169 | assert registered.take_ownership == True 1170 | assert bigdepth is None or bigdepth.take_ownership == True 1171 | 1172 | cdef libfreenect2.Frame* bigdepth_ptr = (NULL) \ 1173 | if bigdepth is None else bigdepth.ptr 1174 | cdef int* color_depth_map_ptr = (NULL) if color_depth_map is None \ 1175 | else (&color_depth_map[0]) 1176 | 1177 | self.ptr.apply(rgb.ptr, depth.ptr, undistorted.ptr, registered.ptr, 1178 | enable_filter, bigdepth_ptr, color_depth_map_ptr) 1179 | 1180 | def undistortDepth(self, Frame depth, Frame undistorted): 1181 | """Same as ``libfreenect2::Registration::undistortDepth(bool, bool)``. 1182 | 1183 | Parameters 1184 | ---------- 1185 | depth : Frame 1186 | ``(512, 424)`` depth frame 1187 | 1188 | undistorted : Frame 1189 | ``(512, 424)`` registered depth frame 1190 | 1191 | Raises 1192 | ------ 1193 | ValueError 1194 | If invalid shape of frame/array is provided 1195 | """ 1196 | 1197 | if depth.width != 512 or depth.height != 424: 1198 | raise ValueError( 1199 | "Shape of depth frame {}x{} is invalid. Expected 512x424.".format( 1200 | depth.width, depth.height)) 1201 | if undistorted.width != 512 or undistorted.height != 424: 1202 | raise ValueError( 1203 | "Shape of undistorted frame {}x{} is invalid. Expected 512x424.".format( 1204 | undistorted.width, undistorted.height)) 1205 | self.ptr.undistortDepth(depth.ptr, undistorted.ptr) 1206 | 1207 | def getPointXYZRGB(self, Frame undistorted, Frame registered, r, c): 1208 | """Same as ``libfreenect2::Registration::getPointXYZRGB``. 1209 | 1210 | Parameters 1211 | ---------- 1212 | undistorted : Frame 1213 | ``(512, 424)`` Undistorted depth frame 1214 | 1215 | registered : Frame 1216 | ``(512, 424)`` Registered color frame 1217 | 1218 | r : int 1219 | Row (y) index in depth image 1220 | 1221 | c : int 1222 | Column (x) index in depth image. 1223 | 1224 | Returns 1225 | ------- 1226 | tuple : (X coordinate of the 3-D point (meter), 1227 | Y coordinate of the 3-D point (meter), 1228 | Z coordinate of the 3-D point (meter), 1229 | B, 1230 | G, 1231 | R) 1232 | 1233 | """ 1234 | cdef float x = 0, y = 0, z = 0, rgb = 0 1235 | self.ptr.getPointXYZRGB(undistorted.ptr, registered.ptr, r, c, x, y, z, rgb) 1236 | cdef uint8_t* bgrptr = reinterpret_cast[uint8_pt](&rgb); 1237 | return (x, y, z, bgrptr[0], bgrptr[1], bgrptr[2]) 1238 | 1239 | def getPointXYZ(self, Frame undistorted, r, c): 1240 | """Same as ``libfreenect2::Registration::getPointXYZ``. 1241 | 1242 | Parameters 1243 | ---------- 1244 | undistorted : Frame 1245 | ``(512, 424)`` Undistorted depth frame 1246 | 1247 | r : int 1248 | Row (y) index in depth image 1249 | 1250 | c : int 1251 | Column (x) index in depth image. 1252 | 1253 | Returns 1254 | ------- 1255 | tuple : (X coordinate of the 3-D point (meter), 1256 | Y coordinate of the 3-D point (meter), 1257 | Z coordinate of the 3-D point (meter)) 1258 | 1259 | """ 1260 | cdef float x = 0, y = 0, z = 0 1261 | self.ptr.getPointXYZ(undistorted.ptr, r, c, x, y, z) 1262 | return (x, y, z) 1263 | 1264 | 1265 | cdef class Logger: 1266 | """Python interface for libfreenect2::Logger 1267 | 1268 | 1269 | The Logger is a container of C++ pointer ``libfreenect2::Logger*``. 1270 | 1271 | Attributes 1272 | ---------- 1273 | ptr : libfreenect2::Logger* 1274 | C++ pointer of Logger 1275 | 1276 | """ 1277 | cdef libfreenect2.Logger* ptr 1278 | 1279 | def level(self): 1280 | """Same as ``Level level()``""" 1281 | return self.ptr.level() 1282 | 1283 | def log(self, level, message): 1284 | """Same as ``void log(Level level, const std::string &messagge)``""" 1285 | self.ptr.log(level, message) 1286 | 1287 | 1288 | def createConsoleLogger(level): 1289 | """Same as ``Logger* libfreenect2::createConsoleLogger(Level level)`` 1290 | 1291 | Parameters 1292 | ---------- 1293 | level : pylibfreenect2.LoggerLevel 1294 | Logger level 1295 | 1296 | Returns 1297 | ------- 1298 | logger : Logger 1299 | Allocated logger 1300 | 1301 | Examples 1302 | -------- 1303 | .. code-block:: python 1304 | 1305 | logger = pylibfreenect2.createConsoleLogger( 1306 | pylibfreenect2.LoggerLevel.Debug) 1307 | 1308 | See also 1309 | -------- 1310 | 1311 | pylibfreenect2.LoggerLevel 1312 | pylibfreenect2.libfreenect2.createConsoleLoggerWithDefaultLevel 1313 | """ 1314 | cdef Logger logger = Logger() 1315 | logger.ptr = libfreenect2.createConsoleLogger(level) 1316 | return logger 1317 | 1318 | 1319 | def createConsoleLoggerWithDefaultLevel(): 1320 | """Same as ``Logger* libfreenect2::createConsoleLoggerWithDefaultLevel()`` 1321 | 1322 | Returns 1323 | ------- 1324 | logger : Logger 1325 | Allocated logger 1326 | 1327 | See also 1328 | -------- 1329 | 1330 | pylibfreenect2.libfreenect2.createConsoleLogger 1331 | """ 1332 | cdef Logger logger = Logger() 1333 | cdef libfreenect2.Logger* ptr = libfreenect2.createConsoleLoggerWithDefaultLevel() 1334 | logger.ptr = ptr 1335 | return logger 1336 | 1337 | 1338 | def getGlobalLogger(): 1339 | """Same as ``Logger* libfreenect2::getGlobalLogger()``""" 1340 | cdef Logger logger = Logger() 1341 | logger.ptr = libfreenect2.getGlobalLogger() 1342 | return logger 1343 | 1344 | 1345 | def setGlobalLogger(Logger logger=None): 1346 | """Same as ``void libfreenect2::getGlobalLogger(Logger*)`` 1347 | 1348 | Parameters 1349 | ---------- 1350 | logger : Logger 1351 | Python side instance for ``libfreenect2::Logger*``. If None, 1352 | ``setGlobalLogger(NULL)`` will be called, i.e. logging is disabled. 1353 | Default is None. 1354 | 1355 | """ 1356 | if logger is None: 1357 | libfreenect2.setGlobalLogger(NULL) 1358 | else: 1359 | libfreenect2.setGlobalLogger(logger.ptr) 1360 | 1361 | 1362 | # MUST be declared before backend specific includes 1363 | cdef class PacketPipeline: 1364 | """Base class for other pipeline classes. 1365 | 1366 | Attributes 1367 | ---------- 1368 | pipeline_ptr_alias : ``libfreenect2::PacketPipeline*`` 1369 | owened_by_device : bool 1370 | 1371 | See also 1372 | -------- 1373 | pylibfreenect2.libfreenect2.CpuPacketPipeline 1374 | pylibfreenect2.libfreenect2.OpenCLPacketPipeline 1375 | pylibfreenect2.libfreenect2.OpenCLKdePacketPipeline 1376 | pylibfreenect2.libfreenect2.OpenGLPacketPipeline 1377 | pylibfreenect2.libfreenect2.CudaPacketPipeline 1378 | """ 1379 | cdef libfreenect2.PacketPipeline* pipeline_ptr_alias 1380 | 1381 | # NOTE: once device is opened with pipeline, pipeline will be 1382 | # releaseed in the destructor of Freenect2DeviceImpl 1383 | cdef bool owned_by_device 1384 | 1385 | 1386 | cdef class CpuPacketPipeline(PacketPipeline): 1387 | """Pipeline with CPU depth processing. 1388 | 1389 | Attributes 1390 | ---------- 1391 | pipeline : `libfreenect2::CpuPacketPipeline*` 1392 | """ 1393 | cdef libfreenect2.CpuPacketPipeline* pipeline 1394 | 1395 | def __cinit__(self): 1396 | self.pipeline = new libfreenect2.CpuPacketPipeline() 1397 | self.pipeline_ptr_alias = self.pipeline 1398 | self.owned_by_device = False 1399 | 1400 | def __dealloc__(self): 1401 | if not self.owned_by_device: 1402 | if self.pipeline is not NULL: 1403 | del self.pipeline 1404 | 1405 | IF LIBFREENECT2_WITH_OPENGL_SUPPORT == True: 1406 | include "opengl_packet_pipeline.pxi" 1407 | 1408 | IF LIBFREENECT2_WITH_OPENCL_SUPPORT == True: 1409 | include "opencl_packet_pipeline.pxi" 1410 | include "opencl_kde_packet_pipeline.pxi" 1411 | 1412 | IF LIBFREENECT2_WITH_CUDA_SUPPORT == True: 1413 | include "cuda_packet_pipeline.pxi" 1414 | 1415 | cdef class Freenect2Device: 1416 | """Python interface for ``libfreenect2::Freenect2Device``. 1417 | 1418 | The Freenect2Device is a container of C++ pointer 1419 | ``libfreenect2::Freenect2Device*``. 1420 | 1421 | .. note:: 1422 | Freenect2Device just keeps a pointer of 1423 | ``libfreenect2::Freenect2Device`` that should be allocated and released 1424 | by Freenect2. Freenect2Device itself doesn't own the memory. 1425 | 1426 | 1427 | A valid device can be created by ``openDefaultDevice``: 1428 | 1429 | .. code-block:: python 1430 | 1431 | fn = Freenect2() 1432 | assert fn.enumerateDevices() > 0 1433 | device = fn.openDefaultDevice() 1434 | 1435 | or by ``openDevice``: 1436 | 1437 | .. code-block:: python 1438 | 1439 | fn = Freenect2() 1440 | assert fn.enumerateDevices() > 0 1441 | serial = fn.getDeviceSerialNumber(0) 1442 | device = fn.openDevice(serial) 1443 | 1444 | Attributes 1445 | ---------- 1446 | ptr : ``libfreenect2::Freenect2Device*`` 1447 | 1448 | See also 1449 | -------- 1450 | pylibfreenect2.libfreenect2.Freenect2 1451 | pylibfreenect2.libfreenect2.Freenect2.openDefaultDevice 1452 | pylibfreenect2.libfreenect2.Freenect2.openDevice 1453 | 1454 | """ 1455 | 1456 | cdef _Freenect2Device* ptr 1457 | 1458 | def getSerialNumber(self): 1459 | """Same as ``libfreenect2::Freenect2Device::getSerialNumber()``""" 1460 | return self.ptr.getSerialNumber() 1461 | 1462 | def getFirmwareVersion(self): 1463 | """Same as ``libfreenect2::Freenect2Device::getFirmwareVersion()``""" 1464 | return self.ptr.getFirmwareVersion() 1465 | 1466 | def getColorCameraParams(self): 1467 | """Same as ``libfreenect2::Freenect2Device::getColorCameraParams()``""" 1468 | cdef _Freenect2Device.ColorCameraParams params 1469 | params = self.ptr.getColorCameraParams() 1470 | cdef ColorCameraParams pyparams = ColorCameraParams() 1471 | pyparams.params = params 1472 | return pyparams 1473 | 1474 | def getIrCameraParams(self): 1475 | """Same as ``libfreenect2::Freenect2Device::getIrCameraParams()``""" 1476 | cdef _Freenect2Device.IrCameraParams params 1477 | params = self.ptr.getIrCameraParams() 1478 | cdef IrCameraParams pyparams = IrCameraParams() 1479 | pyparams.params = params 1480 | return pyparams 1481 | 1482 | def setColorFrameListener(self, FrameListener listener): 1483 | """Same as 1484 | ``libfreenect2::Freenect2Device::setColorFrameListener(FrameListener*)`` 1485 | """ 1486 | self.ptr.setColorFrameListener(listener.listener_ptr_alias) 1487 | 1488 | def setIrAndDepthFrameListener(self, FrameListener listener): 1489 | """Same as 1490 | ``libfreenect2::Freenect2Device::setIrAndDepthFrameListener(FrameListener*)`` 1491 | """ 1492 | self.ptr.setIrAndDepthFrameListener(listener.listener_ptr_alias) 1493 | 1494 | def start(self): 1495 | """Same as ``libfreenect2::Freenect2Device::start()``""" 1496 | self.ptr.start() 1497 | 1498 | def startStreams(self, rgb, depth): 1499 | """Same as ``libfreenect2::Freenect2Device::startStreams(bool, bool)``""" 1500 | self.ptr.startStreams(rgb, depth) 1501 | 1502 | def stop(self): 1503 | """Same as ``libfreenect2::Freenect2Device::stop()``""" 1504 | self.ptr.stop() 1505 | 1506 | def close(self): 1507 | """Same as ``libfreenect2::Freenect2Device::close()``""" 1508 | self.ptr.close() 1509 | 1510 | 1511 | cdef class Freenect2: 1512 | """Python interface for ``libfreenect2::Freenect2``. 1513 | 1514 | The Freenect2 is a container of C++ pointer 1515 | ``libfreenect2::Freenect2*``. The pointer of Freenect2 is allocated 1516 | in ``__cinit__`` and released in ``__dealloc__`` method. 1517 | 1518 | Attributes 1519 | ---------- 1520 | ptr : ``libfreenect2::Freenect2*`` 1521 | 1522 | See also 1523 | -------- 1524 | pylibfreenect2.libfreenect2.Freenect2Device 1525 | 1526 | """ 1527 | 1528 | cdef libfreenect2.Freenect2* ptr 1529 | 1530 | def __cinit__(self): 1531 | self.ptr = new libfreenect2.Freenect2(); 1532 | 1533 | def __dealloc__(self): 1534 | if self.ptr is not NULL: 1535 | del self.ptr 1536 | 1537 | def enumerateDevices(self): 1538 | """Same as ``libfreenect2::Freenect2::enumerateDevices()``""" 1539 | return self.ptr.enumerateDevices() 1540 | 1541 | def getDeviceSerialNumber(self, int idx): 1542 | """Same as ``libfreenect2::Freenect2::getDeviceSerialNumber(int)``""" 1543 | return self.ptr.getDeviceSerialNumber(idx) 1544 | 1545 | def getDefaultDeviceSerialNumber(self): 1546 | """Same as ``libfreenect2::Freenect2::getDefaultDeviceSerialNumber()``""" 1547 | return self.ptr.getDefaultDeviceSerialNumber() 1548 | 1549 | cdef __openDevice__intidx(self, int idx, PacketPipeline pipeline): 1550 | cdef _Freenect2Device* dev_ptr 1551 | if pipeline is None: 1552 | dev_ptr = self.ptr.openDevice(idx) 1553 | else: 1554 | dev_ptr = self.ptr.openDevice(idx, pipeline.pipeline_ptr_alias) 1555 | pipeline.owned_by_device = True 1556 | 1557 | cdef Freenect2Device device = Freenect2Device() 1558 | device.ptr = dev_ptr 1559 | return device 1560 | 1561 | cdef __openDevice__stridx(self, string serial, PacketPipeline pipeline): 1562 | cdef _Freenect2Device* dev_ptr 1563 | if pipeline is None: 1564 | dev_ptr = self.ptr.openDevice(serial) 1565 | else: 1566 | dev_ptr = self.ptr.openDevice(serial, pipeline.pipeline_ptr_alias) 1567 | pipeline.owned_by_device = True 1568 | 1569 | cdef Freenect2Device device = Freenect2Device() 1570 | device.ptr = dev_ptr 1571 | return device 1572 | 1573 | def openDevice(self, name, PacketPipeline pipeline=None): 1574 | """Open device by serial number or index 1575 | 1576 | Parameters 1577 | ---------- 1578 | name : int or str 1579 | Serial number (str) or device index (int) 1580 | 1581 | pipeline : PacketPipeline, optional 1582 | Pipeline. Default is None. 1583 | 1584 | Raises 1585 | ------ 1586 | ValueError 1587 | If invalid name is specified. 1588 | 1589 | """ 1590 | if isinstance(name, int): 1591 | return self.__openDevice__intidx(name, pipeline) 1592 | elif isinstance(name, str) or isinstance(name, bytes): 1593 | return self.__openDevice__stridx(name, pipeline) 1594 | else: 1595 | raise ValueError("device name must be of str, bytes or integer type") 1596 | 1597 | def openDefaultDevice(self, PacketPipeline pipeline=None): 1598 | """Open the first device 1599 | 1600 | Parameters 1601 | ---------- 1602 | pipeline : PacketPipeline, optional 1603 | Pipeline. Default is None. 1604 | 1605 | Returns 1606 | ------- 1607 | device : Freenect2Device 1608 | 1609 | """ 1610 | cdef _Freenect2Device* dev_ptr 1611 | 1612 | if pipeline is None: 1613 | dev_ptr = self.ptr.openDefaultDevice() 1614 | else: 1615 | dev_ptr = self.ptr.openDefaultDevice(pipeline.pipeline_ptr_alias) 1616 | pipeline.owned_by_device = True 1617 | 1618 | cdef Freenect2Device device = Freenect2Device() 1619 | device.ptr = dev_ptr 1620 | return device 1621 | --------------------------------------------------------------------------------