diff --git a/.gitignore b/.gitignore
index f03013e4f5e1219e996f316519fce459d0acbb8c..1bfd386b4ddd10579dc4f62b44835a0422ef085e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@ fet/etc/
 *.pdb
 *.suo
 *.dll
+*.pyd
+*.so
+bgs.egg-info
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..a90eb86150542c0283e6e7a9c45ceef1ec376b0c
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "pybind11"]
+	path = pybind11
+	url = https://github.com/pybind/pybind11.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6416945ec494626e3aea68aae3cf59e31f7359d1..1a9a8c3882776852532d3318478b9acf38fa0e7d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,17 +10,25 @@ elseif()
 endif()
 message(STATUS "BGSLIBRARY WITH PYTHON SUPPORT: ${BGS_PYTHON_SUPPORT}")
 
-# cmake -D BGS_PYTHON_SUPPORT=ON -D BGS_PYTHON_VERSION=2 ..
+# cmake -D BGS_PYTHON_SUPPORT=ON -D BGS_PYTHON_VERSION=3 ..
 if(NOT DEFINED BGS_PYTHON_VERSION)
-  set(BGS_PYTHON_VERSION 2)
+  set(BGS_PYTHON_VERSION 3)
+endif()
+if(BGS_PYTHON_SUPPORT)
+  message(STATUS "PYTHON VERSION: ${BGS_PYTHON_VERSION}")
 endif()
-message(STATUS "PYTHON VERSION: ${BGS_PYTHON_VERSION}")
 
 if(UNIX)
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
   set(CMAKE_MACOSX_RPATH 1)
 endif(UNIX)
 
+# Avoid cmake warnings about changes in behavior of some Mac OS X path 
+# variable we don't care about.
+if (POLICY CMP0042)
+  cmake_policy(SET CMP0042 NEW)
+endif()
+
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
 #set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules)
 
@@ -80,32 +88,44 @@ if(${OpenCV_VERSION} VERSION_LESS 2.3.1)
 endif()
 
 if(BGS_PYTHON_SUPPORT)
-  if(WIN32)
-    set(Boost_USE_STATIC_LIBS ON)
-  else()
-    set(Boost_USE_STATIC_LIBS OFF)
-  endif()
+  #if(WIN32)
+  #  set(Boost_USE_STATIC_LIBS ON)
+  #else()
+  #  set(Boost_USE_STATIC_LIBS OFF)
+  #endif()
   
-  set(Boost_USE_MULTITHREADED ON)
-  set(Boost_USE_STATIC_RUNTIME OFF)
+  #set(Boost_USE_MULTITHREADED ON)
+  #set(Boost_USE_STATIC_RUNTIME OFF)
   
-  message(STATUS "SEARCHING FOR BOOST COMPONENT FOR PYTHON ${BGS_PYTHON_VERSION}")
-  if(BGS_PYTHON_VERSION EQUAL 2)
-    find_package(Boost REQUIRED COMPONENTS python)
-  else()
-    find_package(Boost REQUIRED COMPONENTS python3)
-  endif()
-  find_package(PythonInterp ${BGS_PYTHON_VERSION} REQUIRED)
-  find_package(PythonLibs ${BGS_PYTHON_VERSION} REQUIRED)
-
-  message(STATUS "Boost library status:")
-  message(STATUS "    version: ${Boost_VERSION}")
-  message(STATUS "    libraries: ${Boost_LIBRARIES}")
-  message(STATUS "    include path: ${Boost_INCLUDE_DIRS}")
+  #message(STATUS "SEARCHING FOR BOOST COMPONENT FOR PYTHON ${BGS_PYTHON_VERSION}")
+  #if(BGS_PYTHON_VERSION EQUAL 2)
+  #  find_package(Boost REQUIRED COMPONENTS python)
+  #else()
+  #  find_package(Boost REQUIRED COMPONENTS python3)
+  #endif()
+
+  # Pybind11's cmake scripts enable link time optimization by default.  However,
+  # it makes linking take a really long time and doesn't seem to substantively
+  # improve runtime performance.  So we disable LTO here to make building bgslibrary
+  # faster.
+  set(PYBIND11_LTO_CXX_FLAGS "")
+
+  #set(PYBIND11_PYTHON_VERSION 2.7 3.5 3.6)
+  set(PYBIND11_PYTHON_VERSION ${BGS_PYTHON_VERSION})
+  #find_package(pybind11 REQUIRED)
+  add_subdirectory(pybind11)
+
+  #find_package(PythonInterp ${BGS_PYTHON_VERSION} REQUIRED)
+  #find_package(PythonLibs ${BGS_PYTHON_VERSION} REQUIRED)
+
+  #message(STATUS "Boost library status:")
+  #message(STATUS "    version: ${Boost_VERSION}")
+  #message(STATUS "    libraries: ${Boost_LIBRARIES}")
+  #message(STATUS "    include path: ${Boost_INCLUDE_DIRS}")
 
   message(STATUS "Python library status:")
   message(STATUS "    executable: ${PYTHON_EXECUTABLE}")
-  message(STATUS "    version: ${PYTHON_VERSION_STRING}")
+  #message(STATUS "    version: ${PYTHON_VERSION_STRING}")
   #message(STATUS "    libraries: ${PYTHON_LIBRARIES}")
   message(STATUS "    library: ${PYTHON_LIBRARY}")
   message(STATUS "    include path: ${PYTHON_INCLUDE_DIRS}")
