├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.rst ├── build.bat ├── build.sh ├── build_under_conda.sh ├── install ├── boost.sh ├── dbow3.bat ├── dbow3.sh └── opencv.sh ├── makedist.bat ├── makedist.sh ├── run.sh └── src ├── CMakeLists.txt ├── FindNumPy.cmake ├── MANIFEST.in ├── __init__.py ├── dbow3.cpp ├── lib ├── container.h ├── conversion.cpp ├── conversion.h ├── np_opencv_converter.cpp ├── np_opencv_converter.hpp └── template.h ├── setup.py └── test ├── __init__.py ├── all.py └── test_import.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | matrix: 4 | include: 5 | - os: linux 6 | env: 7 | - BUILD_PYTHON="python3" 8 | - OPENCV_INSTALL_LOCALLY="ON" 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - libboost-all-dev 15 | - libtbb-dev 16 | - libgtk2.0-dev 17 | - python3-dev 18 | - python3-numpy 19 | - libdc1394-22 20 | - libdc1394-22-dev 21 | - libhdf5-serial-dev 22 | - libjpeg-dev 23 | - libpng12-dev 24 | - libjasper-dev 25 | - libavcodec-dev 26 | - libavformat-dev 27 | - libswscale-dev 28 | - libgstreamer0.10-dev 29 | - libgstreamer-plugins-base0.10-dev 30 | - libv4l-dev 31 | - libtbb-dev 32 | - libqt4-dev 33 | - libmp3lame-dev 34 | - libopencore-amrnb-dev 35 | - libopencore-amrwb-dev 36 | - libtheora-dev 37 | - libvorbis-dev 38 | - libxvidcore-dev 39 | - x264 40 | - v4l-utils 41 | - unzip 42 | - os: linux 43 | env: 44 | - BUILD_PYTHON="python2" 45 | - OPENCV_INSTALL_LOCALLY="ON" 46 | addons: 47 | apt: 48 | sources: 49 | - ubuntu-toolchain-r-test 50 | packages: 51 | - libboost-all-dev 52 | - libtbb-dev 53 | - libgtk2.0-dev 54 | - python-dev 55 | - python-numpy 56 | - libdc1394-22 57 | - libdc1394-22-dev 58 | - libhdf5-serial-dev 59 | - libjpeg-dev 60 | - libpng12-dev 61 | - libjasper-dev 62 | - libavcodec-dev 63 | - libavformat-dev 64 | - libswscale-dev 65 | - libgstreamer0.10-dev 66 | - libgstreamer-plugins-base0.10-dev 67 | - libv4l-dev 68 | - libtbb-dev 69 | - libqt4-dev 70 | - libmp3lame-dev 71 | - libopencore-amrnb-dev 72 | - libopencore-amrwb-dev 73 | - libtheora-dev 74 | - libvorbis-dev 75 | - libxvidcore-dev 76 | - x264 77 | - v4l-utils 78 | - unzip 79 | 80 | script: 81 | - chmod +x build.sh 82 | - ./build.sh 83 | - chmod +x makedist.sh 84 | - ./makedist.sh 85 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM defines the base image 2 | # FROM ubuntu16.04 3 | # FROM ubuntu:latest 4 | FROM nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 5 | 6 | ###################################### 7 | # SECTION 1: Essentials # 8 | ###################################### 9 | 10 | # Set up SSH server (https://docs.docker.com/engine/examples/running_ssh_service/) 11 | RUN apt-get update && apt-get install -y openssh-server 12 | RUN mkdir /var/run/sshd 13 | RUN echo 'root:source' | chpasswd 14 | RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config 15 | # SSH login fix. Otherwise user is kicked off after login 16 | RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd 17 | ENV NOTVISIBLE "in users profile" 18 | RUN echo "export VISIBLE=now" >> /etc/profile 19 | 20 | #Fix SSH mode issue 21 | RUN echo "export PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:\$PATH" >> /root/.bashrc 22 | RUN echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/nvidia/lib:/usr/local/nvidia/lib64" >> /root/.bashrc 23 | 24 | #Update apt-get and upgrade 25 | RUN apt-get update && apt-get install -y --no-install-recommends apt-utils # Fix 26 | RUN apt-get -y upgrade 27 | 28 | #Install python3 pip3 29 | RUN apt-get -y install python3 30 | RUN apt-get -y install python3-pip 31 | RUN pip3 install pip --upgrade 32 | RUN pip3 install numpy scipy 33 | 34 | #Install python2.7 pip 35 | RUN apt-get -y install python2.7 36 | RUN wget https://bootstrap.pypa.io/get-pip.py && python2.7 get-pip.py 37 | RUN pip install pip --upgrade 38 | RUN pip install numpy scipy 39 | 40 | # Set up ssh keys in order to be able to checkout TorrVision 41 | ADD ./install/ssh-keys /root/.ssh 42 | RUN chmod -R 600 /root/.ssh 43 | RUN ssh-keyscan github.com >> ~/.ssh/known_hosts 44 | 45 | #Set everything up for user "user" 46 | RUN mkdir /home/user 47 | RUN cp -R /root/.ssh /home/user/.ssh 48 | RUN chmod -R 600 /home/user/.ssh 49 | 50 | # set up directories 51 | RUN mkdir /slamdoom 52 | RUN mkdir /slamdoom/tmp 53 | RUN mkdir /slamdoom/libs 54 | 55 | RUN apt-get update -y 56 | 57 | ###################################### 58 | # SECTION 2: CV packages # 59 | ###################################### 60 | 61 | ### ------------------------------------------------------------------- 62 | ### install OpenCV 3 with python3 bindings and CUDA 8 63 | ### ------------------------------------------------------------------- 64 | ADD ./install/opencv3 /slamdoom/install/opencv3 65 | RUN chmod +x /slamdoom/install/opencv3/install.sh && /slamdoom/install/opencv3/install.sh /slamdoom/libs python3 66 | 67 | 68 | 69 | #### ------------------------------------------------------------------- 70 | #### Install DBow3 71 | #### ------------------------------------------------------------------- 72 | ADD ./install/dbow3 /slamdoom/install/dbow3 73 | RUN chmod +x /slamdoom/install/dbow3/install.sh && /slamdoom/install/dbow3/install.sh 74 | 75 | 76 | ############################################ 77 | ## SECTION: Additional libraries and tools # 78 | ############################################ 79 | 80 | RUN apt-get install -y vim 81 | 82 | ############################################ 83 | ## SECTION: Final instructions and configs # 84 | ############################################ 85 | 86 | RUN apt-get install -y libcanberra-gtk-module 87 | RUN pip install matplotlib 88 | 89 | # set up matplotlibrc file so have Qt5Agg backend by default 90 | RUN mkdir /root/.matplotlib && touch /root/.matplotlib/matplotlibrc && echo "backend: Qt5Agg" >> /root/.matplotlib/matplotlibrc 91 | RUN apt-get install -y gdb 92 | 93 | RUN apt-get install -y libboost-all-dev 94 | RUN pip install numpy --upgrade 95 | RUN pip3 install numpy --upgrade 96 | 97 | # Fix some linux issue 98 | ENV DEBIAN_FRONTEND teletype 99 | 100 | # Expose ports 101 | EXPOSE 22 102 | 103 | #Start SSH server 104 | CMD ["/usr/sbin/sshd", "-D"] 105 | 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Torr Vision Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | .. image:: https://readthedocs.org/projects/pydbow3/badge/?version=latest 3 | :target: https://pydbow3.readthedocs.io/?badge=latest 4 | :alt: Documentation Status 5 | 6 | .. image:: https://travis-ci.org/foxis/pyDBoW3.svg?branch=master 7 | :target: https://travis-ci.org/foxis/pyDBoW3?branch=master 8 | 9 | .. image:: https://codecov.io/gh/FoxIS/pyDBoW3/branch/master/graph/badge.svg 10 | :target: https://codecov.io/gh/foxis/pyDBoW3 11 | 12 | .. image:: https://img.shields.io/pypi/v/pyDBoW3.svg 13 | :target: https://pypi.python.org/pypi/pyDBoW3 14 | 15 | .. image:: https://img.shields.io/pypi/l/pyDBoW3.svg 16 | :target: https://pypi.python.org/pypi/pyDBoW3 17 | 18 | .. image:: https://img.shields.io/pypi/pyversions/pyDBoW3.svg 19 | :target: https://pypi.python.org/pypi/pyDBoW3 20 | 21 | .. image:: https://img.shields.io/badge/STAR_Me_on_GitHub!--None.svg?style=social 22 | :target: https://github.com/foxis/pyDBoW3 23 | 24 | ------ 25 | 26 | 27 | .. image:: https://img.shields.io/badge/Link-Document-blue.svg 28 | :target: https://pydbow3.readthedocs.io/index.html 29 | 30 | .. image:: https://img.shields.io/badge/Link-API-blue.svg 31 | :target: https://pydbow3.readthedocs.io/py-modindex.html 32 | 33 | .. image:: https://img.shields.io/badge/Link-Source_Code-blue.svg 34 | :target: https://pydbow3.readthedocs.io/py-modindex.html 35 | 36 | .. image:: https://img.shields.io/badge/Link-Install-blue.svg 37 | :target: `install`_ 38 | 39 | .. image:: https://img.shields.io/badge/Link-GitHub-blue.svg 40 | :target: https://github.com/foxis/pyDBoW3 41 | 42 | .. image:: https://img.shields.io/badge/Link-Submit_Issue-blue.svg 43 | :target: https://github.com/foxis/pyDBoW3/issues 44 | 45 | .. image:: https://img.shields.io/badge/Link-Request_Feature-blue.svg 46 | :target: https://github.com/foxis/pyDBoW3/issues 47 | 48 | .. image:: https://img.shields.io/badge/Link-Download-blue.svg 49 | :target: https://pypi.org/pypi/pyDBoW3#files 50 | 51 | 52 | 53 | pyDBoW3 54 | ============== 55 | 56 | Ultra-fast Boost.Python interface for `DBoW3 `_ 57 | 58 | This repo was created in order to interface DBoW algorithm from python in another project 59 | `EasyVision `_. It is being used for a simple topological SLAM 60 | implementation since OpenCV BowKMeansTrainer doesn't work with binary features. 61 | 62 | If you wish you use it on your own it is as easy as: 63 | 64 | .. code-block:: python 65 | 66 | import pyDBoW3 as bow 67 | voc = bow.Vocabulary() 68 | voc.load("/slamdoom/libs/orbslam2/Vocabulary/ORBvoc.txt") 69 | db = bow.Database() 70 | db.setVocabulary(voc) 71 | del voc 72 | # extract features using OpenCV 73 | ... 74 | # add features to database 75 | for features in features_list: 76 | db.add(features) 77 | 78 | # query features 79 | feature_to_query = 1 80 | results = db.query(features_list[feature_to_query]) 81 | 82 | del db 83 | 84 | 85 | This repository was created based on `pyORBSLAM2 `_ and 86 | ndarray to cv::Mat conversion on `numpy-opencv-converter `_. 87 | 88 | .. note:: 89 | 90 | Tested on these platforms: 91 | * OpenCV 3.4.2.16 92 | * Windows 10 msvc 2017 x64 93 | * xenial with Python 2.7, libboost 1.54 (autobuild with travis) 94 | * xenial with Python 3.5, libboost 1.54 (autobuild with travis) 95 | 96 | .. _install: 97 | 98 | Get started 99 | ----------- 100 | 101 | Windows 102 | +++++++ 103 | 104 | Prerequisites: 105 | * OpenCV 106 | * Python with Numpy and opencv-contrib-python 107 | * Boost >1.54 108 | * cmake 109 | * Microsoft Visual Studio 110 | 111 | To build Boost.Python, go to Boost root and run:: 112 | 113 | bootstrap.bat --prefix=/dir/to/Boost.Build 114 | 115 | Then build Boost.Python like this:: 116 | 117 | /dir/to/Boost.Build/b2 --with-python threading=multi variant=release link=static 118 | 119 | To build DBoW3, simply run ``build.bat`` file and then build solution folder in ``install/DBoW3/build`` and then the solution 120 | in ``build`` folder. 121 | 122 | Currently there is no python package generation, so you could simply copy ``pyDBoW3.pyd`` and ``opencv_world*.dll`` files 123 | to your virtual environment. 124 | 125 | Unix 126 | ++++ 127 | 128 | Use ``build.sh`` to build ``build/pyDBoW.so``, which you should then put on your ``PYTHONPATH``. 129 | 130 | Check ``.travis.yml`` for environment variables. 131 | 132 | Mac OSX 133 | ++++ 134 | Use ``build.sh`` to build ``build/pyDBoW.so``, which you should then put on your ``PYTHONPATH``. 135 | 136 | Check ``.travis.yml`` for environment variables. 137 | 138 | .. note:: 139 | 140 | You will probably need to run ``sudo make install`` for ``install/opencv/build`` to install it on your system. 141 | 142 | Using under a conda environment (to use pre-installed version of OpenCV) 143 | ++++ 144 | Build a conda environment, adding boost and cmake to it, something like: 145 | 146 | .. code-block:: bash 147 | 148 | conda create -n test_env python=3.5 opencv=3.3.1 cmake boost matplotlib numpy 149 | 150 | ## Unlink system boost installed by brew 151 | brew unlink boost 152 | 153 | Use ``build_under_conda.sh`` to build ``build/pyDBoW.dylink`` which is symlinked to ``build/pyDBoW.so``. 154 | Add this to your conda environment by creating a ``.PTH`` file under ``/Users//anaconda3/envs/test_env/lib/python3.5/site-packages/pydbow3.pth`` containing ``/Users//pyDBoW3/build`` 155 | 156 | 157 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | cd install 2 | 3 | call dbow3.bat 4 | 5 | cd .. 6 | mkdir build 7 | cd build 8 | 9 | cmake -DBUILD_PYTHON3=ON -DBUILD_STATICALLY_LINKED=OFF -DBOOST_ROOT=c:\boost_1_67_0 -DOpenCV_DIR=c:/opencv/build -DDBoW3_DIR=../install/DBow3/build -DDBoW3_INCLUDE_DIRS=../install/DBow3/src -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 15 2017 Win64" ../src 10 | 11 | cd .. -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | cd ${0%%$(basename $0)} 6 | CWD=`pwd` 7 | 8 | cd install 9 | 10 | chmod +x boost.sh && ./boost.sh || exit 1 11 | 12 | chmod +x opencv.sh && ./opencv.sh || exit 1 13 | 14 | chmod +x dbow3.sh && ./dbow3.sh || exit 1 15 | 16 | cd .. 17 | 18 | mkdir build 19 | cd build 20 | 21 | if [[ "$BUILD_PYTHON" == "python3" ]]; then 22 | BUILD_PYTHON3="ON" 23 | pip3 install wheel 24 | else 25 | BUILD_PYTHON3="OFF" 26 | pip install wheel 27 | fi 28 | 29 | if [[ "$OSTYPE" == "linux-gnu" || "$OSTYPE" == "linux" ]]; then 30 | cmake -DBUILD_PYTHON3=$BUILD_PYTHON3 \ 31 | -DBUILD_STATICALLY_LINKED=OFF \ 32 | -DOpenCV_DIR=$CWD/install/opencv3/build \ 33 | -DDBoW3_DIR=$CWD/install/DBow3/build \ 34 | -DDBoW3_INCLUDE_DIRS=$CWD/install/DBow3/src \ 35 | -DCMAKE_BUILD_TYPE=Release ../src && make 36 | elif [[ "$OSTYPE" == "darwin"* ]]; then 37 | : # no support 38 | elif [[ "$OSTYPE" == "cygwin" ]]; then 39 | : # POSIX compatibility layer and Linux environment emulation for Windows 40 | elif [[ "$OSTYPE" == "msys" ]]; then 41 | : # shell and GNU utilities compiled for Windows as part of MinGW 42 | elif [[ "$OSTYPE" == "win32" ]]; then 43 | : # good luck 44 | elif [[ "$OSTYPE" == "freebsd"* ]]; then 45 | : # ... 46 | else 47 | : # Unknown. 48 | fi 49 | 50 | 51 | if [[ "$OSTYPE" == "darwin"* ]]; then 52 | ln -s pyDBoW3.dylib pyDBoW3.so 53 | fi 54 | -------------------------------------------------------------------------------- /build_under_conda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | cd ${0%%$(basename $0)} 6 | CWD=`pwd` 7 | 8 | cd install 9 | 10 | chmod +x boost.sh && ./boost.sh || exit 1 11 | 12 | chmod +x dbow3.sh && ./dbow3.sh || exit 1 13 | 14 | cd .. 15 | 16 | mkdir build 17 | cd build 18 | 19 | if [[ "$BUILD_PYTHON" == "python3" ]]; then 20 | BUILD_PYTHON3="ON" 21 | pip3 install wheel 22 | else 23 | BUILD_PYTHON3="OFF" 24 | pip install wheel 25 | fi 26 | 27 | if [[ "$OSTYPE" == "linux-gnu" || "$OSTYPE" == "linux" || "$OSTYPE" == "darwin"* ]]; then 28 | cmake -DBUILD_PYTHON3=$BUILD_PYTHON3 \ 29 | -DBUILD_STATICALLY_LINKED=OFF \ 30 | -DDBoW3_DIR=$CWD/install/DBow3/build \ 31 | -DDBoW3_INCLUDE_DIRS=$CWD/install/DBow3/src \ 32 | -DCMAKE_BUILD_TYPE=Release ../src && make 33 | #elif [[ "$OSTYPE" == "darwin"* ]]; then 34 | # : # no support 35 | elif [[ "$OSTYPE" == "cygwin" ]]; then 36 | : # POSIX compatibility layer and Linux environment emulation for Windows 37 | elif [[ "$OSTYPE" == "msys" ]]; then 38 | : # shell and GNU utilities compiled for Windows as part of MinGW 39 | elif [[ "$OSTYPE" == "win32" ]]; then 40 | : # good luck 41 | elif [[ "$OSTYPE" == "freebsd"* ]]; then 42 | : # ... 43 | else 44 | : # Unknown. 45 | fi 46 | 47 | if [[ "$OSTYPE" == "darwin"* ]]; then 48 | ln -s pyDBoW3.dylib pyDBoW3.so 49 | fi 50 | -------------------------------------------------------------------------------- /install/boost.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$OSTYPE" == "linux-gnu" || "$OSTYPE" == "linux" ]]; then 4 | echo "Using system boost package" 5 | exit 6 | fi 7 | 8 | # TODO: download and build libboost.python -------------------------------------------------------------------------------- /install/dbow3.bat: -------------------------------------------------------------------------------- 1 | # Install DBow3 2 | git clone https://github.com/rmsalinas/DBow3 DBow3 3 | cd DBow3 4 | mkdir build 5 | cd build 6 | 7 | cmake -DLIB_INSTALL_DIR=lib -DOpenCV_DIR=c:\opencv\build -DBUILD_SHARED_LIBS=OFF -DUSE_CONTRIB=ON -DBUILD_UTILS=OFF -G "Visual Studio 15 2017 Win64" .. 8 | 9 | cd .. 10 | cd .. -------------------------------------------------------------------------------- /install/dbow3.sh: -------------------------------------------------------------------------------- 1 | # Install DBow3 2 | CWD=`pwd` 3 | git clone https://github.com/rmsalinas/DBow3 DBow3 4 | cd DBow3 5 | mkdir build 6 | cd build 7 | 8 | cmake -DOpenCV_DIR=$CWD/opencv3/build \ 9 | -DBUILD_SHARED_LIBS=OFF \ 10 | -DUSE_CONTRIB=ON \ 11 | -DCMAKE_INSTALL_PREFIX=$CWD/DBow3 \ 12 | -DCMAKE_CXX_FLAGS="-fPIC" \ 13 | -DCMAKE_C_FLAGS="-fPIC" \ 14 | -DBUILD_UTILS=OFF .. && make && make install 15 | cd ../.. 16 | -------------------------------------------------------------------------------- /install/opencv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CWD=`pwd` 4 | VERSION=4.0.1 5 | 6 | git clone https://github.com/opencv/opencv.git opencv3 7 | git clone https://github.com/opencv/opencv_contrib.git opencv3_contrib 8 | cd opencv3_contrib 9 | git checkout $VERSION 10 | cd ../opencv3 11 | git checkout $VERSION 12 | 13 | mkdir build 14 | cd build 15 | 16 | if [ -z "$OPENCV_INSTALL_LOCALLY" ]; then 17 | OPENCV_PREFIX="-DCMAKE_INSTALL_PREFIX=/usr/local" 18 | else 19 | OPENCV_PREFIX="-DCMAKE_INSTALL_PREFIX=$CWD/opencv3" 20 | fi 21 | 22 | if [ "$BUILD_PYTHON" = "python3" ]; then 23 | echo "Building OpenCV with Python3 support" 24 | 25 | PYTHON_INTERP=$(which python3) 26 | PYTHON_LIBS=$(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") 27 | PYTHON_INCLUDES=$(python3 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") 28 | 29 | cmake -DCMAKE_BUILD_TYPE=RELEASE \ 30 | $OPENCV_PREFIX \ 31 | -DOPENCV_EXTRA_MODULES_PATH=$CWD/opencv3_contrib/modules \ 32 | -DWITH_CUDA=OFF \ 33 | -DCUDA_FAST_MATH=ON \ 34 | -DOPENCV_ENABLE_NONFREE=ON \ 35 | -DWITH_OPENGL=OFF \ 36 | -DWITH_OPENCL=ON \ 37 | -DBUILD_WITH_DEBUG_INFO=OFF \ 38 | -DENABLE_FAST_MATH=ON \ 39 | -DBUILD_TIFF=ON \ 40 | -DWITH_CSTRIPES=ON \ 41 | -DWITH_EIGEN=ON \ 42 | -DWITH_QT=OFF \ 43 | -DWITH_GTK=OFF \ 44 | -DWITH_IPP=ON \ 45 | -DWITH_TBB=OFF \ 46 | -DWITH_OPENMP=ON \ 47 | -DWITH_V4L=ON \ 48 | -DWITH_GSTREAMER=OFF \ 49 | -DWITH_VTK=OFF \ 50 | -DBUILD_opencv_java=OFF \ 51 | -DBUILD_EXAMPLES=OFF \ 52 | -DBUILD_opencv_apps=OFF \ 53 | -DBUILD_DOCS=OFF \ 54 | -DBUILD_PERF_TESTS=OFF \ 55 | -DBUILD_TESTS=OFF \ 56 | -DBUILD_opencv_dnn=OFF \ 57 | -DBUILD_opencv_xfeatures2d=ON \ 58 | -DBUILD_opencv_python2=OFF \ 59 | -DBUILD_opencv_python3=ON \ 60 | -DBUILD_NEW_PYTHON_SUPPORT=ON \ 61 | -DPYTHON_DEFAULT_EXECUTABLE=$PYTHON_INTERP \ 62 | -DPYTHON2_EXECUTABLE=$PYTHON_INTERP \ 63 | -DPYTHON2_INCLUDE_DIR=$PYTHON_INCLUDES \ 64 | -DPYTHON2_PACKAGES_PATH=$PYTHON_LIBS \ 65 | -DPYTHON3_EXECUTABLE=$PYTHON_INTERP \ 66 | -DPYTHON3_INCLUDE_DIR=$PYTHON_INCLUDES \ 67 | -DPYTHON3_PACKAGES_PATH=$PYTHON_LIBS \ 68 | .. 69 | make -j4 || exit 1 70 | sudo make install 71 | else 72 | echo "Building OpenCV with Python2 support" 73 | cmake -DCMAKE_BUILD_TYPE=RELEASE \ 74 | -DCMAKE_INSTALL_PREFIX=$CWD/opencv3 \ 75 | -DOPENCV_EXTRA_MODULES_PATH=$CWD/opencv3_contrib/modules \ 76 | -DWITH_CUDA=OFF \ 77 | -DCUDA_GENERATION=Kepler \ 78 | -DWITH_CUBLAS=ON \ 79 | -DCUDA_FAST_MATH=ON \ 80 | -DWITH_NVCUVID=ON \ 81 | -DWITH_OPENGL=OFF \ 82 | -DWITH_OPENCL=OFF \ 83 | -DENABLE_AVX=ON \ 84 | -DENABLE_FAST_MATH=ON \ 85 | -DBUILD_TIFF=ON \ 86 | -DWITH_CSTRIPES=ON \ 87 | -DWITH_EIGEN=OFF \ 88 | -DWITH_IPP=ON \ 89 | -DWITH_TBB=ON \ 90 | -DWITH_OPENMP=ON \ 91 | -DENABLE_SSE42=ON \ 92 | -DWITH_V4L=ON \ 93 | -DWITH_VTK=OFF \ 94 | -DBUILD_opencv_java=OFF \ 95 | -DBUILD_EXAMPLES=OFF \ 96 | -DBUILD_opencv_apps=OFF \ 97 | -DBUILD_DOCS=OFF \ 98 | -DBUILD_PERF_TESTS=OFF \ 99 | -DBUILD_TESTS=OFF \ 100 | -DBUILD_opencv_dnn=OFF \ 101 | -DBUILD_opencv_xfeatures2d=ON \ 102 | -DBUILD_opencv_python2=ON \ 103 | -DPYTHON_EXECUTABLE=$(which python) \ 104 | -DPYTHON_INCLUDE_DIR=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \ 105 | -DPYTHON_PACKAGES_PATH=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") \ 106 | .. 107 | make -j12 || exit 1 108 | sudo make install 109 | fi 110 | -------------------------------------------------------------------------------- /makedist.bat: -------------------------------------------------------------------------------- 1 | cd build 2 | 3 | mkdir dist 4 | cd dist 5 | mkdir pyDBoW3 6 | copy ..\Release\pyDBoW3.pyd pyDBoW3 7 | copy c:\opencv\build\x64\vc15\bin\opencv_world400.dll pyDBoW3 8 | copy ..\..\src\__init__.py pyDBoW3 9 | copy ..\..\src\setup.py . 10 | copy ..\..\src\MANIFEST.in . 11 | 12 | python setup.py bdist_wheel 13 | 14 | cd ..\.. -------------------------------------------------------------------------------- /makedist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | cd build 5 | mkdir dist 6 | cd dist 7 | mkdir pyDBoW3 8 | cp ../pyDBoW3.so pyDBoW3 9 | cp ../../src/__init__.py pyDBoW3 10 | cp ../../src/setup.py . 11 | cp ../../src/MANIFEST.in . 12 | 13 | if [[ "$BUILD_PYTHON" == "python3" ]]; then 14 | python3 setup.py bdist_wheel 15 | else 16 | python3 setup.py bdist_wheel 17 | fi 18 | 19 | cd ../.. 20 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Ensure that you have installed nvidia-docker and the latest nvidia graphics driver on host! 3 | 4 | SCRIPT=$(readlink -f "$0") 5 | SCRIPTPATH=$(dirname "$SCRIPT") 6 | 7 | # Build and run the image 8 | echo "Building image..." 9 | sudo nvidia-docker build --build-arg pass=$SPASSWORD -t dbow3 . 10 | echo "Removing older image..." 11 | sudo nvidia-docker rm -f dbow30 12 | echo "Running image..." 13 | sudo nvidia-docker run --privileged -d -v /dev:/dev --ipc=host -p 52022:22 --name dbow30 \ 14 | -v $SCRIPTPATH/src:/dbow3/src \ 15 | -v $SCRIPTPATH/docker_share:/dbow3/docker_share \ 16 | orbslam 17 | 18 | # Retrieve IP and port of Docker instance and container 19 | CONTAINERIP=$(sudo nvidia-docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' orbslam0); 20 | DOCKERIP=$(/sbin/ifconfig docker0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}') 21 | echo "CONTAINER IP:":$CONTAINERIP 22 | echo "DOCKER IP:":$DOCKERIP 23 | DOCKERPORTSTRING=$(sudo nvidia-docker port dbow30 22) 24 | DOCKERPORT=${DOCKERPORTSTRING##*:} 25 | echo "DOCKER PUBLISHED PORT 22 -> :":$DOCKERPORT 26 | echo "IdentityFile $SCRIPTPATH/.sshauth/dbow3.rsa" >> ~/.ssh/config 27 | ssh-keygen -f ~/.ssh/known_hosts -R [$DOCKERIP]:$DOCKERPORT 28 | echo "Login password is: ":$SPASSWORD 29 | #ssh -o StrictHostKeyChecking=no root@$DOCKERIP -X -p $DOCKERPORT 30 | # ssh -X -p $DOCKERPORT -v -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@$DOCKERIP 31 | echo "LOGIN LIKE: ssh -o StrictHostKeyChecking=no -X -p $DOCKERPORT root@$DOCKERIP" >> login.txt 32 | ssh -o StrictHostKeyChecking=no -X -p $DOCKERPORT root@$DOCKERIP 33 | 34 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Disable in-source builds to prevent source tree corruption. 2 | if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}") 3 | message(FATAL_ERROR " 4 | FATAL: In-source builds are not allowed. 5 | You should create a separate directory for build files. 6 | ") 7 | endif() 8 | 9 | cmake_minimum_required(VERSION 2.8) 10 | project(pyDBoW3) 11 | 12 | # Project version 13 | #------------------------------------------------------------------------------ 14 | set(pyDBOW3_MAJOR_VERSION 1) 15 | set(pyDBOW3_MINOR_VERSION 1) 16 | set(pyDBOW3_PATCH_VERSION 1) 17 | set(pyDBOW3_VERSION ${pyDBOW3_MAJOR_VERSION}.${pyDBOW3_MINOR_VERSION}.${pyDBOW3_PATCH_VERSION}) 18 | set(pyDBOW3_VERSION_STR ${pyDBOW3_VERSION}) 19 | set(pyDBOW3_VERSION_ID ${pyDBOW3_MAJOR_VERSION}${pyDBOW3_MINOR_VERSION}${pyDBOW3_PATCH_VERSION}) 20 | 21 | 22 | # Building options 23 | #------------------------------------------------------------------------------- 24 | option(BUILD_PYTHON3 "Build DBow3 Python3 binding instead of default Python2." OFF) 25 | OPTION(BUILD_STATICALLY_LINKED "Set to OFF to link with opencv and DBoW3 dynamically" ON) 26 | 27 | SET(Boost_DEBUG OFF) 28 | 29 | if(BUILD_PYTHON3) 30 | set(PYTHON_VERSION 3) 31 | else() 32 | set(PYTHON_VERSION 2) 33 | endif() 34 | 35 | message( STATUS "BUILD_PYTHON3 = ${BUILD_PYTHON3}") 36 | message( STATUS "PYTHON_VERSION = ${PYTHON_VERSION}") 37 | 38 | 39 | # CMake options 40 | #----------------------------------------------------------------------------------------------------------------------- 41 | 42 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3") 43 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -Wall -O3") 44 | 45 | # Check C++11 or C++0x support 46 | include(CheckCXXCompilerFlag) 47 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 48 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 49 | if(COMPILER_SUPPORTS_CXX11) 50 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 51 | add_definitions(-DCOMPILEDWITHC11) 52 | message(STATUS "Using flag -std=c++11.") 53 | elseif(COMPILER_SUPPORTS_CXX0X) 54 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 55 | add_definitions(-DCOMPILEDWITHC0X) 56 | message(STATUS "Using flag -std=c++0x.") 57 | else() 58 | #message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 59 | endif() 60 | 61 | if (COMMAND cmake_policy) 62 | cmake_policy(SET CMP0003 NEW) 63 | cmake_policy(SET CMP0042 NEW) 64 | endif (COMMAND cmake_policy) 65 | 66 | # Add cmake_modules to module 67 | set(CMAKE_MODULE_PATH 68 | ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" 69 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") 70 | 71 | # Set the release mode if not specified 72 | if (NOT CMAKE_BUILD_TYPE) 73 | set(CMAKE_BUILD_TYPE Release) 74 | endif () 75 | 76 | if (CMAKE_COMPILER_IS_GNUCXX) 77 | add_definitions("-fPIC") 78 | endif () 79 | 80 | 81 | #----------------------------------------------------------------------------------------------------------------------- 82 | 83 | #LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../../cmake_modules) 84 | 85 | IF(NOT UNIX) 86 | SET(OpenCV_USE_STATIC_LIBS ON) 87 | ENDIF() 88 | find_package(OpenCV REQUIRED) 89 | 90 | SET(DBoW3_USE_STATIC_LIBS ON) 91 | find_package(DBoW3 REQUIRED) 92 | 93 | #----------------------------------------------------------------------------------------------------------------------- 94 | # Python binding 95 | #----------------------------------------------------------------------------------------------------------------------- 96 | 97 | if (BUILD_PYTHON3) 98 | FIND_PACKAGE(PythonInterp 3 REQUIRED) 99 | FIND_PACKAGE(PythonLibs 3 REQUIRED) 100 | else() 101 | SET(PythonLibs_FIND_VERSION 2.7) 102 | FIND_PACKAGE(PythonInterp 2.7 REQUIRED) 103 | FIND_PACKAGE(PythonLibs 2.7 REQUIRED) 104 | endif() 105 | 106 | if(PYTHON_VERSION_STRING VERSION_LESS 2.7) 107 | message(WARNING "Python version less than 2.7: \"${PYTHON_VERSION_STRING}\".") 108 | endif() 109 | 110 | FIND_PACKAGE(NumPy REQUIRED) 111 | 112 | IF (NOT UNIX) 113 | SET(Boost_USE_STATIC_LIBS ON) 114 | add_definitions(-DBOOST_PYTHON_STATIC_LIB) 115 | ENDIF() 116 | SET(Boost_USE_MULTITHREADED ON) 117 | SET(Boost_USE_STATIC_RUNTIME OFF) 118 | SET(BOOST_ALL_NO_LIB ON) 119 | 120 | FIND_PACKAGE(Boost 1.54) 121 | 122 | if (NOT UNIX) 123 | FIND_PACKAGE(Boost COMPONENTS python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} REQUIRED) 124 | elseif(APPLE) 125 | FIND_PACKAGE(Boost 1.54 COMPONENTS python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} REQUIRED) 126 | else() 127 | FIND_PACKAGE(Boost 1.54 COMPONENTS python-py${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} REQUIRED) 128 | endif() 129 | 130 | # This is a hack, since DBoW3 report weird library path 131 | if (UNIX) 132 | LINK_DIRECTORIES(${DBoW3_INCLUDE_DIRS}/../lib) 133 | else() 134 | LINK_DIRECTORIES(../install/DBow3/build/bin/Release) 135 | endif() 136 | 137 | if (UNIX) 138 | INCLUDE_DIRECTORIES( 139 | ${OpenCV_INCLUDE_DIRS} 140 | ${Boost_INCLUDE_DIRS} 141 | ${PYTHON_INCLUDE_DIRS} 142 | ${NUMPY_INCLUDES} 143 | ${DBoW3_INCLUDE_DIRS}/DBoW3 144 | lib/) 145 | else() 146 | INCLUDE_DIRECTORIES( 147 | ${OpenCV_INCLUDE_DIRS} 148 | ${Boost_INCLUDE_DIRS} 149 | ${PYTHON_INCLUDE_DIRS} 150 | ${NUMPY_INCLUDES} 151 | ../install/DBow3/src 152 | lib/) 153 | endif() 154 | 155 | if (BUILD_STATICALLY_LINKED) 156 | ADD_DEFINITIONS(-DBOOST_PYTHON_STATIC_LIB) 157 | endif () 158 | 159 | # Build np<=>opencv converter library 160 | ADD_LIBRARY(np_opencv_converter lib/conversion.cpp lib/np_opencv_converter.cpp) 161 | TARGET_COMPILE_OPTIONS(np_opencv_converter PRIVATE -DBOOST_ALL_NO_LIB) 162 | if (NOT UNIX) 163 | elseif (APPLE) 164 | TARGET_LINK_LIBRARIES(np_opencv_converter ${OpenCV_LIBRARIES} ${Boost_LIBRARIES}) 165 | set_target_properties(np_opencv_converter PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") 166 | else() 167 | TARGET_LINK_LIBRARIES(np_opencv_converter ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) 168 | endif() 169 | 170 | 171 | # Build python extension 172 | ADD_LIBRARY(pyDBoW3 SHARED dbow3.cpp) 173 | TARGET_COMPILE_OPTIONS(pyDBoW3 PRIVATE -DBOOST_ALL_NO_LIB) 174 | 175 | if (NOT UNIX) 176 | TARGET_LINK_LIBRARIES(pyDBoW3 np_opencv_converter ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${DBoW3_LIBRARIES} "-static") 177 | SET_TARGET_PROPERTIES(pyDBoW3 PROPERTIES PREFIX "" SUFFIX ".pyd") 178 | elseif (APPLE) 179 | TARGET_LINK_LIBRARIES(pyDBoW3 np_opencv_converter ${DBoW3_LIBRARIES}) 180 | SET_TARGET_PROPERTIES(pyDBoW3 PROPERTIES PREFIX "" LINK_FLAGS "-undefined dynamic_lookup") 181 | else () 182 | TARGET_LINK_LIBRARIES(pyDBoW3 np_opencv_converter ${DBoW3_LIBRARIES}) 183 | SET_TARGET_PROPERTIES(pyDBoW3 PROPERTIES PREFIX "") 184 | endif () 185 | 186 | 187 | # ---------------------------------------------------------------------------- 188 | # display status message for important variables 189 | # ---------------------------------------------------------------------------- 190 | message( STATUS ) 191 | MESSAGE( STATUS "-------------------------------------------------------------------------------" ) 192 | message( STATUS "General configuration for ${PROJECT_NAME} ${PROJECT_VERSION}") 193 | MESSAGE( STATUS "-------------------------------------------------------------------------------" ) 194 | message(" Built as static libs?:" ${BUILD_STATICALLY_LINKED}) 195 | message(" Compiler:" "${CMAKE_COMPILER}" "${CMAKE_CXX_COMPILER}") 196 | 197 | message( STATUS "Build Type: ${CMAKE_BUILD_TYPE}") 198 | message( STATUS "C++ flags (Release): ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}") 199 | message( STATUS "C++ flags (Debug): ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") 200 | message( STATUS "C++ flags (Relase+Debug): ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") 201 | 202 | message( STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 203 | message( STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") 204 | message(STATUS "PYTHON_EXECUTABLE = ${PYTHON_EXECUTABLE}") 205 | message(STATUS "PYTHON_LIBRARIES = ${PYTHON_LIBRARIES}") 206 | message(STATUS "PYTHON_INCLUDE_DIRS = ${PYTHON_INCLUDE_DIRS}") 207 | message(STATUS "NUMPY_LIBRARIES = ${NUMPY_LIBRARIES}") 208 | message(STATUS "NUMPY_INCLUDE_DIRS = ${NUMPY_INCLUDES}") 209 | message(STATUS "DBoW3_INCLUDE_DIRS = ${DBoW3_INCLUDE_DIRS}") 210 | message(STATUS "DBoW3_LIB_DIR = ${DBoW3_LIB_DIR}") 211 | message(STATUS "DBoW3_LIBRARIES = ${DBoW3_LIBRARIES}") 212 | message(STATUS "Boost_LIBRARIES = ${Boost_LIBRARIES}") 213 | message(STATUS "PROJECT LIBRARIES = ${PROJECT_LIBRARIES}") 214 | -------------------------------------------------------------------------------- /src/FindNumPy.cmake: -------------------------------------------------------------------------------- 1 | 2 | #------------------------------------------------------------------------------- 3 | # Copyright (c) 2013, Lars Baehren 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without modification, 7 | # are permitted provided that the following conditions are met: 8 | # 9 | # * Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # 15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | #------------------------------------------------------------------------------- 26 | 27 | # - Check for the presence of NumPy 28 | # 29 | # The following variables are set when NumPy is found: 30 | # NUMPY_FOUND = Set to true, if all components of NUMPY have been found. 31 | # NUMPY_INCLUDES = Include path for the header files of NUMPY 32 | # NUMPY_LIBRARIES = Link these to use NUMPY 33 | # NUMPY_LFLAGS = Linker flags (optional) 34 | 35 | if (NOT NUMPY_FOUND) 36 | 37 | if (NOT NUMPY_ROOT_DIR) 38 | set (NUMPY_ROOT_DIR ${CMAKE_INSTALL_PREFIX}) 39 | endif (NOT NUMPY_ROOT_DIR) 40 | 41 | if (NOT PYTHONINTERP_FOUND) 42 | find_package (PythonInterp) 43 | endif (NOT PYTHONINTERP_FOUND) 44 | 45 | ##__________________________________________________________________________ 46 | ## Check for the header files 47 | 48 | ## Use Python to determine the include directory 49 | execute_process ( 50 | COMMAND ${PYTHON_EXECUTABLE} -c import\ numpy\;\ print\(numpy.get_include\(\)\)\; 51 | ERROR_VARIABLE NUMPY_FIND_ERROR 52 | RESULT_VARIABLE NUMPY_FIND_RESULT 53 | OUTPUT_VARIABLE NUMPY_FIND_OUTPUT 54 | OUTPUT_STRIP_TRAILING_WHITESPACE 55 | ) 56 | ## process the output from the execution of the command 57 | if (NOT NUMPY_FIND_RESULT) 58 | set (NUMPY_INCLUDES ${NUMPY_FIND_OUTPUT}) 59 | endif (NOT NUMPY_FIND_RESULT) 60 | 61 | ##__________________________________________________________________________ 62 | ## Check for the library 63 | 64 | unset (NUMPY_LIBRARIES) 65 | 66 | if (PYTHON_SITE_PACKAGES) 67 | find_library (NUMPY_NPYMATH_LIBRARY npymath 68 | HINTS ${PYTHON_SITE_PACKAGES}/numpy/core 69 | PATH_SUFFIXES lib 70 | ) 71 | if (NUMPY_NPYMATH_LIBRARY) 72 | list (APPEND NUMPY_LIBRARIES ${NUMPY_NPYMATH_LIBRARY}) 73 | endif (NUMPY_NPYMATH_LIBRARY) 74 | endif (PYTHON_SITE_PACKAGES) 75 | 76 | ##__________________________________________________________________________ 77 | ## Get API version of NumPy from 'numpy/numpyconfig.h' 78 | 79 | if (PYTHON_EXECUTABLE) 80 | execute_process ( 81 | COMMAND ${PYTHON_EXECUTABLE} -c import\ numpy\;\ print\(numpy.__version__\)\; 82 | ERROR_VARIABLE NUMPY_API_VERSION_ERROR 83 | RESULT_VARIABLE NUMPY_API_VERSION_RESULT 84 | OUTPUT_VARIABLE NUMPY_API_VERSION 85 | OUTPUT_STRIP_TRAILING_WHITESPACE 86 | ) 87 | else () 88 | ## Backup procedure: extract version number directly from the header file 89 | if (NUMPY_INCLUDES) 90 | find_file (HAVE_NUMPYCONFIG_H numpy/numpyconfig.h 91 | HINTS ${NUMPY_INCLUDES} 92 | ) 93 | endif (NUMPY_INCLUDES) 94 | endif () 95 | 96 | ## Dissect full version number into major, minor and patch version 97 | if (NUMPY_API_VERSION) 98 | string (REGEX REPLACE "\\." ";" _tmp ${NUMPY_API_VERSION}) 99 | list (GET _tmp 0 NUMPY_API_VERSION_MAJOR) 100 | list (GET _tmp 1 NUMPY_API_VERSION_MINOR) 101 | list (GET _tmp 2 NUMPY_API_VERSION_PATCH) 102 | endif (NUMPY_API_VERSION) 103 | 104 | ##__________________________________________________________________________ 105 | ## Actions taken when all components have been found 106 | 107 | find_package_handle_standard_args (NUMPY DEFAULT_MSG NUMPY_INCLUDES) 108 | 109 | if (NUMPY_FOUND) 110 | if (NOT NUMPY_FIND_QUIETLY) 111 | message (STATUS "Found components for NumPy") 112 | message (STATUS "NUMPY_ROOT_DIR = ${NUMPY_ROOT_DIR}") 113 | message (STATUS "NUMPY_INCLUDES = ${NUMPY_INCLUDES}") 114 | message (STATUS "NUMPY_LIBRARIES = ${NUMPY_LIBRARIES}") 115 | message (STATUS "NUMPY_API_VERSION = ${NUMPY_API_VERSION}") 116 | endif (NOT NUMPY_FIND_QUIETLY) 117 | else (NUMPY_FOUND) 118 | if (NUMPY_FIND_REQUIRED) 119 | message (FATAL_ERROR "Could not find NUMPY!") 120 | endif (NUMPY_FIND_REQUIRED) 121 | endif (NUMPY_FOUND) 122 | 123 | ##__________________________________________________________________________ 124 | ## Mark advanced variables 125 | 126 | mark_as_advanced ( 127 | NUMPY_ROOT_DIR 128 | NUMPY_INCLUDES 129 | NUMPY_LIBRARIES 130 | ) 131 | 132 | endif (NOT NUMPY_FOUND) 133 | -------------------------------------------------------------------------------- /src/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include ../../README.rst 2 | include pyDBoW3/*.pyd 3 | include pyDBoW3/*.dll -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Python wrappers for DBoW3 library 5 | """ 6 | 7 | __version__ = "0.3" 8 | __short_description__ = "Python wrappers for DBoW3 library." 9 | __license__ = "MIT" 10 | __author__ = "Andrius Mikonis" 11 | __author_email__ = "andrius.mikonis@gmail.com" 12 | __maintainer__ = "Andrius Mikonis" 13 | __maintainer_email__ = "andrius.mikonis@gmail.com" 14 | __github_username__ = "FoxIS" 15 | __all__ = [ 16 | "pyDBoW3" 17 | ] 18 | 19 | from .pyDBoW3 import * -------------------------------------------------------------------------------- /src/dbow3.cpp: -------------------------------------------------------------------------------- 1 | // Author: Andrius Mikonis (andrius.mikonis@gmail.com) 2 | // License: BSD 3 | // Last modified: Feb 12, 2019 4 | 5 | // Wrapper for most external modules 6 | #include 7 | #include 8 | #include 9 | 10 | // Opencv includes 11 | #include 12 | 13 | // np_opencv_converter 14 | #include "np_opencv_converter.hpp" 15 | 16 | // DBoW3 17 | #include "DBoW3.h" 18 | 19 | namespace py = boost::python; 20 | 21 | cv::Mat test_np_mat(const cv::Mat& in) { 22 | std::cerr << "in: " << in << std::endl; 23 | std::cerr << "sz: " << in.size() << std::endl; 24 | return in.clone(); 25 | } 26 | 27 | cv::Mat test_with_args(const cv::Mat_& in, const int& var1 = 1, 28 | const double& var2 = 10.0, const std::string& name = std::string("test_name")) { 29 | std::cerr << "in: " << in << std::endl; 30 | std::cerr << "sz: " << in.size() << std::endl; 31 | std::cerr << "Returning transpose" << std::endl; 32 | return in.t(); 33 | } 34 | 35 | class GenericWrapper { 36 | public: 37 | GenericWrapper(const int& _var_int = 1, const float& _var_float = 1.f, 38 | const double& _var_double = 1.f, const std::string& _var_string = std::string("test_string")) 39 | : var_int(_var_int), var_float(_var_float), var_double(_var_double), var_string(_var_string) 40 | { 41 | 42 | } 43 | 44 | cv::Mat process(const cv::Mat& in) { 45 | std::cerr << "in: " << in << std::endl; 46 | std::cerr << "sz: " << in.size() << std::endl; 47 | std::cerr << "Returning transpose" << std::endl; 48 | return in.t(); 49 | } 50 | 51 | private: 52 | int var_int; 53 | float var_float; 54 | double var_double; 55 | std::string var_string; 56 | }; 57 | 58 | class Vocabulary 59 | { 60 | public: 61 | Vocabulary(int k = 10, int L = 5, DBoW3::WeightingType weighting = DBoW3::TF_IDF, DBoW3::ScoringType scoring = DBoW3::L1_NORM, const std::string& path = std::string()) { 62 | vocabulary = new DBoW3::Vocabulary(k, L, weighting, scoring); 63 | if (!path.empty()) 64 | load(path); 65 | } 66 | ~Vocabulary() { 67 | delete vocabulary; 68 | } 69 | 70 | void create(const std::vector &training_features) { 71 | vocabulary->create(training_features); 72 | } 73 | 74 | void clear() { 75 | vocabulary->clear(); 76 | } 77 | 78 | void load(const std::string& path) { 79 | vocabulary->load(path); 80 | } 81 | 82 | void save(const std::string& path, bool binary_compressed = true) { 83 | vocabulary->save(path, binary_compressed); 84 | } 85 | 86 | DBoW3::BowVector transform(const std::vector & features) { 87 | DBoW3::BowVector word; 88 | vocabulary->transform(features, word); 89 | return word; 90 | } 91 | 92 | double score(const DBoW3::BowVector &A, const DBoW3::BowVector &B) { 93 | return vocabulary->score(A, B); 94 | } 95 | 96 | DBoW3::Vocabulary * vocabulary; 97 | }; 98 | 99 | class Database 100 | { 101 | public: 102 | Database(const std::string& path = std::string()) { 103 | if (path.empty()) 104 | database = new DBoW3::Database(); 105 | else 106 | database = new DBoW3::Database(path); 107 | } 108 | ~Database() { 109 | delete database; 110 | } 111 | 112 | void setVocabulary(const Vocabulary& vocabulary, bool use_di, int di_levels=0) { 113 | database->setVocabulary(*vocabulary.vocabulary, use_di, di_levels); 114 | } 115 | 116 | unsigned int add(const cv::Mat & features) { 117 | return database->add(features, NULL, NULL); 118 | } 119 | 120 | std::vector query(const cv::Mat &features, int max_results = 1, int max_id = -1) { 121 | DBoW3::QueryResults results; 122 | database->query(features, results, max_results, max_id); 123 | return results; 124 | } 125 | 126 | void save(const std::string &filename) const { 127 | database->save(filename); 128 | } 129 | 130 | void load(const std::string &filename) { 131 | database->load(filename); 132 | } 133 | 134 | void loadVocabulary(const std::string &filename, bool use_di, int di_levels=0) { 135 | DBoW3::Vocabulary voc; 136 | voc.load(filename); 137 | database->setVocabulary(voc, use_di, di_levels); 138 | } 139 | 140 | 141 | private: 142 | DBoW3::Database * database; 143 | }; 144 | 145 | // Wrap a few functions and classes for testing purposes 146 | namespace fs { 147 | namespace python { 148 | 149 | BOOST_PYTHON_MODULE(pyDBoW3) 150 | { 151 | // Main types export 152 | fs::python::init_and_export_converters(); 153 | py::scope scope = py::scope(); 154 | 155 | py::enum_("WeightingType") 156 | .value("TF_IDF", DBoW3::TF_IDF) 157 | .value("TF", DBoW3::TF) 158 | .value("IDF", DBoW3::IDF) 159 | .value("BINARY", DBoW3::BINARY); 160 | 161 | py::enum_("ScoringType") 162 | .value("L1_NORM", DBoW3::L1_NORM) 163 | .value("L2_NORM", DBoW3::L2_NORM) 164 | .value("CHI_SQUARE", DBoW3::CHI_SQUARE) 165 | .value("KL", DBoW3::KL) 166 | .value("BHATTACHARYYA", DBoW3::BHATTACHARYYA) 167 | .value("DOT_PRODUCT", DBoW3::DOT_PRODUCT); 168 | 169 | // Class 170 | py::class_("Vocabulary") 171 | .def(py::init >( 172 | (py::arg("k") = 10, py::arg("L") = 5, py::arg("weighting") = DBoW3::TF_IDF, py::arg("scoring") = DBoW3::L1_NORM, 173 | py::arg("path") = std::string()))) 174 | .def("load", &Vocabulary::load) 175 | .def("save", &Vocabulary::save) 176 | .def("create", &Vocabulary::create) 177 | .def("transform", &Vocabulary::transform, py::return_value_policy()) 178 | .def("score", &Vocabulary::score) 179 | .def("clear", &Vocabulary::clear); 180 | 181 | py::class_("Database") 182 | .def(py::init >(py::arg("path") = std::string())) 183 | .def("setVocabulary", &Database::setVocabulary) 184 | .def("save", &Database::save) 185 | .def("load", &Database::load) 186 | .def("loadVocabulary", &Database::loadVocabulary) 187 | .def("add", &Database::add) 188 | .def("query", &Database::query, py::return_value_policy()); 189 | 190 | py::class_("Result") 191 | .def_readonly("Id", &DBoW3::Result::Id) 192 | .def_readonly("Score", &DBoW3::Result::Score) 193 | .def_readonly("nWords", &DBoW3::Result::nWords) 194 | .def_readonly("bhatScore", &DBoW3::Result::bhatScore) 195 | .def_readonly("chiScore", &DBoW3::Result::chiScore) 196 | .def_readonly("sumCommonVi", &DBoW3::Result::sumCommonVi) 197 | .def_readonly("sumCommonWi", &DBoW3::Result::sumCommonWi) 198 | .def_readonly("expectedChiScore", &DBoW3::Result::expectedChiScore); 199 | } 200 | 201 | } // namespace fs 202 | } // namespace python 203 | -------------------------------------------------------------------------------- /src/lib/container.h: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // Note: Stripped from pyxx project 3 | 4 | #ifndef UTILS_CONTAINER_H_ 5 | #define UTILS_CONTAINER_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace py = boost::python; 20 | 21 | template 22 | struct expose_template_type< std::vector > : 23 | public expose_template_type_base< std::vector > 24 | { 25 | typedef expose_template_type_base< std::vector > base_type; 26 | typedef expose_template_type< std::vector > this_type; 27 | typedef std::vector wrapped_type; 28 | 29 | expose_template_type() 30 | { 31 | ::expose_template_type(); 32 | if( !base_type::wrapped() ) 33 | { 34 | py::to_python_converter< wrapped_type, this_type >(); 35 | py::converter::registry::push_back( 36 | this_type::convertible, 37 | this_type::construct, 38 | py::type_id< wrapped_type >() ); 39 | 40 | } 41 | } 42 | 43 | static PyObject * convert( const wrapped_type & container) 44 | { 45 | py::list l; 46 | for(typename wrapped_type::const_iterator iter = container.begin(); iter != container.end(); iter++) 47 | { 48 | l.append( py::object( *iter ) ); 49 | } 50 | Py_INCREF( l.ptr() ); 51 | return l.ptr(); 52 | } 53 | 54 | static void * convertible( PyObject * py_obj) 55 | { 56 | // we are supposed to indicate whether or not we can convert this 57 | // we don't really know, but we'll try any sequence 58 | if( PySequence_Check(py_obj) ) 59 | return py_obj; 60 | return 0; 61 | } 62 | 63 | static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data) 64 | { 65 | using namespace boost::python; 66 | typedef converter::rvalue_from_python_storage< wrapped_type > storage_t; 67 | 68 | storage_t* the_storage = reinterpret_cast( data ); 69 | void* memory_chunk = the_storage->storage.bytes; 70 | wrapped_type * newvec = new (memory_chunk) wrapped_type; 71 | data->convertible = memory_chunk; 72 | 73 | object sequence(handle<>( borrowed( py_obj ) ) ); 74 | 75 | for(int idx = 0; idx < len(sequence);idx++) 76 | { 77 | newvec->push_back( extract( sequence[idx] )() ); 78 | } 79 | 80 | } 81 | 82 | }; 83 | 84 | template 85 | struct expose_template_type< std::map > : 86 | public expose_template_type_base< std::map > 87 | { 88 | typedef std::map wrapped_type; 89 | typedef expose_template_type_base< wrapped_type > base_type; 90 | typedef expose_template_type< wrapped_type > this_type; 91 | 92 | expose_template_type() 93 | { 94 | if( !base_type::wrapped() ) 95 | { 96 | py::to_python_converter< wrapped_type, this_type >(); 97 | py::converter::registry::push_back( 98 | this_type::convertible, 99 | this_type::construct, 100 | py::type_id< wrapped_type >() ); 101 | 102 | } 103 | } 104 | 105 | static PyObject * convert( const wrapped_type & container) 106 | { 107 | py::dict d; 108 | for(typename wrapped_type::const_iterator iter = container.begin(); iter != container.end(); iter++) 109 | { 110 | d[iter->first] = py::object(iter->second); 111 | } 112 | Py_INCREF( d.ptr() ); 113 | return d.ptr(); 114 | } 115 | 116 | static void * convertible( PyObject * py_obj) 117 | { 118 | // we are supposed to indicate whether or not we can convert this 119 | // we don't really know, but we'll try any sequence 120 | if( PyMapping_Check(py_obj) ) 121 | return py_obj; 122 | return 0; 123 | } 124 | 125 | static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data) 126 | { 127 | using namespace boost::python; 128 | typedef converter::rvalue_from_python_storage< wrapped_type > storage_t; 129 | 130 | storage_t* the_storage = reinterpret_cast( data ); 131 | void* memory_chunk = the_storage->storage.bytes; 132 | wrapped_type * newvec = new (memory_chunk) wrapped_type; 133 | data->convertible = memory_chunk; 134 | 135 | object sequence(handle<>( borrowed( py_obj ) ) ); 136 | sequence = sequence.attr("items")(); 137 | 138 | for(int idx = 0; idx < len(sequence);idx++) 139 | { 140 | Key key = py::extract(sequence[idx][0])(); 141 | Value value = py::extract(sequence[idx][1])(); 142 | (*newvec)[key] = value; 143 | } 144 | 145 | } 146 | 147 | }; 148 | 149 | template 150 | struct expose_template_type< typename std::pair > : 151 | public expose_template_type_base< std::pair > 152 | { 153 | typedef std::pair wrapped_type; 154 | typedef expose_template_type_base< wrapped_type > base_type; 155 | typedef expose_template_type< wrapped_type > this_type; 156 | 157 | expose_template_type() 158 | { 159 | if( !base_type::wrapped() ) 160 | { 161 | py::converter::registry::push_back( 162 | this_type::convertible, 163 | this_type::construct, 164 | py::type_id< wrapped_type >() ); 165 | 166 | } 167 | } 168 | 169 | static void * convertible( PyObject * py_obj) 170 | { 171 | // we are supposed to indicate whether or not we can convert this 172 | // we don't really know, but we'll try any sequence 173 | if( PyTuple_Check(py_obj) && PyTuple_Size(py_obj) == 2) 174 | return py_obj; 175 | return 0; 176 | } 177 | 178 | static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data) 179 | { 180 | using namespace boost::python; 181 | typedef converter::rvalue_from_python_storage< wrapped_type > storage_t; 182 | 183 | storage_t* the_storage = reinterpret_cast( data ); 184 | void* memory_chunk = the_storage->storage.bytes; 185 | wrapped_type * newvec = new (memory_chunk) wrapped_type; 186 | data->convertible = memory_chunk; 187 | 188 | object sequence(handle<>( borrowed( py_obj ) ) ); 189 | newvec->first = extract(sequence[0])(); 190 | newvec->second = extract(sequence[1])(); 191 | } 192 | 193 | }; 194 | 195 | #endif // UTILS_CONTAINER_H_ 196 | -------------------------------------------------------------------------------- /src/lib/conversion.cpp: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // Note: Stripped from Opencv (opencv/modules/python/src2/cv2.cpp) 3 | 4 | # include "conversion.h" 5 | /* 6 | * The following conversion functions are taken/adapted from OpenCV's cv2.cpp file 7 | * inside modules/python/src2 folder. 8 | */ 9 | 10 | static int init() 11 | { 12 | import_array(); 13 | } 14 | 15 | static int failmsg(const char *fmt, ...) 16 | { 17 | char str[1000]; 18 | 19 | va_list ap; 20 | va_start(ap, fmt); 21 | vsnprintf(str, sizeof(str), fmt, ap); 22 | va_end(ap); 23 | 24 | PyErr_SetString(PyExc_TypeError, str); 25 | return 0; 26 | } 27 | 28 | class PyAllowThreads 29 | { 30 | public: 31 | PyAllowThreads() : _state(PyEval_SaveThread()) {} 32 | ~PyAllowThreads() 33 | { 34 | PyEval_RestoreThread(_state); 35 | } 36 | private: 37 | PyThreadState* _state; 38 | }; 39 | 40 | class PyEnsureGIL 41 | { 42 | public: 43 | PyEnsureGIL() : _state(PyGILState_Ensure()) {} 44 | ~PyEnsureGIL() 45 | { 46 | PyGILState_Release(_state); 47 | } 48 | private: 49 | PyGILState_STATE _state; 50 | }; 51 | 52 | using namespace cv; 53 | static PyObject* failmsgp(const char *fmt, ...) 54 | { 55 | char str[1000]; 56 | 57 | va_list ap; 58 | va_start(ap, fmt); 59 | vsnprintf(str, sizeof(str), fmt, ap); 60 | va_end(ap); 61 | 62 | PyErr_SetString(PyExc_TypeError, str); 63 | return 0; 64 | } 65 | 66 | #if CV_MAJOR_VERSION < 3 67 | #define OPENCV_3 0 68 | #else 69 | #define OPENCV_3 1 70 | #endif 71 | 72 | #if OPENCV_3 73 | class NumpyAllocator : public MatAllocator 74 | { 75 | public: 76 | NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); } 77 | ~NumpyAllocator() {} 78 | 79 | UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const 80 | { 81 | UMatData* u = new UMatData(this); 82 | u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o); 83 | npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o); 84 | for( int i = 0; i < dims - 1; i++ ) 85 | step[i] = (size_t)_strides[i]; 86 | step[dims-1] = CV_ELEM_SIZE(type); 87 | u->size = sizes[0]*step[0]; 88 | u->userdata = o; 89 | return u; 90 | } 91 | 92 | UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const 93 | { 94 | USAGE_DEFAULT; 95 | if( data != 0 ) 96 | { 97 | CV_Error(Error::StsAssert, "The data should normally be NULL!"); 98 | // probably this is safe to do in such extreme case 99 | return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags); 100 | } 101 | PyEnsureGIL gil; 102 | 103 | int depth = CV_MAT_DEPTH(type); 104 | int cn = CV_MAT_CN(type); 105 | const int f = (int)(sizeof(size_t)/8); 106 | int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE : 107 | depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT : 108 | depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT : 109 | depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT; 110 | int i, dims = dims0; 111 | cv::AutoBuffer _sizes(dims + 1); 112 | for( i = 0; i < dims; i++ ) 113 | _sizes[i] = sizes[i]; 114 | if( cn > 1 ) 115 | _sizes[dims++] = cn; 116 | PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum); 117 | if(!o) 118 | CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims)); 119 | return allocate(o, dims0, sizes, type, step); 120 | } 121 | 122 | bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const 123 | { 124 | return stdAllocator->allocate(u, accessFlags, usageFlags); 125 | } 126 | 127 | void deallocate(UMatData* u) const 128 | { 129 | if(u) 130 | { 131 | PyEnsureGIL gil; 132 | PyObject* o = (PyObject*)u->userdata; 133 | Py_XDECREF(o); 134 | delete u; 135 | } 136 | } 137 | 138 | const MatAllocator* stdAllocator; 139 | }; 140 | #else 141 | class NumpyAllocator : public MatAllocator 142 | { 143 | public: 144 | NumpyAllocator() {} 145 | ~NumpyAllocator() {} 146 | 147 | void allocate(int dims, const int* sizes, int type, int*& refcount, 148 | uchar*& datastart, uchar*& data, size_t* step) 149 | { 150 | PyEnsureGIL gil; 151 | 152 | int depth = CV_MAT_DEPTH(type); 153 | int cn = CV_MAT_CN(type); 154 | const int f = (int)(sizeof(size_t)/8); 155 | int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE : 156 | depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT : 157 | depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT : 158 | depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT; 159 | int i; 160 | npy_intp _sizes[CV_MAX_DIM+1]; 161 | for( i = 0; i < dims; i++ ) 162 | _sizes[i] = sizes[i]; 163 | if( cn > 1 ) 164 | { 165 | /*if( _sizes[dims-1] == 1 ) 166 | _sizes[dims-1] = cn; 167 | else*/ 168 | _sizes[dims++] = cn; 169 | } 170 | PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum); 171 | if(!o) 172 | CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims)); 173 | refcount = refcountFromPyObject(o); 174 | npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o); 175 | for( i = 0; i < dims - (cn > 1); i++ ) 176 | step[i] = (size_t)_strides[i]; 177 | datastart = data = (uchar*)PyArray_DATA((PyArrayObject*) o); 178 | } 179 | 180 | void deallocate(int* refcount, uchar*, uchar*) 181 | { 182 | PyEnsureGIL gil; 183 | if( !refcount ) 184 | return; 185 | PyObject* o = pyObjectFromRefcount(refcount); 186 | Py_INCREF(o); 187 | Py_DECREF(o); 188 | } 189 | }; 190 | #endif 191 | 192 | 193 | 194 | NumpyAllocator g_numpyAllocator; 195 | 196 | NDArrayConverter::NDArrayConverter() { init(); } 197 | 198 | int NDArrayConverter::init() 199 | { 200 | import_array(); 201 | } 202 | 203 | cv::Mat NDArrayConverter::toMat(const PyObject *o) 204 | { 205 | cv::Mat m; 206 | 207 | if(!o || o == Py_None) 208 | { 209 | if( !m.data ) 210 | m.allocator = &g_numpyAllocator; 211 | return m; 212 | } 213 | 214 | if( !PyArray_Check(o) ) 215 | { 216 | failmsg("toMat: Object is not a numpy array"); 217 | } 218 | 219 | int typenum = PyArray_TYPE(o); 220 | int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S : 221 | typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S : 222 | typenum == NPY_INT || typenum == NPY_LONG ? CV_32S : 223 | typenum == NPY_FLOAT ? CV_32F : 224 | typenum == NPY_DOUBLE ? CV_64F : -1; 225 | 226 | if( type < 0 ) 227 | { 228 | failmsg("toMat: Data type = %d is not supported", typenum); 229 | } 230 | 231 | int ndims = PyArray_NDIM(o); 232 | 233 | if(ndims >= CV_MAX_DIM) 234 | { 235 | failmsg("toMat: Dimensionality (=%d) is too high", ndims); 236 | } 237 | 238 | int size[CV_MAX_DIM+1]; 239 | size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type); 240 | const npy_intp* _sizes = PyArray_DIMS(o); 241 | const npy_intp* _strides = PyArray_STRIDES(o); 242 | bool transposed = false; 243 | 244 | for(int i = 0; i < ndims; i++) 245 | { 246 | size[i] = (int)_sizes[i]; 247 | step[i] = (size_t)_strides[i]; 248 | } 249 | 250 | if( ndims == 0 || step[ndims-1] > elemsize ) { 251 | size[ndims] = 1; 252 | step[ndims] = elemsize; 253 | ndims++; 254 | } 255 | 256 | if( ndims >= 2 && step[0] < step[1] ) 257 | { 258 | std::swap(size[0], size[1]); 259 | std::swap(step[0], step[1]); 260 | transposed = true; 261 | } 262 | 263 | // std::cerr << " ndims: " << ndims 264 | // << " size: " << size 265 | // << " type: " << type 266 | // << " step: " << step 267 | // << " size: " << size[2] << std::endl; 268 | 269 | // TODO: Possible bug in multi-dimensional matrices 270 | #if 1 271 | if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] ) 272 | { 273 | ndims--; 274 | type |= CV_MAKETYPE(0, size[2]); 275 | } 276 | #endif 277 | 278 | if( ndims > 2) 279 | { 280 | failmsg("toMat: Object has more than 2 dimensions"); 281 | } 282 | 283 | m = Mat(ndims, size, type, PyArray_DATA(o), step); 284 | // m.u = g_numpyAllocator.allocate(o, ndims, size, type, step); 285 | 286 | if( m.data ) 287 | { 288 | #if OPENCV_3 289 | m.addref(); 290 | Py_INCREF(o); 291 | #else 292 | m.refcount = refcountFromPyObject(o); 293 | m.addref(); // protect the original numpy array from deallocation 294 | // (since Mat destructor will decrement the reference counter) 295 | #endif 296 | }; 297 | m.allocator = &g_numpyAllocator; 298 | 299 | if( transposed ) 300 | { 301 | Mat tmp; 302 | tmp.allocator = &g_numpyAllocator; 303 | transpose(m, tmp); 304 | m = tmp; 305 | } 306 | return m; 307 | } 308 | 309 | PyObject* NDArrayConverter::toNDArray(const cv::Mat& m) 310 | { 311 | #if OPENCV_3 312 | if( !m.data ) 313 | Py_RETURN_NONE; 314 | Mat temp, *p = (Mat*)&m; 315 | if(!p->u || p->allocator != &g_numpyAllocator) 316 | { 317 | temp.allocator = &g_numpyAllocator; 318 | m.copyTo(temp); 319 | p = &temp; 320 | } 321 | PyObject* o = (PyObject*)p->u->userdata; 322 | Py_INCREF(o); 323 | // p->addref(); 324 | // pyObjectFromRefcount(p->refcount); 325 | return o; 326 | #else 327 | if( !m.data ) 328 | Py_RETURN_NONE; 329 | Mat temp, *p = (Mat*)&m; 330 | if(!p->refcount || p->allocator != &g_numpyAllocator) 331 | { 332 | temp.allocator = &g_numpyAllocator; 333 | ERRWRAP2(m.copyTo(temp)); 334 | p = &temp; 335 | } 336 | p->addref(); 337 | return pyObjectFromRefcount(p->refcount); 338 | #endif 339 | 340 | } 341 | -------------------------------------------------------------------------------- /src/lib/conversion.h: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // Note: Stripped from Opencv (opencv/modules/python/src2/cv2.cpp) 3 | 4 | # ifndef __COVERSION_OPENCV_H__ 5 | # define __COVERSION_OPENCV_H__ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define CV_MAX_DIM 32 13 | 14 | static PyObject* opencv_error = 0; 15 | 16 | static int failmsg(const char *fmt, ...); 17 | 18 | class PyAllowThreads; 19 | 20 | class PyEnsureGIL; 21 | 22 | #define ERRWRAP2(expr) \ 23 | try \ 24 | { \ 25 | PyAllowThreads allowThreads; \ 26 | expr; \ 27 | } \ 28 | catch (const cv::Exception &e) \ 29 | { \ 30 | PyErr_SetString(opencv_error, e.what()); \ 31 | return 0; \ 32 | } 33 | 34 | static PyObject* failmsgp(const char *fmt, ...); 35 | 36 | static size_t REFCOUNT_OFFSET = (size_t)&(((PyObject*)0)->ob_refcnt) + 37 | (0x12345678 != *(const size_t*)"\x78\x56\x34\x12\0\0\0\0\0")*sizeof(int); 38 | 39 | static inline PyObject* pyObjectFromRefcount(const int* refcount) 40 | { 41 | return (PyObject*)((size_t)refcount - REFCOUNT_OFFSET); 42 | } 43 | 44 | static inline int* refcountFromPyObject(const PyObject* obj) 45 | { 46 | return (int*)((size_t)obj + REFCOUNT_OFFSET); 47 | } 48 | 49 | 50 | class NumpyAllocator; 51 | 52 | enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 }; 53 | 54 | class NDArrayConverter 55 | { 56 | private: 57 | int init(); 58 | public: 59 | NDArrayConverter(); 60 | cv::Mat toMat(const PyObject* o); 61 | PyObject* toNDArray(const cv::Mat& mat); 62 | }; 63 | 64 | # endif 65 | -------------------------------------------------------------------------------- /src/lib/np_opencv_converter.cpp: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // License: BSD 3 | // Last modified: Sep 14, 2014 4 | 5 | #include "np_opencv_converter.hpp" 6 | #include "DBoW3.h" 7 | 8 | namespace fs { namespace python { 9 | 10 | // Static PyInit 11 | static int py_init() { 12 | Py_Initialize(); 13 | import_array(); 14 | } 15 | 16 | // Singleton init and export converters 17 | static bool export_type_conversions_once = false; 18 | bool init_and_export_converters() { 19 | 20 | if (export_type_conversions_once) 21 | return false; 22 | 23 | std::cerr << "PYTHON TYPE CONVERTERS exported" << std::endl; 24 | export_type_conversions_once = true; 25 | 26 | // Py_Init and array import 27 | py_init(); 28 | 29 | // => py::list 30 | expose_template_type(); 31 | expose_template_type(); 32 | expose_template_type(); 33 | 34 | // std::vector => py::list 35 | expose_template_type< std::vector >(); 36 | expose_template_type< std::vector >(); 37 | expose_template_type< std::vector >(); 38 | 39 | expose_template_type< std::vector >(); 40 | expose_template_type< std::vector >(); 41 | expose_template_type< std::vector >(); 42 | 43 | expose_template_type< std::vector >(); 44 | expose_template_type< std::vector >(); 45 | expose_template_type< std::vector >(); 46 | 47 | // std::map => py::dict 48 | expose_template_type > >(); 49 | expose_template_type > >(); 50 | expose_template_type >(); 51 | 52 | // various converters to cv::Mat 53 | py::to_python_converter(); 54 | py::to_python_converter(); 55 | py::to_python_converter(); 56 | py::to_python_converter(); 57 | 58 | // register the to-from-python converter for each of the types 59 | Mat_PyObject_converter< cv::Mat >(); 60 | 61 | // 1-channel 62 | Mat_PyObject_converter< cv::Mat1b >(); 63 | Mat_PyObject_converter< cv::Mat1s >(); 64 | Mat_PyObject_converter< cv::Mat1w >(); 65 | Mat_PyObject_converter< cv::Mat1i >(); 66 | Mat_PyObject_converter< cv::Mat1f >(); 67 | Mat_PyObject_converter< cv::Mat1d >(); 68 | 69 | // 2-channel 70 | Mat_PyObject_converter< cv::Mat2b >(); 71 | Mat_PyObject_converter< cv::Mat2s >(); 72 | Mat_PyObject_converter< cv::Mat2w >(); 73 | Mat_PyObject_converter< cv::Mat2i >(); 74 | Mat_PyObject_converter< cv::Mat2f >(); 75 | Mat_PyObject_converter< cv::Mat2d >(); 76 | 77 | // 3-channel 78 | Mat_PyObject_converter< cv::Mat3b >(); 79 | Mat_PyObject_converter< cv::Mat3s >(); 80 | Mat_PyObject_converter< cv::Mat3w >(); 81 | Mat_PyObject_converter< cv::Mat3i >(); 82 | Mat_PyObject_converter< cv::Mat3f >(); 83 | Mat_PyObject_converter< cv::Mat3d >(); 84 | 85 | // add more if needed 86 | expose_template_type< std::vector >(); 87 | expose_template_type< DBoW3::BowVector >(); 88 | 89 | return true; 90 | } 91 | 92 | } // namespace python 93 | } // namespace fs 94 | 95 | -------------------------------------------------------------------------------- /src/lib/np_opencv_converter.hpp: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // License: BSD 3 | // Last modified: Sep 14, 2014 4 | 5 | #ifndef NP_OPENCV_CONVERTER_HPP_ 6 | #define NP_OPENCV_CONVERTER_HPP_ 7 | 8 | // Boost python includes 9 | #include 10 | #include 11 | 12 | // Include templated conversion utils 13 | #include "template.h" 14 | #include "container.h" 15 | #include "conversion.h" 16 | 17 | // opencv includes 18 | #include 19 | 20 | namespace fs { namespace python { 21 | 22 | // TODO: Template these 23 | // Vec3f => cv::Mat 24 | struct Vec3f_to_mat { 25 | static PyObject* convert(const cv::Vec3f& v){ 26 | NDArrayConverter cvt; 27 | PyObject* ret = cvt.toNDArray(cv::Mat(v)); 28 | return ret; 29 | } 30 | }; 31 | 32 | // cv::Point => cv::Mat 33 | struct Point_to_mat { 34 | static PyObject* convert(const cv::Point& v){ 35 | NDArrayConverter cvt; 36 | PyObject* ret = cvt.toNDArray(cv::Mat(v)); 37 | return ret; 38 | } 39 | }; 40 | 41 | // cv::Point2f => cv::Mat 42 | struct Point2f_to_mat { 43 | static PyObject* convert(const cv::Point2f& v){ 44 | NDArrayConverter cvt; 45 | PyObject* ret = cvt.toNDArray(cv::Mat(v)); 46 | return ret; 47 | } 48 | }; 49 | 50 | // cv::Point3f => cv::Mat 51 | struct Point3f_to_mat { 52 | static PyObject* convert(const cv::Point3f& v){ 53 | NDArrayConverter cvt; 54 | PyObject* ret = cvt.toNDArray(cv::Mat(v)); 55 | return ret; 56 | } 57 | }; 58 | 59 | // cv::Mat_ => Numpy PyObject 60 | template 61 | struct Mat_to_PyObject { 62 | static PyObject* convert(const T& mat){ 63 | NDArrayConverter cvt; 64 | PyObject* ret = cvt.toNDArray(mat); 65 | return ret; 66 | } 67 | }; 68 | 69 | // Generic templated cv::Mat <=> Numpy PyObject converter 70 | template 71 | struct Mat_PyObject_converter 72 | { 73 | // Register from converter 74 | Mat_PyObject_converter() { 75 | boost::python::converter::registry::push_back( 76 | &convertible, 77 | &construct, 78 | boost::python::type_id()); 79 | 80 | // Register to converter 81 | py::to_python_converter >(); 82 | } 83 | 84 | // Convert from type T to PyObject (numpy array) 85 | // Assume obj_ptr can be converted in a cv::Mat 86 | static void* convertible(PyObject* obj_ptr) 87 | { 88 | // Check validity? 89 | assert(obj_ptr != 0); 90 | return obj_ptr; 91 | } 92 | 93 | // Convert obj_ptr into a cv::Mat 94 | static void construct(PyObject* obj_ptr, 95 | boost::python::converter::rvalue_from_python_stage1_data* data) 96 | { 97 | using namespace boost::python; 98 | typedef converter::rvalue_from_python_storage< T > storage_t; 99 | 100 | storage_t* the_storage = reinterpret_cast( data ); 101 | void* memory_chunk = the_storage->storage.bytes; 102 | 103 | NDArrayConverter cvt; 104 | T* newvec = new (memory_chunk) T(cvt.toMat(obj_ptr)); 105 | data->convertible = memory_chunk; 106 | 107 | return; 108 | } 109 | }; 110 | 111 | bool init_and_export_converters(); 112 | 113 | } // namespace python 114 | } // namespace fs 115 | 116 | #endif // NP_OPENCV_CONVERTER_HPP_ 117 | -------------------------------------------------------------------------------- /src/lib/template.h: -------------------------------------------------------------------------------- 1 | // Author: Sudeep Pillai (spillai@csail.mit.edu) 2 | // Note: Stripped from pyxx project 3 | 4 | #ifndef PYXX_TEMPLATE_H 5 | #define PYXX_TEMPLATE_H 6 | 7 | #include 8 | /* 9 | * Provides template support 10 | */ 11 | 12 | template 13 | struct expose_template_type 14 | { 15 | // do nothing! 16 | }; 17 | 18 | template 19 | struct expose_template_type_base 20 | { 21 | bool wrapped() 22 | { 23 | using namespace boost::python::converter; 24 | using namespace boost::python; 25 | registration const * p = registry::query( type_id() ); 26 | return p && (p->m_class_object || p->m_to_python); 27 | } 28 | 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, Extension 2 | from pyDBoW3 import __version__, __short_description__, __author__, __author_email__ 3 | 4 | try: 5 | from wheel.bdist_wheel import bdist_wheel as _bdist_wheel 6 | class bdist_wheel(_bdist_wheel): 7 | def finalize_options(self): 8 | _bdist_wheel.finalize_options(self) 9 | self.root_is_pure = False 10 | except ImportError: 11 | bdist_wheel = None 12 | 13 | 14 | def readme(): 15 | with open('../../README.rst') as f: 16 | return f.read() 17 | 18 | 19 | setup(name='pyDBoW3', 20 | version=__version__, 21 | description=__short_description__, 22 | long_description=readme(), 23 | url='http://github.com/foxis/pyDBoW3', 24 | author=__author__, 25 | author_email=__author_email__, 26 | classifiers=[ 27 | 'Development Status :: 3 - Alpha', 28 | 'License :: OSI Approved :: MIT License', 29 | 'Programming Language :: Python :: 2.7', 30 | 'Programming Language :: Python :: 3.5', 31 | 'Programming Language :: Python :: 3.6', 32 | 'Programming Language :: Python :: 3.7', 33 | 'Topic :: Text Processing :: Linguistic', 34 | ], 35 | keywords='bag of words bow dbow3 dbow slam orb odometry visual', 36 | license='MIT', 37 | packages=['pyDBoW3'], 38 | include_package_data=True, 39 | zip_safe=False, 40 | install_requires=[ 41 | 'numpy' 42 | ], 43 | cmdclass={'bdist_wheel': bdist_wheel}, 44 | ) -------------------------------------------------------------------------------- /src/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxis/pyDBoW3/7599791e06280381923499fd813afd2f4f21295a/src/test/__init__.py -------------------------------------------------------------------------------- /src/test/all.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | if __name__ == "__main__": 5 | import pytest 6 | 7 | pytest.main(["-s", "--tb=native"]) -------------------------------------------------------------------------------- /src/test/test_import.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import pytest 5 | from pytest import raises, approx 6 | 7 | 8 | def test_import_main(): 9 | import pyDBoW3 10 | 11 | assert('Vocabulary' in pyDBoW3) 12 | assert('Database' in pyDBoW3) 13 | 14 | 15 | if __name__ == "__main__": 16 | import os 17 | 18 | basename = os.path.basename(__file__) 19 | pytest.main([basename, "-s", "--tb=native"]) 20 | --------------------------------------------------------------------------------