@@ -131,11 +151,17 @@ file(GLOB_RECURSE analysis_src package_analysis/*.cpp)
 if(BGS_PYTHON_SUPPORT)
   file(GLOB_RECURSE bgs_src package_bgs/*.cpp package_bgs/*.c wrapper_python/*.cpp)
   file(GLOB_RECURSE bgs_include package_bgs/*.h wrapper_python/*.h)
-  include_directories(${CMAKE_SOURCE_DIR} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR})
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR}/pybind11/include)
+  include_directories(${OpenCV_INCLUDE_DIRS})
+  #include_directories(${Boost_INCLUDE_DIRS})
+  include_directories(${PYTHON_INCLUDE_DIRS})
+  include_directories(${NUMPY_INCLUDE_DIR})
 else()
   file(GLOB_RECURSE bgs_src package_bgs/*.cpp package_bgs/*.c)
   file(GLOB_RECURSE bgs_include package_bgs/*.h)
-  include_directories(${CMAKE_SOURCE_DIR} ${OpenCV_INCLUDE_DIRS})
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+  include_directories(${OpenCV_INCLUDE_DIRS})
 endif()
 
 # GMG is not available in older OpenCV versions
@@ -145,43 +171,59 @@ if(${OpenCV_VERSION} VERSION_LESS 2.4.3)
 endif()
 
 if(BGS_PYTHON_SUPPORT)
-  #add_library(libbgs SHARED ${sources} ${bgs_src} ${analysis_src})
-  add_library(libbgs SHARED ${bgs_src} ${analysis_src})
-  target_link_libraries(libbgs ${OpenCV_LIBS} ${Boost_LIBRARIES} ${PYTHON_LIBRARY})
-  target_compile_definitions(libbgs PRIVATE BGS_PYTHON_SUPPORT=1)
+  #add_library(bgs_python SHARED ${sources} ${bgs_src} ${analysis_src})
+  #add_library(bgs_python SHARED ${bgs_src} ${analysis_src})
+  pybind11_add_module(bgs_python ${bgs_src} ${analysis_src})
+  target_link_libraries(bgs_python PRIVATE ${OpenCV_LIBS} ${PYTHON_LIBRARY} pybind11::module)
+  #target_link_libraries(bgs_python ${OpenCV_LIBS} ${Boost_LIBRARIES} ${PYTHON_LIBRARY})
+  #target_link_libraries(bgs_python ${OpenCV_LIBS} ${PYTHON_LIBRARY} pybind11::module)
+  #target_link_libraries(bgs_python PRIVATE ${OpenCV_LIBS} ${PYTHON_LIBRARY} pybind11::embed)
+  #set_target_properties(bgs_python PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" SUFFIX "${PYTHON_MODULE_EXTENSION}")
+  set_target_properties(bgs_python PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")
+  target_compile_definitions(bgs_python PRIVATE BGS_PYTHON_SUPPORT=1)
+  install(TARGETS bgs_python DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
+  # Set the output library name to bgslibrary because that's what setup.py and distutils expects.
+  set_property(TARGET bgs_python PROPERTY OUTPUT_NAME "bgs")
 else()
-  #add_library(libbgs STATIC ${sources} ${bgs_src} ${analysis_src})
-  add_library(libbgs STATIC ${bgs_src} ${analysis_src})
-  target_link_libraries(libbgs ${OpenCV_LIBS})
+  #add_library(bgslibrary_core STATIC ${sources} ${bgs_src} ${analysis_src})
+  add_library(bgslibrary_core STATIC ${bgs_src} ${analysis_src})
+  target_link_libraries(bgslibrary_core ${OpenCV_LIBS})
+  set_property(TARGET bgslibrary_core PROPERTY PUBLIC_HEADER ${bgs_include})
 endif()
-set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_include})
 
-if(WIN32)
-  # set_property(TARGET libbgs PROPERTY SUFFIX ".lib")
-  if(BGS_PYTHON_SUPPORT)
-    set_property(TARGET libbgs PROPERTY SUFFIX ".pyd")
-  endif()
-else()
-  set_property(TARGET libbgs PROPERTY OUTPUT_NAME "bgs")
-endif()
+#if(WIN32)
+#  # set_property(TARGET bgslibrary_core PROPERTY SUFFIX ".lib")
+#  #if(BGS_PYTHON_SUPPORT)
+#  #  set_property(TARGET bgslibrary_core PROPERTY SUFFIX ".pyd")
+#  #endif()
+#else()
+#  set_property(TARGET bgslibrary_core PROPERTY OUTPUT_NAME "bgs")
+#endif()
+
+#if(APPLE)
+#  if(BGS_PYTHON_SUPPORT)
+#    set_property(TARGET bgslibrary_core PROPERTY SUFFIX ".so")
+#    set_target_properties(bgslibrary_core PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
+#  endif()
+#endif()
 
 if(NOT BGS_PYTHON_SUPPORT)
-add_executable(bgslibrary ${main})
-target_link_libraries(bgslibrary ${OpenCV_LIBS} libbgs)
-# set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs)
-
-add_executable(bgs_demo ${demo})
-target_link_libraries(bgs_demo ${OpenCV_LIBS} libbgs)
-
-add_executable(bgs_demo2 ${demo2})
-target_link_libraries(bgs_demo2 ${OpenCV_LIBS} libbgs)
-
-install(TARGETS libbgs
-  bgslibrary
-  RUNTIME DESTINATION bin COMPONENT app
-  LIBRARY DESTINATION lib COMPONENT runtime
-  ARCHIVE DESTINATION lib COMPONENT runtime
-  PUBLIC_HEADER DESTINATION include/package_bgs COMPONENT dev
-  FRAMEWORK DESTINATION "/Library/Frameworks"
-)
+  add_executable(bgslibrary ${main})
+  target_link_libraries(bgslibrary ${OpenCV_LIBS} bgslibrary_core)
+  # set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs)
+
+  add_executable(bgs_demo ${demo})
+  target_link_libraries(bgs_demo ${OpenCV_LIBS} bgslibrary_core)
+
+  add_executable(bgs_demo2 ${demo2})
+  target_link_libraries(bgs_demo2 ${OpenCV_LIBS} bgslibrary_core)
+
+  install(TARGETS bgslibrary_core
+    bgslibrary
+    RUNTIME DESTINATION bin COMPONENT app
+    LIBRARY DESTINATION lib COMPONENT runtime
+    ARCHIVE DESTINATION lib COMPONENT runtime
+    PUBLIC_HEADER DESTINATION include/package_bgs COMPONENT dev
+    FRAMEWORK DESTINATION "/Library/Frameworks"
+  )
 endif()
\ No newline at end of file
diff --git a/Demo.py b/Demo.py
index de7142f5dcffff938b6971d2d3e95b49900e0133..c988e63e9110311a010da2ae1d62510ffb6e6aac 100644
--- a/Demo.py
+++ b/Demo.py
@@ -1,52 +1,8 @@
 import numpy as np
 import cv2
-import libbgs
-
-## BGS Library algorithms
-bgs = libbgs.FrameDifference()
-#bgs = libbgs.StaticFrameDifference()
-#bgs = libbgs.AdaptiveBackgroundLearning()
-#bgs = libbgs.AdaptiveSelectiveBackgroundLearning()
-#bgs = libbgs.DPAdaptiveMedian()
-#bgs = libbgs.DPEigenbackground()
-#bgs = libbgs.DPGrimsonGMM()
-#bgs = libbgs.DPMean()
-#bgs = libbgs.DPPratiMediod()
-#bgs = libbgs.DPTexture()
-#bgs = libbgs.DPWrenGA()
-#bgs = libbgs.DPZivkovicAGMM()
-#bgs = libbgs.FuzzyChoquetIntegral()
-#bgs = libbgs.FuzzySugenoIntegral()
-#bgs = libbgs.GMG() # if opencv 2.x
-#bgs = libbgs.IndependentMultimodal()
-#bgs = libbgs.KDE()
-#bgs = libbgs.KNN() # if opencv 3.x
-#bgs = libbgs.LBAdaptiveSOM()
-#bgs = libbgs.LBFuzzyAdaptiveSOM()
-#bgs = libbgs.LBFuzzyGaussian()
-#bgs = libbgs.LBMixtureOfGaussians()
-#bgs = libbgs.LBSimpleGaussian()
-#bgs = libbgs.LBP_MRF()
-#bgs = libbgs.LOBSTER()
-#bgs = libbgs.MixtureOfGaussianV1() # if opencv 2.x
-#bgs = libbgs.MixtureOfGaussianV2()
-#bgs = libbgs.MultiCue()
-#bgs = libbgs.MultiLayer()
-#bgs = libbgs.PAWCS()
-#bgs = libbgs.PixelBasedAdaptiveSegmenter()
-#bgs = libbgs.SigmaDelta()
-#bgs = libbgs.SuBSENSE()
-#bgs = libbgs.T2FGMM_UM()
-#bgs = libbgs.T2FGMM_UV()
-#bgs = libbgs.T2FMRF_UM()
-#bgs = libbgs.T2FMRF_UV()
-#bgs = libbgs.VuMeter()
-#bgs = libbgs.WeightedMovingMean()
-#bgs = libbgs.WeightedMovingVariance()
-#bgs = libbgs.TwoPoints()
-#bgs = libbgs.ViBe()
-#bgs = libbgs.CodeBook()
+import bgs
 
+algorithm = bgs.FrameDifference()
 video_file = "dataset/video.avi"
 
 capture = cv2.VideoCapture(video_file)
@@ -68,8 +24,8 @@ while True:
     pos_frame = capture.get(1)
     #print str(pos_frame)+" frames"
     
-    img_output = bgs.apply(frame)
-    img_bgmodel = bgs.getBackgroundModel();
+    img_output = algorithm.apply(frame)
+    img_bgmodel = algorithm.getBackgroundModel()
     
     cv2.imshow('img_output', img_output)
     cv2.imshow('img_bgmodel', img_bgmodel)
diff --git a/Demo2.py b/Demo2.py
new file mode 100644
index 0000000000000000000000000000000000000000..542ab3da6e675189acd08b41b6ee71c2447e8f2f
--- /dev/null
+++ b/Demo2.py
@@ -0,0 +1,112 @@
+import numpy as np
+import cv2
+import bgs
+
+print("OpenCV Version: {}".format(cv2.__version__))
+
+def is_cv2():
+  return check_opencv_version("2.")
+
+def is_cv3():
+  return check_opencv_version("3.")
+
+def check_opencv_version(major):
+  return cv2.__version__.startswith(major)
+
+## bgslibrary algorithms
+algorithms=[]
+algorithms.append(bgs.FrameDifference())
+algorithms.append(bgs.StaticFrameDifference())
+algorithms.append(bgs.AdaptiveBackgroundLearning())
+algorithms.append(bgs.AdaptiveSelectiveBackgroundLearning())
+algorithms.append(bgs.DPAdaptiveMedian())
+algorithms.append(bgs.DPEigenbackground())
+algorithms.append(bgs.DPGrimsonGMM())
+algorithms.append(bgs.DPMean())
+algorithms.append(bgs.DPPratiMediod())
+algorithms.append(bgs.DPTexture())
+algorithms.append(bgs.DPWrenGA())
+algorithms.append(bgs.DPZivkovicAGMM())
+algorithms.append(bgs.FuzzyChoquetIntegral())
+algorithms.append(bgs.FuzzySugenoIntegral())
+algorithms.append(bgs.IndependentMultimodal())
+algorithms.append(bgs.KDE())
+if is_cv3():
+  algorithms.append(bgs.KNN()) # if opencv 3.x
+algorithms.append(bgs.LBAdaptiveSOM())
+algorithms.append(bgs.LBFuzzyAdaptiveSOM())
+algorithms.append(bgs.LBFuzzyGaussian())
+algorithms.append(bgs.LBMixtureOfGaussians())
+algorithms.append(bgs.LBSimpleGaussian())
+algorithms.append(bgs.LBP_MRF())
+algorithms.append(bgs.LOBSTER())
+if is_cv2():
+  algorithms.append(bgs.GMG()) # if opencv 2.x
+  algorithms.append(bgs.MixtureOfGaussianV1()) # if opencv 2.x
+algorithms.append(bgs.MixtureOfGaussianV2())
+algorithms.append(bgs.MultiCue())
+algorithms.append(bgs.MultiLayer())
+algorithms.append(bgs.PAWCS())
+algorithms.append(bgs.PixelBasedAdaptiveSegmenter())
+algorithms.append(bgs.SigmaDelta())
+algorithms.append(bgs.SuBSENSE())
+algorithms.append(bgs.T2FGMM_UM())
+algorithms.append(bgs.T2FGMM_UV())
+algorithms.append(bgs.T2FMRF_UM())
+algorithms.append(bgs.T2FMRF_UV())
+algorithms.append(bgs.VuMeter())
+algorithms.append(bgs.WeightedMovingMean())
+algorithms.append(bgs.WeightedMovingVariance())
+algorithms.append(bgs.TwoPoints())
+algorithms.append(bgs.ViBe())
+algorithms.append(bgs.CodeBook())
+
+video_file = "dataset/video.avi"
+
+for algorithm in algorithms:
+  print("Running ", algorithm.__class__)
+  
+  capture = cv2.VideoCapture(video_file)
+  while not capture.isOpened():
+    capture = cv2.VideoCapture(video_file)
+    cv2.waitKey(1000)
+    print("Wait for the header")
+
+  #pos_frame = capture.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
+  #pos_frame = capture.get(cv2.CV_CAP_PROP_POS_FRAMES)
+  pos_frame = capture.get(1)
+  while True:
+    flag, frame = capture.read()
+    
+    if flag:
+      cv2.imshow('video', frame)
+      #pos_frame = capture.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
+      #pos_frame = capture.get(cv2.CV_CAP_PROP_POS_FRAMES)
+      pos_frame = capture.get(1)
+      #print str(pos_frame)+" frames"
+      
+      img_output = algorithm.apply(frame)
+      img_bgmodel = algorithm.getBackgroundModel()
+      
+      cv2.imshow('img_output', img_output)
+      cv2.imshow('img_bgmodel', img_bgmodel)
+
+    else:
+      #capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
+      #capture.set(cv2.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
+      #capture.set(1, pos_frame-1)
+      #print "Frame is not ready"
+      cv2.waitKey(1000)
+      break
+    
+    if 0xFF & cv2.waitKey(10) == 27:
+      break
+    
+    #if capture.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == capture.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
+    #if capture.get(cv2.CV_CAP_PROP_POS_FRAMES) == capture.get(cv2.CV_CAP_PROP_FRAME_COUNT):
+    #if capture.get(1) == capture.get(cv2.CV_CAP_PROP_FRAME_COUNT):
+      #break
+
+  cv2.destroyAllWindows()
+
+print("Finished")
\ No newline at end of file
diff --git a/README.md b/README.md
index 88c4af1b034aa215d143c5f638eb36e7e42c8663..bdb6d4b3dec0cc8afe53fd55109919480ba64662 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,11 @@ A Background Subtraction Library
 
 [![bgslibrary](http://i.giphy.com/5A94AZahSIVOw.gif)](https://youtu.be/_UbERwuQ0OU)
 
-Page Update: **01/04/2017**
+Page Update: **26/08/2018**
 
 Library Version: **2.0.0** (see **[Build Status](https://github.com/andrewssobral/bgslibrary/wiki/Build-status)** and **[Release Notes](https://github.com/andrewssobral/bgslibrary/wiki/Release-notes)** for more info)
 
-The **BGSLibrary** was developed by [Andrews Sobral](http://andrewssobral.wixsite.com/home) and provides an easy-to-use C++ framework based on [OpenCV](http://www.opencv.org/) to perform foreground-background separation in videos. The bgslibrary is compatible with OpenCV 2.x and 3.x, and compiles under Windows, Linux, and Mac OS X. Currently the library contains **43** algorithms. The source code is available under [GNU GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html), the library is free and open source for academic purposes.
+The **BGSLibrary** was developed early 2012 by [Andrews Sobral](http://andrewssobral.wixsite.com/home) to provide an easy-to-use C++ framework for foreground-background separation in videos based on [OpenCV](http://www.opencv.org/). The bgslibrary is compatible with OpenCV 2.x and 3.x, and compiles under Windows, Linux, and Mac OS X. Currently the library contains **43** algorithms. The source code is available under [GNU GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html), the library is available free of charge to all users, academic and commercial.
 
 * [List of available algorithms](https://github.com/andrewssobral/bgslibrary/wiki/List-of-available-algorithms)
 * [Algorithms benchmark](https://github.com/andrewssobral/bgslibrary/wiki/Algorithms-benchmark)
@@ -24,15 +24,15 @@ The **BGSLibrary** was developed by [Andrews Sobral](http://andrewssobral.wixsit
 
 * Graphical User Interface:
 
-*  * [C++ QT](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-QT) ***(NEW)***
-*  * [C++ MFC](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-MFC)
-*  * [Java](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-Java)
+*  * [C++ QT](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-QT)
+*  * [C++ MFC](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-MFC) ***(Deprecated)***
+*  * [Java](https://github.com/andrewssobral/bgslibrary/wiki/Graphical-User-Interface:-Java) ***(Obsolete)***
 
 * Wrappers:
 
-*  * [Python](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-Python) ***(NEW)***
-*  * [MATLAB](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-MATLAB) ***(NEW)***
-*  * [Java](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-Java) ***(NEW)***
+*  * [Python](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-Python)
+*  * [MATLAB](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-MATLAB)
+*  * [Java](https://github.com/andrewssobral/bgslibrary/wiki/Wrapper:-Java)
 
 * [Docker images](https://github.com/andrewssobral/bgslibrary/wiki/Docker-images)
 * [How to integrate BGSLibrary in your own CPP code](https://github.com/andrewssobral/bgslibrary/wiki/How-to-integrate-BGSLibrary-in-your-own-CPP-code)
diff --git a/package_bgs/_template_/amber/amber.c b/package_bgs/_template_/amber/amber.cpp
similarity index 98%
rename from package_bgs/_template_/amber/amber.c
rename to package_bgs/_template_/amber/amber.cpp
index 00bdfb14a5006b825448657d8f565469eaa6dc93..b48b9805905490c5084310b3f0cce604f8159fd9 100644
--- a/package_bgs/_template_/amber/amber.c
+++ b/package_bgs/_template_/amber/amber.cpp
@@ -75,6 +75,6 @@ int32_t libamberModelFree(amberModel* model)
 }
 
 /* For compilation with g++ */
-#ifdef __cplusplus
-}
-#endif
+//#ifdef __cplusplus
+//}
+//#endif
diff --git a/pybind11 b/pybind11
new file mode 160000
index 0000000000000000000000000000000000000000..f7bc18f528bb35cd06c93d0a58c17e6eea3fa68c
--- /dev/null
+++ b/pybind11
@@ -0,0 +1 @@
+Subproject commit f7bc18f528bb35cd06c93d0a58c17e6eea3fa68c
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..758165e2b8310022a186a2ebb4ecac32be4124dc
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,91 @@
+"""
+To build the bgslibrary:
+    python setup.py build
+To build and install:
+    python setup.py install
+To package the wheel (after pip installing twine and wheel):
+    python setup.py bdist_wheel
+To upload the binary wheel to PyPi
+    twine upload dist/*.whl
+To upload the source distribution to PyPi
+    python setup.py sdist 
+    twine upload dist/bgs-*.tar.gz
+"""
+import os
+import re
+import sys
+import platform
+import subprocess
+
+from setuptools import setup, find_packages, Extension
+from setuptools.command.build_ext import build_ext
+from distutils.version import LooseVersion
+
+
+class CMakeExtension(Extension):
+    def __init__(self, name, sourcedir=''):
+        Extension.__init__(self, name, sources=[])
+        self.sourcedir = os.path.abspath(sourcedir)
+
+
+class CMakeBuild(build_ext):
+    def run(self):
+        try:
+            out = subprocess.check_output(['cmake', '--version'])
+        except OSError:
+            raise RuntimeError("CMake must be installed to build the following extensions: " +
+                               ", ".join(e.name for e in self.extensions))
+
+        if platform.system() == "Windows":
+            cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
+            if cmake_version < '3.1.0':
+                raise RuntimeError("CMake >= 3.1.0 is required on Windows")
+
+        for ext in self.extensions:
+            self.build_extension(ext)
+
+    def build_extension(self, ext):
+        python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1])
+        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
+        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
+                      '-DPYTHON_EXECUTABLE=' + sys.executable,
+                      '-DBGS_PYTHON_SUPPORT=ON',
+                      '-DBGS_PYTHON_VERSION=' + python_version]
+
+        cfg = 'Debug' if self.debug else 'Release'
+        build_args = ['--config', cfg]
+
+        if platform.system() == "Windows":
+            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
+            if sys.maxsize > 2**32:
+                cmake_args += ['-A', 'x64']
+            build_args += ['--', '/m']
+        else:
+            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
+            build_args += ['--', '-j2']
+
+        env = os.environ.copy()
+        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
+                                                              self.distribution.get_version())
+        if not os.path.exists(self.build_temp):
+            os.makedirs(self.build_temp)
+        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
+        subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)
+        #subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd="./build", env=env)
+        #subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd="./build")
+
+setup(
+    name='bgs',
+    version='2.0.0',
+    author='Andrews Sobral',
+    author_email='andrewssobral@gmail.com',
+    url='https://github.com/andrewssobral/bgslibrary',
+    license='GPL v3',
+    description='Python wrapper for bgslibrary using pybind11 and CMake',
+    long_description='',
+    ext_modules=[CMakeExtension('bgs')],
+    cmdclass=dict(build_ext=CMakeBuild),
+    zip_safe=False,
+    packages=find_packages(),
+    keywords=['BGSLibrary', 'Background Subtraction', 'Computer Vision', 'Machine Learning'],
+)
diff --git a/test.png b/test.png
new file mode 100644
index 0000000000000000000000000000000000000000..aec6f5c4691ce4804abe5a0e03b6d227ade22b48
Binary files /dev/null and b/test.png differ
diff --git a/wrapper_python/bgslibrary_module.cpp b/wrapper_python/bgslibrary_module.cpp
index 35fc57f164bef2519668845cf259c1b7d67ffd62..4c1d0d3335eb6020b2aa6a960b0b4beeb75bfa59 100644
--- a/wrapper_python/bgslibrary_module.cpp
+++ b/wrapper_python/bgslibrary_module.cpp
@@ -14,258 +14,306 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
 */
-#define BOOST_PYTHON_STATIC_LIB
-#include <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <pybind11/pybind11.h>
 #include <exception>
 
 #include <opencv2/opencv.hpp>
-#include "np_opencv_converter.h"
 
+#include "ndarray_converter.h"
 #include "../package_bgs/bgslibrary.h"
 
-namespace py = boost::python;
+namespace py = pybind11;
 
-cv::Mat test_transpose(const cv::Mat& in)
+cv::Mat transpose_image(const cv::Mat& image)
 {
-	std::cerr << "Input size: " << in.size() << std::endl;
-	std::cerr << "Returning transpose" << std::endl;
-	return in.t();
+	std::cerr << "Input size: " << image.size() << std::endl;
+	std::cerr << "Returning the image transpose" << std::endl;
+	return image.t();
 }
 
-namespace fs 
-{ 
-	namespace python 
-	{
-		BOOST_PYTHON_MODULE(libbgs)
-		{
-			// Main types export
-			fs::python::init_and_export_converters();
-			py::scope scope = py::scope();
-			
-			// Basic test
-			py::def("test_transpose", &test_transpose);
-			
-			py::class_<FrameDifference>("FrameDifference")
-			.def("apply", &FrameDifference::apply)
-			.def("getBackgroundModel", &FrameDifference::getBackgroundModel)
-			;
-
-			py::class_<StaticFrameDifference>("StaticFrameDifference")
-				.def("apply", &StaticFrameDifference::apply)
-				.def("getBackgroundModel", &StaticFrameDifference::getBackgroundModel)
-				;
-
-			py::class_<AdaptiveBackgroundLearning>("AdaptiveBackgroundLearning")
-				.def("apply", &AdaptiveBackgroundLearning::apply)
-				.def("getBackgroundModel", &AdaptiveBackgroundLearning::getBackgroundModel)
-				;
-
-			py::class_<AdaptiveSelectiveBackgroundLearning>("AdaptiveSelectiveBackgroundLearning")
-				.def("apply", &AdaptiveSelectiveBackgroundLearning::apply)
-				.def("getBackgroundModel", &AdaptiveSelectiveBackgroundLearning::getBackgroundModel)
-				;
-
-			py::class_<DPAdaptiveMedian>("DPAdaptiveMedian")
-				.def("apply", &DPAdaptiveMedian::apply)
-				.def("getBackgroundModel", &DPAdaptiveMedian::getBackgroundModel)
-				;
-
-			py::class_<DPEigenbackground>("DPEigenbackground")
-				.def("apply", &DPEigenbackground::apply)
-				.def("getBackgroundModel", &DPEigenbackground::getBackgroundModel)
-				;
-
-			py::class_<DPGrimsonGMM>("DPGrimsonGMM")
-				.def("apply", &DPGrimsonGMM::apply)
-				.def("getBackgroundModel", &DPGrimsonGMM::getBackgroundModel)
-				;
-
-			py::class_<DPMean>("DPMean")
-				.def("apply", &DPMean::apply)
-				.def("getBackgroundModel", &DPMean::getBackgroundModel)
-				;
-
-			py::class_<DPPratiMediod>("DPPratiMediod")
-				.def("apply", &DPPratiMediod::apply)
-				.def("getBackgroundModel", &DPPratiMediod::getBackgroundModel)
-				;
-
-			py::class_<DPTexture>("DPTexture")
-				.def("apply", &DPTexture::apply)
-				.def("getBackgroundModel", &DPTexture::getBackgroundModel)
-				;
-
-			py::class_<DPWrenGA>("DPWrenGA")
-				.def("apply", &DPWrenGA::apply)
-				.def("getBackgroundModel", &DPWrenGA::getBackgroundModel)
-				;
-
-			py::class_<DPZivkovicAGMM>("DPZivkovicAGMM")
-				.def("apply", &DPZivkovicAGMM::apply)
-				.def("getBackgroundModel", &DPZivkovicAGMM::getBackgroundModel)
-				;
-
-			py::class_<FuzzyChoquetIntegral>("FuzzyChoquetIntegral")
-				.def("apply", &FuzzyChoquetIntegral::apply)
-				.def("getBackgroundModel", &FuzzyChoquetIntegral::getBackgroundModel)
-				;
-
-			py::class_<FuzzySugenoIntegral>("FuzzySugenoIntegral")
-				.def("apply", &FuzzySugenoIntegral::apply)
-				.def("getBackgroundModel", &FuzzySugenoIntegral::getBackgroundModel)
-				;
+void show_image(const cv::Mat& image)
+{
+	cv::imshow("Image", image);
+	cv::waitKey(0);
+}
+
+cv::Mat read_image(std::string image_name)
+{
+	cv::Mat image = cv::imread(image_name, CV_LOAD_IMAGE_COLOR);
+	return image;
+}
+
+PYBIND11_MODULE(bgs, m)
+{
+	NDArrayConverter::init_numpy();
+	m.doc() = "python wrapper for bgslibrary using pybind11";
+	
+	// Basic test
+  m.def("read_image", &read_image, "A function that read an image", py::arg("image"));
+  m.def("show_image", &show_image, "A function that show an image", py::arg("image"));
+	m.def("transpose_image", &transpose_image, "A function that transpose an image", py::arg("image"));
+
+	py::class_<FrameDifference>(m, "FrameDifference")
+	.def(py::init<>())
+	.def("apply", &FrameDifference::apply)
+	.def("getBackgroundModel", &FrameDifference::getBackgroundModel)
+	;
+
+	py::class_<StaticFrameDifference>(m, "StaticFrameDifference")
+    .def(py::init<>())
+		.def("apply", &StaticFrameDifference::apply)
+		.def("getBackgroundModel", &StaticFrameDifference::getBackgroundModel)
+		;
+
+	py::class_<AdaptiveBackgroundLearning>(m, "AdaptiveBackgroundLearning")
+    .def(py::init<>())
+		.def("apply", &AdaptiveBackgroundLearning::apply)
+		.def("getBackgroundModel", &AdaptiveBackgroundLearning::getBackgroundModel)
+		;
+
+	py::class_<AdaptiveSelectiveBackgroundLearning>(m, "AdaptiveSelectiveBackgroundLearning")
+    .def(py::init<>())
+		.def("apply", &AdaptiveSelectiveBackgroundLearning::apply)
+		.def("getBackgroundModel", &AdaptiveSelectiveBackgroundLearning::getBackgroundModel)
+		;
+
+	py::class_<DPAdaptiveMedian>(m, "DPAdaptiveMedian")
+    .def(py::init<>())
+		.def("apply", &DPAdaptiveMedian::apply)
+		.def("getBackgroundModel", &DPAdaptiveMedian::getBackgroundModel)
+		;
+
+	py::class_<DPEigenbackground>(m, "DPEigenbackground")
+    .def(py::init<>())
+		.def("apply", &DPEigenbackground::apply)
+		.def("getBackgroundModel", &DPEigenbackground::getBackgroundModel)
+		;
+
+	py::class_<DPGrimsonGMM>(m, "DPGrimsonGMM")
+    .def(py::init<>())
+		.def("apply", &DPGrimsonGMM::apply)
+		.def("getBackgroundModel", &DPGrimsonGMM::getBackgroundModel)
+		;
+
+	py::class_<DPMean>(m, "DPMean")
+    .def(py::init<>())
+		.def("apply", &DPMean::apply)
+		.def("getBackgroundModel", &DPMean::getBackgroundModel)
+		;
+
+	py::class_<DPPratiMediod>(m, "DPPratiMediod")
+    .def(py::init<>())
+		.def("apply", &DPPratiMediod::apply)
+		.def("getBackgroundModel", &DPPratiMediod::getBackgroundModel)
+		;
+
+	py::class_<DPTexture>(m, "DPTexture")
+    .def(py::init<>())
+		.def("apply", &DPTexture::apply)
+		.def("getBackgroundModel", &DPTexture::getBackgroundModel)
+		;
+
+	py::class_<DPWrenGA>(m, "DPWrenGA")
+    .def(py::init<>())
+		.def("apply", &DPWrenGA::apply)
+		.def("getBackgroundModel", &DPWrenGA::getBackgroundModel)
+		;
+
+	py::class_<DPZivkovicAGMM>(m, "DPZivkovicAGMM")
+    .def(py::init<>())
+		.def("apply", &DPZivkovicAGMM::apply)
+		.def("getBackgroundModel", &DPZivkovicAGMM::getBackgroundModel)
+		;
+
+	py::class_<FuzzyChoquetIntegral>(m, "FuzzyChoquetIntegral")
+    .def(py::init<>())
+		.def("apply", &FuzzyChoquetIntegral::apply)
+		.def("getBackgroundModel", &FuzzyChoquetIntegral::getBackgroundModel)
+		;
+
+	py::class_<FuzzySugenoIntegral>(m, "FuzzySugenoIntegral")
+    .def(py::init<>())
+		.def("apply", &FuzzySugenoIntegral::apply)
+		.def("getBackgroundModel", &FuzzySugenoIntegral::getBackgroundModel)
+		;
 
 #if CV_MAJOR_VERSION == 2
-			py::class_<GMG>("GMG")
-				.def("apply", &GMG::apply)
-				.def("getBackgroundModel", &GMG::getBackgroundModel)
-				;
+	py::class_<GMG>(m, "GMG")
+    .def(py::init<>())
+		.def("apply", &GMG::apply)
+		.def("getBackgroundModel", &GMG::getBackgroundModel)
+		;
 #endif
 
-			py::class_<IndependentMultimodal>("IndependentMultimodal")
-				.def("apply", &IndependentMultimodal::apply)
-				.def("getBackgroundModel", &IndependentMultimodal::getBackgroundModel)
-				;
+	py::class_<IndependentMultimodal>(m, "IndependentMultimodal")
+    .def(py::init<>())
+		.def("apply", &IndependentMultimodal::apply)
+		.def("getBackgroundModel", &IndependentMultimodal::getBackgroundModel)
+		;
 
-			py::class_<KDE>("KDE")
-				.def("apply", &KDE::apply)
-				.def("getBackgroundModel", &KDE::getBackgroundModel)
-				;
+	py::class_<KDE>(m, "KDE")
+    .def(py::init<>())
+		.def("apply", &KDE::apply)
+		.def("getBackgroundModel", &KDE::getBackgroundModel)
+		;
 
 #if CV_MAJOR_VERSION == 3
-			py::class_<KNN>("KNN")
-				.def("apply", &KNN::apply)
-				.def("getBackgroundModel", &KNN::getBackgroundModel)
-				;
+	py::class_<KNN>(m, "KNN")
+    .def(py::init<>())
+		.def("apply", &KNN::apply)
+		.def("getBackgroundModel", &KNN::getBackgroundModel)
+		;
 #endif
 
-			py::class_<LBAdaptiveSOM>("LBAdaptiveSOM")
-				.def("apply", &LBAdaptiveSOM::apply)
-				.def("getBackgroundModel", &LBAdaptiveSOM::getBackgroundModel)
-				;
-
-			py::class_<LBFuzzyAdaptiveSOM>("LBFuzzyAdaptiveSOM")
-				.def("apply", &LBFuzzyAdaptiveSOM::apply)
-				.def("getBackgroundModel", &LBFuzzyAdaptiveSOM::getBackgroundModel)
-				;
-
-			py::class_<LBFuzzyGaussian>("LBFuzzyGaussian")
-				.def("apply", &LBFuzzyGaussian::apply)
-				.def("getBackgroundModel", &LBFuzzyGaussian::getBackgroundModel)
-				;
-
-			py::class_<LBMixtureOfGaussians>("LBMixtureOfGaussians")
-				.def("apply", &LBMixtureOfGaussians::apply)
-				.def("getBackgroundModel", &LBMixtureOfGaussians::getBackgroundModel)
-				;
-
-			py::class_<LBSimpleGaussian>("LBSimpleGaussian")
-				.def("apply", &LBSimpleGaussian::apply)
-				.def("getBackgroundModel", &LBSimpleGaussian::getBackgroundModel)
-				;
-
-			py::class_<LBP_MRF>("LBP_MRF")
-				.def("apply", &LBP_MRF::apply)
-				.def("getBackgroundModel", &LBP_MRF::getBackgroundModel)
-				;
-
-			py::class_<LOBSTER>("LOBSTER")
-				.def("apply", &LOBSTER::apply)
-				.def("getBackgroundModel", &LOBSTER::getBackgroundModel)
-				;
+	py::class_<LBAdaptiveSOM>(m, "LBAdaptiveSOM")
+    .def(py::init<>())
+		.def("apply", &LBAdaptiveSOM::apply)
+		.def("getBackgroundModel", &LBAdaptiveSOM::getBackgroundModel)
+		;
+
+	py::class_<LBFuzzyAdaptiveSOM>(m, "LBFuzzyAdaptiveSOM")
+    .def(py::init<>())
+		.def("apply", &LBFuzzyAdaptiveSOM::apply)
+		.def("getBackgroundModel", &LBFuzzyAdaptiveSOM::getBackgroundModel)
+		;
+
+	py::class_<LBFuzzyGaussian>(m, "LBFuzzyGaussian")
+    .def(py::init<>())
+		.def("apply", &LBFuzzyGaussian::apply)
+		.def("getBackgroundModel", &LBFuzzyGaussian::getBackgroundModel)
+		;
+
+	py::class_<LBMixtureOfGaussians>(m, "LBMixtureOfGaussians")
+    .def(py::init<>())
+		.def("apply", &LBMixtureOfGaussians::apply)
+		.def("getBackgroundModel", &LBMixtureOfGaussians::getBackgroundModel)
+		;
+
+	py::class_<LBSimpleGaussian>(m, "LBSimpleGaussian")
+    .def(py::init<>())
+		.def("apply", &LBSimpleGaussian::apply)
+		.def("getBackgroundModel", &LBSimpleGaussian::getBackgroundModel)
+		;
+
+	py::class_<LBP_MRF>(m, "LBP_MRF")
+    .def(py::init<>())
+		.def("apply", &LBP_MRF::apply)
+		.def("getBackgroundModel", &LBP_MRF::getBackgroundModel)
+		;
+
+	py::class_<LOBSTER>(m, "LOBSTER")
+    .def(py::init<>())
+		.def("apply", &LOBSTER::apply)
+		.def("getBackgroundModel", &LOBSTER::getBackgroundModel)
+		;
 
 #if CV_MAJOR_VERSION == 2
-			py::class_<MixtureOfGaussianV1>("MixtureOfGaussianV1")
-				.def("apply", &MixtureOfGaussianV1::apply)
-				.def("getBackgroundModel", &MixtureOfGaussianV1::getBackgroundModel)
-				;
+	py::class_<MixtureOfGaussianV1>(m, "MixtureOfGaussianV1")
+    .def(py::init<>())
+		.def("apply", &MixtureOfGaussianV1::apply)
+		.def("getBackgroundModel", &MixtureOfGaussianV1::getBackgroundModel)
+		;
 #endif
 
-			py::class_<MixtureOfGaussianV2>("MixtureOfGaussianV2")
-				.def("apply", &MixtureOfGaussianV2::apply)
-				.def("getBackgroundModel", &MixtureOfGaussianV2::getBackgroundModel)
-				;
-
-			py::class_<MultiCue>("MultiCue")
-				.def("apply", &MultiCue::apply)
-				.def("getBackgroundModel", &MultiCue::getBackgroundModel)
-				;
-
-			py::class_<MultiLayer>("MultiLayer")
-				.def("apply", &MultiLayer::apply)
-				.def("getBackgroundModel", &MultiLayer::getBackgroundModel)
-				;
-
-			py::class_<PAWCS>("PAWCS")
-				.def("apply", &PAWCS::apply)
-				.def("getBackgroundModel", &PAWCS::getBackgroundModel)
-				;
-
-			py::class_<PixelBasedAdaptiveSegmenter>("PixelBasedAdaptiveSegmenter")
-				.def("apply", &PixelBasedAdaptiveSegmenter::apply)
-				.def("getBackgroundModel", &PixelBasedAdaptiveSegmenter::getBackgroundModel)
-				;
-
-			py::class_<SigmaDelta>("SigmaDelta")
-				.def("apply", &SigmaDelta::apply)
-				.def("getBackgroundModel", &SigmaDelta::getBackgroundModel)
-				;
-
-			py::class_<SuBSENSE>("SuBSENSE")
-				.def("apply", &SuBSENSE::apply)
-				.def("getBackgroundModel", &SuBSENSE::getBackgroundModel)
-				;
-
-			py::class_<T2FGMM_UM>("T2FGMM_UM")
-				.def("apply", &T2FGMM_UM::apply)
-				.def("getBackgroundModel", &T2FGMM_UM::getBackgroundModel)
-				;
-
-			py::class_<T2FGMM_UV>("T2FGMM_UV")
-				.def("apply", &T2FGMM_UV::apply)
-				.def("getBackgroundModel", &T2FGMM_UV::getBackgroundModel)
-				;
-
-			py::class_<T2FMRF_UM>("T2FMRF_UM")
-				.def("apply", &T2FMRF_UM::apply)
-				.def("getBackgroundModel", &T2FMRF_UM::getBackgroundModel)
-				;
-
-			py::class_<T2FMRF_UV>("T2FMRF_UV")
-				.def("apply", &T2FMRF_UV::apply)
-				.def("getBackgroundModel", &T2FMRF_UV::getBackgroundModel)
-				;
-
-			py::class_<VuMeter>("VuMeter")
-				.def("apply", &VuMeter::apply)
-				.def("getBackgroundModel", &VuMeter::getBackgroundModel)
-				;
-
-			py::class_<WeightedMovingMean>("WeightedMovingMean")
-				.def("apply", &WeightedMovingMean::apply)
-				.def("getBackgroundModel", &WeightedMovingMean::getBackgroundModel)
-				;
-
-			py::class_<WeightedMovingVariance>("WeightedMovingVariance")
-				.def("apply", &WeightedMovingVariance::apply)
-				.def("getBackgroundModel", &WeightedMovingVariance::getBackgroundModel)
-				;
-
-			py::class_<TwoPoints>("TwoPoints")
-				.def("apply", &TwoPoints::apply)
-				.def("getBackgroundModel", &TwoPoints::getBackgroundModel)
-				;
-
-			py::class_<ViBe>("ViBe")
-				.def("apply", &ViBe::apply)
-				.def("getBackgroundModel", &ViBe::getBackgroundModel)
-				;
-
-			py::class_<CodeBook>("CodeBook")
-				.def("apply", &CodeBook::apply)
-				.def("getBackgroundModel", &CodeBook::getBackgroundModel)
-				;
-		}
-	} // namespace fs
-} // namespace python
+	py::class_<MixtureOfGaussianV2>(m, "MixtureOfGaussianV2")
+    .def(py::init<>())
+		.def("apply", &MixtureOfGaussianV2::apply)
+		.def("getBackgroundModel", &MixtureOfGaussianV2::getBackgroundModel)
+		;
+
+	py::class_<MultiCue>(m, "MultiCue")
+    .def(py::init<>())
+		.def("apply", &MultiCue::apply)
+		.def("getBackgroundModel", &MultiCue::getBackgroundModel)
+		;
+
+	py::class_<MultiLayer>(m, "MultiLayer")
+    .def(py::init<>())
+		.def("apply", &MultiLayer::apply)
+		.def("getBackgroundModel", &MultiLayer::getBackgroundModel)
+		;
+
+	py::class_<PAWCS>(m, "PAWCS")
+    .def(py::init<>())
+		.def("apply", &PAWCS::apply)
+		.def("getBackgroundModel", &PAWCS::getBackgroundModel)
+		;
+
+	py::class_<PixelBasedAdaptiveSegmenter>(m, "PixelBasedAdaptiveSegmenter")
+    .def(py::init<>())
+		.def("apply", &PixelBasedAdaptiveSegmenter::apply)
+		.def("getBackgroundModel", &PixelBasedAdaptiveSegmenter::getBackgroundModel)
+		;
+
+	py::class_<SigmaDelta>(m, "SigmaDelta")
+    .def(py::init<>())
+		.def("apply", &SigmaDelta::apply)
+		.def("getBackgroundModel", &SigmaDelta::getBackgroundModel)
+		;
+
+	py::class_<SuBSENSE>(m, "SuBSENSE")
+    .def(py::init<>())
+		.def("apply", &SuBSENSE::apply)
+		.def("getBackgroundModel", &SuBSENSE::getBackgroundModel)
+		;
+
+	py::class_<T2FGMM_UM>(m, "T2FGMM_UM")
+    .def(py::init<>())
+		.def("apply", &T2FGMM_UM::apply)
+		.def("getBackgroundModel", &T2FGMM_UM::getBackgroundModel)
+		;
+
+	py::class_<T2FGMM_UV>(m, "T2FGMM_UV")
+    .def(py::init<>())
+		.def("apply", &T2FGMM_UV::apply)
+		.def("getBackgroundModel", &T2FGMM_UV::getBackgroundModel)
+		;
+
+	py::class_<T2FMRF_UM>(m, "T2FMRF_UM")
+    .def(py::init<>())
+		.def("apply", &T2FMRF_UM::apply)
+		.def("getBackgroundModel", &T2FMRF_UM::getBackgroundModel)
+		;
+
+	py::class_<T2FMRF_UV>(m, "T2FMRF_UV")
+    .def(py::init<>())
+		.def("apply", &T2FMRF_UV::apply)
+		.def("getBackgroundModel", &T2FMRF_UV::getBackgroundModel)
+		;
+
+	py::class_<VuMeter>(m, "VuMeter")
+    .def(py::init<>())
+		.def("apply", &VuMeter::apply)
+		.def("getBackgroundModel", &VuMeter::getBackgroundModel)
+		;
+
+	py::class_<WeightedMovingMean>(m, "WeightedMovingMean")
+    .def(py::init<>())
+		.def("apply", &WeightedMovingMean::apply)
+		.def("getBackgroundModel", &WeightedMovingMean::getBackgroundModel)
+		;
+
+	py::class_<WeightedMovingVariance>(m, "WeightedMovingVariance")
+    .def(py::init<>())
+		.def("apply", &WeightedMovingVariance::apply)
+		.def("getBackgroundModel", &WeightedMovingVariance::getBackgroundModel)
+		;
+
+	py::class_<TwoPoints>(m, "TwoPoints")
+    .def(py::init<>())
+		.def("apply", &TwoPoints::apply)
+		.def("getBackgroundModel", &TwoPoints::getBackgroundModel)
+		;
+
+	py::class_<ViBe>(m, "ViBe")
+    .def(py::init<>())
+		.def("apply", &ViBe::apply)
+		.def("getBackgroundModel", &ViBe::getBackgroundModel)
+		;
+
+	py::class_<CodeBook>(m, "CodeBook")
+    .def(py::init<>())
+		.def("apply", &CodeBook::apply)
+		.def("getBackgroundModel", &CodeBook::getBackgroundModel)
+		;
+}
diff --git a/wrapper_python/ndarray_converter.cpp b/wrapper_python/ndarray_converter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b95a72f559cf7e6d15082b6d7b939a2025c1117
--- /dev/null
+++ b/wrapper_python/ndarray_converter.cpp
@@ -0,0 +1,352 @@
+// borrowed in spirit from https://github.com/yati-sagade/opencv-ndarray-conversion
+// MIT License
+
+#include "ndarray_converter.h"
+
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include <numpy/ndarrayobject.h>
+
+#if PY_VERSION_HEX >= 0x03000000
+    #define PyInt_Check PyLong_Check
+    #define PyInt_AsLong PyLong_AsLong
+#endif
+
+struct Tmp {
+    const char * name;
+
+    Tmp(const char * name ) : name(name) {}
+};
+
+Tmp info("return value");
+
+bool NDArrayConverter::init_numpy() {
+    // this has to be in this file, since PyArray_API is defined as static
+    import_array1(false);
+    return true;
+}
+
+/*
+ * The following conversion functions are taken/adapted from OpenCV's cv2.cpp file
+ * inside modules/python/src2 folder (OpenCV 3.1.0)
+ */
+
+static PyObject* opencv_error = 0;
+
+static int failmsg(const char *fmt, ...)
+{
+    char str[1000];
+
+    va_list ap;
+    va_start(ap, fmt);
+    vsnprintf(str, sizeof(str), fmt, ap);
+    va_end(ap);
+
+    PyErr_SetString(PyExc_TypeError, str);
+    return 0;
+}
+
+class PyAllowThreads
+{
+public:
+    PyAllowThreads() : _state(PyEval_SaveThread()) {}
+    ~PyAllowThreads()
+    {
+        PyEval_RestoreThread(_state);
+    }
+private:
+    PyThreadState* _state;
+};
+
+class PyEnsureGIL
+{
+public:
+    PyEnsureGIL() : _state(PyGILState_Ensure()) {}
+    ~PyEnsureGIL()
+    {
+        PyGILState_Release(_state);
+    }
+private:
+    PyGILState_STATE _state;
+};
+
+#define ERRWRAP2(expr) \
+try \
+{ \
+    PyAllowThreads allowThreads; \
+    expr; \
+} \
+catch (const cv::Exception &e) \
+{ \
+    PyErr_SetString(opencv_error, e.what()); \
+    return 0; \
+}
+
+using namespace cv;
+
+class NumpyAllocator : public MatAllocator
+{
+public:
+    NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); }
+    ~NumpyAllocator() {}
+
+    UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
+    {
+        UMatData* u = new UMatData(this);
+        u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
+        npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
+        for( int i = 0; i < dims - 1; i++ )
+            step[i] = (size_t)_strides[i];
+        step[dims-1] = CV_ELEM_SIZE(type);
+        u->size = sizes[0]*step[0];
+        u->userdata = o;
+        return u;
+    }
+
+    UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
+    {
+        if( data != 0 )
+        {
+            CV_Error(Error::StsAssert, "The data should normally be NULL!");
+            // probably this is safe to do in such extreme case
+            return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
+        }
+        PyEnsureGIL gil;
+
+        int depth = CV_MAT_DEPTH(type);
+        int cn = CV_MAT_CN(type);
+        const int f = (int)(sizeof(size_t)/8);
+        int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
+        depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
+        depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
+        depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
+        int i, dims = dims0;
+        cv::AutoBuffer<npy_intp> _sizes(dims + 1);
+        for( i = 0; i < dims; i++ )
+            _sizes[i] = sizes[i];
+        if( cn > 1 )
+            _sizes[dims++] = cn;
+        PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
+        if(!o)
+            CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
+        return allocate(o, dims0, sizes, type, step);
+    }
+
+    bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
+    {
+        return stdAllocator->allocate(u, accessFlags, usageFlags);
+    }
+
+    void deallocate(UMatData* u) const
+    {
+        if(!u)
+            return;
+        PyEnsureGIL gil;
+        CV_Assert(u->urefcount >= 0);
+        CV_Assert(u->refcount >= 0);
+        if(u->refcount == 0)
+        {
+            PyObject* o = (PyObject*)u->userdata;
+            Py_XDECREF(o);
+            delete u;
+        }
+    }
+
+    const MatAllocator* stdAllocator;
+};
+
+NumpyAllocator g_numpyAllocator;
+
+bool NDArrayConverter::toMat(PyObject *o, Mat &m)
+{
+    bool allowND = true;
+    if(!o || o == Py_None)
+    {
+        if( !m.data )
+            m.allocator = &g_numpyAllocator;
+        return true;
+    }
+
+    if( PyInt_Check(o) )
+    {
+        double v[] = {static_cast<double>(PyInt_AsLong((PyObject*)o)), 0., 0., 0.};
+        m = Mat(4, 1, CV_64F, v).clone();
+        return true;
+    }
+    if( PyFloat_Check(o) )
+    {
+        double v[] = {PyFloat_AsDouble((PyObject*)o), 0., 0., 0.};
+        m = Mat(4, 1, CV_64F, v).clone();
+        return true;
+    }
+    if( PyTuple_Check(o) )
+    {
+        int i, sz = (int)PyTuple_Size((PyObject*)o);
+        m = Mat(sz, 1, CV_64F);
+        for( i = 0; i < sz; i++ )
+        {
+            PyObject* oi = PyTuple_GET_ITEM(o, i);
+            if( PyInt_Check(oi) )
+                m.at<double>(i) = (double)PyInt_AsLong(oi);
+            else if( PyFloat_Check(oi) )
+                m.at<double>(i) = (double)PyFloat_AsDouble(oi);
+            else
+            {
+                failmsg("%s is not a numerical tuple", info.name);
+                m.release();
+                return false;
+            }
+        }
+        return true;
+    }
+
+    if( !PyArray_Check(o) )
+    {
+        failmsg("%s is not a numpy array, neither a scalar", info.name);
+        return false;
+    }
+
+    PyArrayObject* oarr = (PyArrayObject*) o;
+
+    bool needcopy = false, needcast = false;
+    int typenum = PyArray_TYPE(oarr), new_typenum = typenum;
+    int type = typenum == NPY_UBYTE ? CV_8U :
+               typenum == NPY_BYTE ? CV_8S :
+               typenum == NPY_USHORT ? CV_16U :
+               typenum == NPY_SHORT ? CV_16S :
+               typenum == NPY_INT ? CV_32S :
+               typenum == NPY_INT32 ? CV_32S :
+               typenum == NPY_FLOAT ? CV_32F :
+               typenum == NPY_DOUBLE ? CV_64F : -1;
+
+    if( type < 0 )
+    {
+        if( typenum == NPY_INT64 || typenum == NPY_UINT64 || typenum == NPY_LONG )
+        {
+            needcopy = needcast = true;
+            new_typenum = NPY_INT;
+            type = CV_32S;
+        }
+        else
+        {
+            failmsg("%s data type = %d is not supported", info.name, typenum);
+            return false;
+        }
+    }
+
+#ifndef CV_MAX_DIM
+    const int CV_MAX_DIM = 32;
+#endif
+
+    int ndims = PyArray_NDIM(oarr);
+    if(ndims >= CV_MAX_DIM)
+    {
+        failmsg("%s dimensionality (=%d) is too high", info.name, ndims);
+        return false;
+    }
+
+    int size[CV_MAX_DIM+1];
+    size_t step[CV_MAX_DIM+1];
+    size_t elemsize = CV_ELEM_SIZE1(type);
+    const npy_intp* _sizes = PyArray_DIMS(oarr);
+    const npy_intp* _strides = PyArray_STRIDES(oarr);
+    bool ismultichannel = ndims == 3 && _sizes[2] <= CV_CN_MAX;
+
+    for( int i = ndims-1; i >= 0 && !needcopy; i-- )
+    {
+        // these checks handle cases of
+        //  a) multi-dimensional (ndims > 2) arrays, as well as simpler 1- and 2-dimensional cases
+        //  b) transposed arrays, where _strides[] elements go in non-descending order
+        //  c) flipped arrays, where some of _strides[] elements are negative
+        // the _sizes[i] > 1 is needed to avoid spurious copies when NPY_RELAXED_STRIDES is set
+        if( (i == ndims-1 && _sizes[i] > 1 && (size_t)_strides[i] != elemsize) ||
+            (i < ndims-1 && _sizes[i] > 1 && _strides[i] < _strides[i+1]) )
+            needcopy = true;
+    }
+
+    if( ismultichannel && _strides[1] != (npy_intp)elemsize*_sizes[2] )
+        needcopy = true;
+
+    if (needcopy)
+    {
+        //if (info.outputarg)
+        //{
+        //    failmsg("Layout of the output array %s is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)", info.name);
+        //    return false;
+        //}
+
+        if( needcast ) {
+            o = PyArray_Cast(oarr, new_typenum);
+            oarr = (PyArrayObject*) o;
+        }
+        else {
+            oarr = PyArray_GETCONTIGUOUS(oarr);
+            o = (PyObject*) oarr;
+        }
+
+        _strides = PyArray_STRIDES(oarr);
+    }
+
+    // Normalize strides in case NPY_RELAXED_STRIDES is set
+    size_t default_step = elemsize;
+    for ( int i = ndims - 1; i >= 0; --i )
+    {
+        size[i] = (int)_sizes[i];
+        if ( size[i] > 1 )
+        {
+            step[i] = (size_t)_strides[i];
+            default_step = step[i] * size[i];
+        }
+        else
+        {
+            step[i] = default_step;
+            default_step *= size[i];
+        }
+    }
+
+    // handle degenerate case
+    if( ndims == 0) {
+        size[ndims] = 1;
+        step[ndims] = elemsize;
+        ndims++;
+    }
+
+    if( ismultichannel )
+    {
+        ndims--;
+        type |= CV_MAKETYPE(0, size[2]);
+    }
+
+    if( ndims > 2 && !allowND )
+    {
+        failmsg("%s has more than 2 dimensions", info.name);
+        return false;
+    }
+
+    m = Mat(ndims, size, type, PyArray_DATA(oarr), step);
+    m.u = g_numpyAllocator.allocate(o, ndims, size, type, step);
+    m.addref();
+
+    if( !needcopy )
+    {
+        Py_INCREF(o);
+    }
+    m.allocator = &g_numpyAllocator;
+
+    return true;
+}
+
+PyObject* NDArrayConverter::toNDArray(const cv::Mat& m)
+{
+    if( !m.data )
+        Py_RETURN_NONE;
+    Mat temp, *p = (Mat*)&m;
+    if(!p->u || p->allocator != &g_numpyAllocator)
+    {
+        temp.allocator = &g_numpyAllocator;
+        ERRWRAP2(m.copyTo(temp));
+        p = &temp;
+    }
+    PyObject* o = (PyObject*)p->u->userdata;
+    Py_INCREF(o);
+    return o;
+}
diff --git a/wrapper_python/ndarray_converter.h b/wrapper_python/ndarray_converter.h
new file mode 100644
index 0000000000000000000000000000000000000000..da5ea16cd65dc2e8e1c9687e2af5ecb4bb74429b
--- /dev/null
+++ b/wrapper_python/ndarray_converter.h
@@ -0,0 +1,42 @@
+# ifndef __NDARRAY_CONVERTER_H__
+# define __NDARRAY_CONVERTER_H__
+
+#include <Python.h>
+#include <opencv2/core/core.hpp>
+
+
+class NDArrayConverter {
+public:
+    // must call this first, or the other routines don't work!
+    static bool init_numpy();
+    
+    static bool toMat(PyObject* o, cv::Mat &m);
+    static PyObject* toNDArray(const cv::Mat& mat);
+};
+
+//
+// Define the type converter
+//
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11 { namespace detail {
+    
+template <> struct type_caster<cv::Mat> {
+public:
+    
+    PYBIND11_TYPE_CASTER(cv::Mat, _("numpy.ndarray"));
+    
+    bool load(handle src, bool) {
+        return NDArrayConverter::toMat(src.ptr(), value);
+    }
+    
+    static handle cast(const cv::Mat &m, return_value_policy, handle defval) {
+        return handle(NDArrayConverter::toNDArray(m));
+    }
+};
+    
+    
+}} // namespace pybind11::detail
+
+# endif
diff --git a/wrapper_python/np_opencv_converter.cpp b/wrapper_python/np_opencv_converter.cpp
deleted file mode 100644
index 6799b4c0853fec9d59849cd1c37ef2bc8b44cb0d..0000000000000000000000000000000000000000
--- a/wrapper_python/np_opencv_converter.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "np_opencv_converter.h"
-
-namespace fs { namespace python {
-
-// Static PyInit
-#if PY_VERSION_HEX >= 0x03000000
-  static int py_init() {
-    Py_Initialize();
-    import_array();
-    return NULL;
-  }
-#else
-  static void py_init() {
-    Py_Initialize();
-    import_array();
-  }
-#endif
-
-// Singleton init and export converters
-static bool export_type_conversions_once = false;
-bool init_and_export_converters() {
-
-  if (export_type_conversions_once)
-    return false;
-  
-  std::cerr << "PYTHON TYPE CONVERTERS exported" << std::endl;
-  export_type_conversions_once = true;
-
-  // Py_Init and array import
-  py_init();
-  
-  // => py::list
-  expose_template_type<int>();
-  expose_template_type<float>();
-  expose_template_type<double>();
-
-  // std::vector => py::list
-  expose_template_type< std::vector<int> >();
-  expose_template_type< std::vector<float> >();
-  expose_template_type< std::vector<double> >();
-
-  expose_template_type< std::vector<cv::Point> >();
-  expose_template_type< std::vector<cv::Point2f> >();
-  expose_template_type< std::vector<cv::KeyPoint> >();
-  
-  expose_template_type< std::vector<cv::Mat> >();
-  expose_template_type< std::vector<cv::Mat1b > >();
-  expose_template_type< std::vector<cv::Mat1f > >();
-
-  // std::map => py::dict
-  expose_template_type<std::map<int, std::vector<int> > >();
-  expose_template_type<std::map<int, std::vector<float> > >();
-  expose_template_type<std::map<std::string, float> >();
-
-  // various converters to cv::Mat
-  py::to_python_converter<cv::Point, Point_to_mat>();
-  py::to_python_converter<cv::Point2f, Point2f_to_mat>();
-  py::to_python_converter<cv::Point3f, Point3f_to_mat>();
-  py::to_python_converter<cv::Vec3f, Vec3f_to_mat>();
-
-  // register the to-from-python converter for each of the types
-  Mat_PyObject_converter< cv::Mat >();
-  
-  // 1-channel
-  Mat_PyObject_converter< cv::Mat1b >();
-  Mat_PyObject_converter< cv::Mat1s >();
-  Mat_PyObject_converter< cv::Mat1w >();
-  Mat_PyObject_converter< cv::Mat1i >();
-  Mat_PyObject_converter< cv::Mat1f >();
-  Mat_PyObject_converter< cv::Mat1d >();
-
-  // 2-channel
-  Mat_PyObject_converter< cv::Mat2b >();
-  Mat_PyObject_converter< cv::Mat2s >();
-  Mat_PyObject_converter< cv::Mat2w >();
-  Mat_PyObject_converter< cv::Mat2i >();
-  Mat_PyObject_converter< cv::Mat2f >();
-  Mat_PyObject_converter< cv::Mat2d >();
-
-  // 3-channel
-  Mat_PyObject_converter< cv::Mat3b >();
-  Mat_PyObject_converter< cv::Mat3s >();
-  Mat_PyObject_converter< cv::Mat3w >();
-  Mat_PyObject_converter< cv::Mat3i >();
-  Mat_PyObject_converter< cv::Mat3f >();
-  Mat_PyObject_converter< cv::Mat3d >();
-
-  // add more if needed
-
-  return true;
-}
-
-} // namespace python
-} // namespace fs
-
diff --git a/wrapper_python/np_opencv_converter.h b/wrapper_python/np_opencv_converter.h
deleted file mode 100644
index ada6020378f51c71f1c3505f9001f8dd9c6f6567..0000000000000000000000000000000000000000
--- a/wrapper_python/np_opencv_converter.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#define BOOST_PYTHON_STATIC_LIB
-#include <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-
-#include "utils/template.h"
-#include "utils/container.h"
-#include "utils/conversion.h"
-
-#include <opencv2/opencv.hpp>
-
-namespace fs { namespace python {
-
-// TODO: Template these
-// Vec3f => cv::Mat
-struct Vec3f_to_mat {
-  static PyObject* convert(const cv::Vec3f& v){
-    NDArrayConverter cvt;
-    PyObject* ret = cvt.toNDArray(cv::Mat(v));
-    return ret;
-  }
-};
-
-// cv::Point => cv::Mat
-struct Point_to_mat {
-  static PyObject* convert(const cv::Point& v){
-    NDArrayConverter cvt;
-    PyObject* ret = cvt.toNDArray(cv::Mat(v));
-    return ret;
-  }
-};
-
-// cv::Point2f => cv::Mat
-struct Point2f_to_mat {
-  static PyObject* convert(const cv::Point2f& v){
-    NDArrayConverter cvt;
-    PyObject* ret = cvt.toNDArray(cv::Mat(v));
-    return ret;
-  }
-};
-
-// cv::Point3f => cv::Mat
-struct Point3f_to_mat {
-  static PyObject* convert(const cv::Point3f& v){
-    NDArrayConverter cvt;
-    PyObject* ret = cvt.toNDArray(cv::Mat(v));
-    return ret;
-  }
-};
-
-// cv::Mat_<T> => Numpy PyObject
-template <typename T>
-struct Mat_to_PyObject {
-  static PyObject* convert(const T& mat){
-    NDArrayConverter cvt;
-    PyObject* ret = cvt.toNDArray(mat);
-    return ret;
-  }
-};
-
-// Generic templated cv::Mat <=> Numpy PyObject converter
-template <typename T>
-struct Mat_PyObject_converter
-{
-  // Register from converter
-  Mat_PyObject_converter() {
-    boost::python::converter::registry::push_back(
-        &convertible,
-        &construct,
-        boost::python::type_id<T>());
-
-    // Register to converter
-    py::to_python_converter<T, Mat_to_PyObject<T> >();
-  }
-
-  // Convert from type T to PyObject (numpy array)
-  // Assume obj_ptr can be converted in a cv::Mat
-  static void* convertible(PyObject* obj_ptr)
-  {
-    // Check validity? 
-    assert(obj_ptr != 0); 
-    return obj_ptr;
-  }
-
-  // Convert obj_ptr into a cv::Mat
-  static void construct(PyObject* obj_ptr,
-                        boost::python::converter::rvalue_from_python_stage1_data* data)
-  {
-    using namespace boost::python;
-    typedef converter::rvalue_from_python_storage< T > storage_t;
-
-    // Object is a borrowed reference, so create a handle indicating it is
-    // borrowed for proper reference counting.
-    boost::python::handle<> handle(boost::python::borrowed(obj_ptr));
-
-    storage_t* the_storage = reinterpret_cast<storage_t*>( data );
-    void* memory_chunk = the_storage->storage.bytes;
-
-    NDArrayConverter cvt;
-    T* newvec = new (memory_chunk) T(cvt.toMat(obj_ptr));
-    data->convertible = memory_chunk;
-
-    return;
-  }
-};
-
-bool init_and_export_converters();
-
-} // namespace python
-} // namespace fs
diff --git a/wrapper_python/utils/container.h b/wrapper_python/utils/container.h
deleted file mode 100644
index 3db5613a9e4a1f694fbbf008c2c0c6d0913eb730..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/container.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-// Author: Sudeep Pillai (spillai@csail.mit.edu)
-// Note: Stripped from pyxx project
-
-#pragma once
-
-#include <boost/python.hpp>
-#include <boost/python/class.hpp>
-#include <boost/python/module.hpp>
-#include <boost/foreach.hpp>
-
-#include <vector>
-#include <string>
-#include <stdexcept>
-#include <iostream>
-#include <map>
-#include <list>
-
-namespace py = boost::python;
-
-template<typename T>
-struct expose_template_type< std::vector<T> > :
-    public expose_template_type_base< std::vector<T> >
-{
-  typedef expose_template_type_base< std::vector<T> > base_type;
-  typedef expose_template_type< std::vector<T> > this_type;
-  typedef std::vector<T> wrapped_type;
-
-  expose_template_type()
-  {
-    ::expose_template_type<T>();
-    if( !base_type::wrapped() )
-    {
-      py::to_python_converter< wrapped_type, this_type >();
-      py::converter::registry::push_back(
-          this_type::convertible,
-          this_type::construct,
-          py::type_id< wrapped_type >() );
- 
-    }
-  }
-
-  static PyObject * convert( const wrapped_type & container)
-  {
-    py::list l;
-    for(typename wrapped_type::const_iterator iter = container.begin(); iter != container.end(); iter++)
-    {
-      l.append( py::object( *iter ) );
-    }
-    Py_INCREF( l.ptr() );
-    return l.ptr();
-  }
-
-  static void * convertible( PyObject * py_obj)
-  {
-    // we are supposed to indicate whether or not we can convert this
-    // we don't really know, but we'll try any sequence
-    if( PySequence_Check(py_obj) )
-      return py_obj;
-    return 0;
-  }
-    
-  static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data)
-  {
-    using namespace boost::python;
-    typedef converter::rvalue_from_python_storage< wrapped_type > storage_t;
-        
-    storage_t* the_storage = reinterpret_cast<storage_t*>( data );
-    void* memory_chunk = the_storage->storage.bytes;
-    wrapped_type * newvec = new (memory_chunk) wrapped_type;
-    data->convertible = memory_chunk;
-
-    object sequence(handle<>( borrowed( py_obj ) ) );
-
-    for(int idx = 0; idx < len(sequence);idx++)
-    {
-      newvec->push_back( extract<T>( sequence[idx] )() );
-    }
-
-  }
-
-};
-
-template<typename Key, typename Value>
-    struct expose_template_type< std::map<Key, Value> > :
-    public expose_template_type_base< std::map<Key, Value> >
-{
-  typedef std::map<Key, Value> wrapped_type;
-  typedef expose_template_type_base< wrapped_type > base_type;
-  typedef expose_template_type< wrapped_type > this_type;
-
-  expose_template_type()
-  {
-    if( !base_type::wrapped() )
-    {
-      py::to_python_converter< wrapped_type, this_type >();
-      py::converter::registry::push_back(
-          this_type::convertible,
-          this_type::construct,
-          py::type_id< wrapped_type >() );
- 
-    }
-  }
-
-  static PyObject * convert( const wrapped_type & container)
-  {
-    py::dict d;
-    for(typename wrapped_type::const_iterator iter = container.begin(); iter != container.end(); iter++)
-    {
-      d[iter->first] = py::object(iter->second);
-    }
-    Py_INCREF( d.ptr() );
-    return d.ptr();
-  }
-
-  static void * convertible( PyObject * py_obj)
-  {
-    // we are supposed to indicate whether or not we can convert this
-    // we don't really know, but we'll try any sequence
-    if( PyMapping_Check(py_obj) )
-      return py_obj;
-    return 0;
-  }
-    
-  static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data)
-  {
-    using namespace boost::python;
-    typedef converter::rvalue_from_python_storage< wrapped_type > storage_t;
-        
-    storage_t* the_storage = reinterpret_cast<storage_t*>( data );
-    void* memory_chunk = the_storage->storage.bytes;
-    wrapped_type * newvec = new (memory_chunk) wrapped_type;
-    data->convertible = memory_chunk;
-
-    object sequence(handle<>( borrowed( py_obj ) ) );
-    sequence = sequence.attr("items")();
-
-    for(int idx = 0; idx < len(sequence);idx++)
-    {
-      Key key = py::extract<Key>(sequence[idx][0])();
-      Value value = py::extract<Value>(sequence[idx][1])();
-      (*newvec)[key] = value;
-    }
-
-  }
-
-};
-
-template<typename Key, typename Value>
-    struct expose_template_type< typename std::pair<Key, Value> > :
-    public expose_template_type_base< std::pair<Key, Value> >
-{
-  typedef std::pair<Key, Value> wrapped_type;
-  typedef expose_template_type_base< wrapped_type > base_type;
-  typedef expose_template_type< wrapped_type > this_type;
-
-  expose_template_type()
-  {
-    if( !base_type::wrapped() )
-    {
-      py::converter::registry::push_back(
-          this_type::convertible,
-          this_type::construct,
-          py::type_id< wrapped_type >() );
- 
-    }
-  }
-
-  static void * convertible( PyObject * py_obj)
-  {
-    // we are supposed to indicate whether or not we can convert this
-    // we don't really know, but we'll try any sequence
-    if( PyTuple_Check(py_obj) && PyTuple_Size(py_obj) == 2)
-      return py_obj;
-    return 0;
-  }
-    
-  static void construct( PyObject * py_obj, py::converter::rvalue_from_python_stage1_data* data)
-  {
-    using namespace boost::python;
-    typedef converter::rvalue_from_python_storage< wrapped_type > storage_t;
-        
-    storage_t* the_storage = reinterpret_cast<storage_t*>( data );
-    void* memory_chunk = the_storage->storage.bytes;
-    wrapped_type * newvec = new (memory_chunk) wrapped_type;
-    data->convertible = memory_chunk;
-
-    object sequence(handle<>( borrowed( py_obj ) ) );
-    newvec->first = extract<Key>(sequence[0])();
-    newvec->second = extract<Value>(sequence[1])();
-  }
-
-};
diff --git a/wrapper_python/utils/conversion.cpp b/wrapper_python/utils/conversion.cpp
deleted file mode 100644
index 27b06a7dceac9866758e9928f95f1717c9d4292d..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/conversion.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-// Author: Sudeep Pillai (spillai@csail.mit.edu)
-// Note: Stripped from Opencv (opencv/modules/python/src2/cv2.cpp)
-
-# include "conversion.h"
-/*
- * The following conversion functions are taken/adapted from OpenCV's cv2.cpp file
- * inside modules/python/src2 folder.
- */
-
-#if PY_VERSION_HEX >= 0x03000000
-static int init()
-{
-  import_array();
-  return NULL;
-}
-#else
-static void init()
-{
-  import_array();
-}
-#endif
-
-static int failmsg(const char *fmt, ...)
-{
-    char str[1000];
-
-    va_list ap;
-    va_start(ap, fmt);
-    vsnprintf(str, sizeof(str), fmt, ap);
-    va_end(ap);
-
-    PyErr_SetString(PyExc_TypeError, str);
-    return 0;
-}
-
-class PyAllowThreads
-{
-public:
-    PyAllowThreads() : _state(PyEval_SaveThread()) {}
-    ~PyAllowThreads()
-    {
-        PyEval_RestoreThread(_state);
-    }
-private:
-    PyThreadState* _state;
-};
-
-class PyEnsureGIL
-{
-public:
-    PyEnsureGIL() : _state(PyGILState_Ensure()) {}
-    ~PyEnsureGIL()
-    {
-        PyGILState_Release(_state);
-    }
-private:
-    PyGILState_STATE _state;
-};
-
-using namespace cv;
-static PyObject* failmsgp(const char *fmt, ...)
-{
-  char str[1000];
-
-  va_list ap;
-  va_start(ap, fmt);
-  vsnprintf(str, sizeof(str), fmt, ap);
-  va_end(ap);
-
-  PyErr_SetString(PyExc_TypeError, str);
-  return 0;
-}
-
-#if CV_MAJOR_VERSION == 3
-class NumpyAllocator : public MatAllocator
-{
-public:
-    NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); }
-    ~NumpyAllocator() {}
-
-    UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
-    {
-        UMatData* u = new UMatData(this);
-        u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
-        npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
-        for( int i = 0; i < dims - 1; i++ )
-            step[i] = (size_t)_strides[i];
-        step[dims-1] = CV_ELEM_SIZE(type);
-        u->size = sizes[0]*step[0];
-        u->userdata = o;
-        return u;
-    }
-
-    UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags=USAGE_DEFAULT) const
-    {
-        if( data != 0 )
-        {
-            CV_Error(Error::StsAssert, "The data should normally be NULL!");
-            // probably this is safe to do in such extreme case
-            return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
-        }
-        PyEnsureGIL gil;
-
-        int depth = CV_MAT_DEPTH(type);
-        int cn = CV_MAT_CN(type);
-        const int f = (int)(sizeof(size_t)/8);
-        int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
-        depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
-        depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
-        depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
-        int i, dims = dims0;
-        cv::AutoBuffer<npy_intp> _sizes(dims + 1);
-        for( i = 0; i < dims; i++ )
-            _sizes[i] = sizes[i];
-        if( cn > 1 )
-            _sizes[dims++] = cn;
-        PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
-        if(!o)
-            CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
-        return allocate(o, dims0, sizes, type, step);
-    }
-
-    bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags=USAGE_DEFAULT) const
-    {
-        return stdAllocator->allocate(u, accessFlags, usageFlags);
-    }
-
-    void deallocate(UMatData* u) const
-    {
-        if(u)
-        {
-            PyEnsureGIL gil;
-            PyObject* o = (PyObject*)u->userdata;
-            Py_XDECREF(o);
-            delete u;
-        }
-    }
- 
-    const MatAllocator* stdAllocator;
-};
-#else
-class NumpyAllocator : public MatAllocator
-{
-public:
-    NumpyAllocator() {}
-    ~NumpyAllocator() {}
-
-    void allocate(int dims, const int* sizes, int type, int*& refcount,
-                  uchar*& datastart, uchar*& data, size_t* step)
-    {
-        PyEnsureGIL gil;
-
-        int depth = CV_MAT_DEPTH(type);
-        int cn = CV_MAT_CN(type);
-        const int f = (int)(sizeof(size_t)/8);
-        int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
-                      depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
-                      depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
-                      depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
-        int i;
-        npy_intp _sizes[CV_MAX_DIM+1];
-        for( i = 0; i < dims; i++ )
-            _sizes[i] = sizes[i];
-        if( cn > 1 )
-        {
-            /*if( _sizes[dims-1] == 1 )
-                _sizes[dims-1] = cn;
-            else*/
-                _sizes[dims++] = cn;
-        }
-        PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
-        if(!o)
-            CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
-        refcount = refcountFromPyObject(o);
-        npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
-        for( i = 0; i < dims - (cn > 1); i++ )
-            step[i] = (size_t)_strides[i];
-        datastart = data = (uchar*)PyArray_DATA((PyArrayObject*) o);
-    }
-
-    void deallocate(int* refcount, uchar*, uchar*)
-    {
-        PyEnsureGIL gil;
-        if( !refcount )
-            return;
-        PyObject* o = pyObjectFromRefcount(refcount);
-        Py_INCREF(o);
-        Py_DECREF(o);
-    }
-};
-#endif
-  
-
-  
-NumpyAllocator g_numpyAllocator;
-
-NDArrayConverter::NDArrayConverter() { init(); }
-
-#if PY_VERSION_HEX >= 0x03000000
-int NDArrayConverter::init()
-{
-  import_array();
-  return NULL;
-}
-#else
-void NDArrayConverter::init()
-{
-  import_array();
-}
-#endif
-
-cv::Mat NDArrayConverter::toMat(const PyObject *o)
-{
-    cv::Mat m;
-
-    if(!o || o == Py_None)
-    {
-        if( !m.data )
-            m.allocator = &g_numpyAllocator;
-    }
-
-    if( !PyArray_Check(o) )
-    {
-        failmsg("toMat: Object is not a numpy array");
-    }
-
-    int typenum = PyArray_TYPE(o);
-    int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :
-               typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :
-               typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :
-               typenum == NPY_FLOAT ? CV_32F :
-               typenum == NPY_DOUBLE ? CV_64F : -1;
-
-    if( type < 0 )
-    {
-        failmsg("toMat: Data type = %d is not supported", typenum);
-    }
-
-    int ndims = PyArray_NDIM(o);
-
-    if(ndims >= CV_MAX_DIM)
-    {
-        failmsg("toMat: Dimensionality (=%d) is too high", ndims);
-    }
-
-    int size[CV_MAX_DIM+1];
-    size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);
-    const npy_intp* _sizes = PyArray_DIMS(o);
-    const npy_intp* _strides = PyArray_STRIDES(o);
-    bool transposed = false;
-    
-    for(int i = 0; i < ndims; i++)
-    {
-        size[i] = (int)_sizes[i];
-        step[i] = (size_t)_strides[i];
-    }
-
-    if( ndims == 0 || step[ndims-1] > elemsize ) {
-        size[ndims] = 1;
-        step[ndims] = elemsize;
-        ndims++;
-    }
-
-    if( ndims >= 2 && step[0] < step[1] )
-    {
-        std::swap(size[0], size[1]);
-        std::swap(step[0], step[1]);
-        transposed = true;
-    }
-
-    // std::cerr << " ndims: " << ndims
-    //           << " size: " << size
-    //           << " type: " << type
-    //           << " step: " << step 
-    //           << " size: " << size[2] << std::endl;
-
-    // TODO: Possible bug in multi-dimensional matrices
-#if 1
-    if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )
-    {
-        ndims--;
-        type |= CV_MAKETYPE(0, size[2]);
-    }
-#endif
-    
-    if( ndims > 2)
-    {
-        failmsg("toMat: Object has more than 2 dimensions");
-    }
-    
-    m = Mat(ndims, size, type, PyArray_DATA(o), step);
-    // m.u = g_numpyAllocator.allocate(o, ndims, size, type, step);
-    
-    if( m.data )
-    {
-#if CV_MAJOR_VERSION == 3
-      m.addref();
-// Not needed anymore, the pointer is now managed by a borrowed handle, which
-// which will handle reference counting.
-//      Py_INCREF(o);
-#else
-// TODO: I assume this one is leaking too, but don't have CV v2 to test.
-        m.refcount = refcountFromPyObject(o);
-        m.addref(); // protect the original numpy array from deallocation
-                    // (since Mat destructor will decrement the reference counter)
-#endif
-    };
-    m.allocator = &g_numpyAllocator;
-
-    if( transposed )
-    {
-        Mat tmp;
-        tmp.allocator = &g_numpyAllocator;
-        transpose(m, tmp);
-        m = tmp;
-    }
-    return m;
-}
-
-PyObject* NDArrayConverter::toNDArray(const cv::Mat& m)
-{
-#if CV_MAJOR_VERSION == 3
-  if( !m.data )
-        Py_RETURN_NONE;
-    Mat temp, *p = (Mat*)&m;
-    if(!p->u || p->allocator != &g_numpyAllocator)
-    {
-        temp.allocator = &g_numpyAllocator;
-        m.copyTo(temp);
-        p = &temp;
-    }
-    PyObject* o = (PyObject*)p->u->userdata;
-    Py_INCREF(o);
-    // p->addref();
-    // pyObjectFromRefcount(p->refcount);
-    return o; 
-#else
-    if( !m.data )
-      Py_RETURN_NONE;
-    Mat temp, *p = (Mat*)&m;
-    if(!p->refcount || p->allocator != &g_numpyAllocator)
-    {
-        temp.allocator = &g_numpyAllocator;
-        ERRWRAP2(m.copyTo(temp));
-        p = &temp;
-    }
-    p->addref();
-    return pyObjectFromRefcount(p->refcount);
-#endif
-
-}
diff --git a/wrapper_python/utils/conversion.h b/wrapper_python/utils/conversion.h
deleted file mode 100644
index 4f7aa968a84b850b8668370bfa43bfd6ccf90d6b..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/conversion.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-// Author: Sudeep Pillai (spillai@csail.mit.edu)
-// Note: Stripped from Opencv (opencv/modules/python/src2/cv2.cpp)
-
-#pragma once
-
-#include <Python.h>
-#include <opencv2/opencv.hpp>
-#include <numpy/ndarrayobject.h>
-
-static PyObject* opencv_error = 0;
-
-static int failmsg(const char *fmt, ...);
-
-class PyAllowThreads;
-
-class PyEnsureGIL;
-
-#define ERRWRAP2(expr) \
-try \
-{ \
-    PyAllowThreads allowThreads; \
-    expr; \
-} \
-catch (const cv::Exception &e) \
-{ \
-    PyErr_SetString(opencv_error, e.what()); \
-    return 0; \
-}
-
-static PyObject* failmsgp(const char *fmt, ...);
-
-static size_t REFCOUNT_OFFSET = (size_t)&(((PyObject*)0)->ob_refcnt) +
-    (0x12345678 != *(const size_t*)"\x78\x56\x34\x12\0\0\0\0\0")*sizeof(int);
-
-static inline PyObject* pyObjectFromRefcount(const int* refcount)
-{
-    return (PyObject*)((size_t)refcount - REFCOUNT_OFFSET);
-}
-
-static inline int* refcountFromPyObject(const PyObject* obj)
-{
-    return (int*)((size_t)obj + REFCOUNT_OFFSET);
-}
-
-
-class NumpyAllocator;
-
-enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
-
-class NDArrayConverter
-{
-private:
-#if PY_VERSION_HEX >= 0x03000000
-  int init();
-#else
-  void init();
-#endif
-  
-public:
-    NDArrayConverter();
-    cv::Mat toMat(const PyObject* o);
-    PyObject* toNDArray(const cv::Mat& mat);
-};
diff --git a/wrapper_python/utils/template.h b/wrapper_python/utils/template.h
deleted file mode 100644
index 3f0b535a8df7b92d645d63787787900644f77f56..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/template.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-This file is part of BGSLibrary.
-
-BGSLibrary is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-BGSLibrary is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
-// Author: Sudeep Pillai (spillai@csail.mit.edu)
-// Note: Stripped from pyxx project
-
-#pragma once
-
-#include <boost/python.hpp>
-/*
- * Provides template support
- */
-
-template<typename TemplateType>
-struct expose_template_type
-{
-   // do nothing! 
-};
-
-template<typename TemplateType>
-struct expose_template_type_base
-{
-    bool wrapped()
-    {
-        using namespace boost::python::converter;
-        using namespace boost::python;
-        registration const * p = registry::query( type_id<TemplateType>() );
-        return p && (p->m_class_object || p->m_to_python);
-    }
-
-};