diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..473518b31247ac107bba824c4d8189b6ad13a618
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: https://www.paypal.me/andrewssobral
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000000000000000000000000000000000..6920e4be380dd49bae41766e5eebb6a697813a42
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
+---
+name: Bug report
+about: Create a report to help us improve
+
+---
+
+If you open a GitHub issue, here is our policy:
+
+1. It must be a bug, a feature request, or a significant problem with documentation (for small docs fixes please send a PR instead).
+2. The form below must be filled out.
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior.
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+### System information
+**Desktop (please complete the following information):**
+- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:
+- **Python version (for issues related to the python wrapper)**: 
+- **Java version (for issues related to the java wrapper)**: 
+- **MATLAB version (for issues related to the matlab wrapper)**: 
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..066b2d920a28db73b4ba3a0b35e6905eeeef5772
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,17 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.gitignore b/.gitignore
index f1d9cb4f152103523a763b0ee6d6d67515a8239c..fea4abeebeacf41c52c2e31f8582808dfdf633a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,30 @@
 etc/
+tmp/
+bkp/
+build-*/
 build_*/
+dist/
 dataset_*/
 binaries*/
-java_gui/dist/
-java_gui/build/
-java_gui/bgslibrary.exe
-python/
-qt_gui/
-fet/etc/
+examples/build-*/
+examples/build_*/
+gui/java/dist/
+gui/java/build/
+gui/java/bgslibrary.exe
+_*
 *.exe
 *.pdb
 *.suo
 *.dll
+*.pyd
+*.so
+*.config
+*.creator
+*.creator.user
+*.files
+*.includes
+*.egg-info/
+.vscode/
+bgslibrary_gui
+.pypirc
+upload.sh
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..75ed460c4816f2deba70ef6a7abb77bbc543c41e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "pybind11"]
+	path = modules/pybind11
+	url = https://github.com/pybind/pybind11.git
diff --git a/.properties b/.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cd92d6b08519670a0c5c1d82e502580766840f53
--- /dev/null
+++ b/.properties
@@ -0,0 +1 @@
+version=3.0.0-SNAPSHOT
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d668f260fc04479100b0fb447cad7c730397af16..2e8bb3d325358ff690ab07a3c249faeefb3dd750 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,20 +1,41 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.1)
 
 project(bgslibrary)
 
-# cmake -D BGS_PYTHON_SUPPORT=ON ..
-if(NOT DEFINED BGS_PYTHON_SUPPORT)
-	set(BGS_PYTHON_SUPPORT OFF)
-elseif()
-	# add_definitions(-DBGS_PYTHON_SUPPORT)
-endif()
-message(STATUS "BGSLIBRARY WITH PYTHON SUPPORT: ${BGS_PYTHON_SUPPORT}")
+include(CheckCXXCompilerFlag)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+function(append_if condition value)
+  if (${condition})
+    foreach(variable ${ARGN})
+      set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
+    endforeach(variable)
+  endif()
+endfunction()
+
+#if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
+#    CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+#    CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+#  check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG)
+#  append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility=hidden -fvisibility-inlines-hidden" CMAKE_CXX_FLAGS)
+#endif()
 
 if(UNIX)
-	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++2a")
+  set(CMAKE_MACOSX_RPATH 1)
 endif(UNIX)
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+# 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)
 
 # compilation mode setup
@@ -22,8 +43,15 @@ set(CMAKE_BUILD_TYPE Release)
 #set(CMAKE_BUILD_TYPE Debug)
 
 if(WIN32)
-	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
-	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
+  set(BUILD_SHARED_LIBS TRUE)
+  #if(BGS_PYTHON_SUPPORT)
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
+    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
+  #else()
+  #  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+  #  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+  #endif()
 endif(WIN32)
 
 set(bgs_out_dir ".")
@@ -33,121 +61,260 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${bgs_out_dir})
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${bgs_out_dir})
 # Second, for multi-config builds (e.g. msvc)
 foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
-    string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
-    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
-    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
-    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+  string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
 endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
 
 if(UNIX)
-	# add some standard warnings
-	ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
+  # add some standard warnings
+  ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
 
-	# -ansi does not compile with sjn module
-	#ADD_DEFINITIONS(-ansi)
+  # -ansi does not compile with sjn module
+  #ADD_DEFINITIONS(-ansi)
 
-	# if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
-	#ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
+  # if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
+  #ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
 endif(UNIX)
 
-set(OpenCV_STATIC OFF)
-find_package(OpenCV REQUIRED)
+# cmake -D BGS_PYTHON_SUPPORT=ON ..
+if(NOT DEFINED BGS_PYTHON_SUPPORT)
+  set(BGS_PYTHON_SUPPORT OFF)
+else()
+  # add_definitions(-DBGS_PYTHON_SUPPORT)
+endif()
+# cmake -D BGS_PYTHON_ONLY=ON ..
+if(NOT DEFINED BGS_PYTHON_ONLY)
+  set(BGS_PYTHON_ONLY OFF)
+else()
+  # add_definitions(-DBGS_PYTHON_ONLY)
+endif()
+# cmake -D BGS_CORE_STATIC=ON ..
+if(NOT DEFINED BGS_CORE_STATIC)
+  set(BGS_CORE_STATIC OFF)
+else()
+  # add_definitions(-DBGS_CORE_STATIC)
+endif()
+message(STATUS "")
+message(STATUS "BGS_PYTHON_SUPPORT: ${BGS_PYTHON_SUPPORT}")
+message(STATUS "BGS_PYTHON_ONLY:    ${BGS_PYTHON_ONLY}")
+message(STATUS "BGS_CORE_STATIC:    ${BGS_CORE_STATIC}")
 
-message(STATUS "OpenCV library status:")
-message(STATUS "    version: ${OpenCV_VERSION}")
-message(STATUS "    libraries: ${OpenCV_LIBS}")
-message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
+# cmake -D BGS_PYTHON_SUPPORT=ON -D BGS_PYTHON_VERSION=3 ..
+if(NOT DEFINED BGS_PYTHON_VERSION)
+  set(BGS_PYTHON_VERSION 3)
+endif()
+if(BGS_PYTHON_SUPPORT)
+  message(STATUS "PYTHON VERSION: ${BGS_PYTHON_VERSION}")
+endif()
+
+if(BGS_CORE_STATIC)
+  set(OpenCV_STATIC ON)
+else()
+  set(OpenCV_STATIC OFF)
+endif()
+
+find_package(OpenCV REQUIRED)
+if(OpenCV_FOUND)
+  message(STATUS "")
+  message(STATUS "OpenCV library status:")
+  message(STATUS "    version: ${OpenCV_VERSION}")
+  message(STATUS "    libraries: ${OpenCV_LIBS}")
+  message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}\n")
+endif()
 
 # if(${OpenCV_VERSION} VERSION_EQUAL 3 OR ${OpenCV_VERSION} VERSION_GREATER 3)
-# 	message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
+#   message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
 # endif()
 
 if(${OpenCV_VERSION} VERSION_LESS 2.3.1)
-	message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
+  message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
 endif()
 
-find_package(LibArchive REQUIRED)
-message(STATUS "LibArchive library status:")
-message(STATUS "    version: ${LibArchive_VERSION}")
-message(STATUS "    libraries: ${LibArchive_LIBRARIES}")
-message(STATUS "    include path: ${LibArchive_INCLUDE_DIRS}")
+if(BGS_PYTHON_SUPPORT)
+  #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)
 
+  #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()
 
-if(BGS_PYTHON_SUPPORT)
-	set(Boost_USE_STATIC_LIBS OFF)
-	set(Boost_USE_MULTITHREADED ON)
-	set(Boost_USE_STATIC_RUNTIME OFF)
-	
-	find_package(Boost REQUIRED COMPONENTS python)
-	find_package(PythonLibs REQUIRED)
+  # 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(modules/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 "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 "    version: ${PYTHON_VERSION}")
-	message(STATUS "    libraries: ${PYTHON_LIBRARIES}")
-	message(STATUS "    include path: ${PYTHON_INCLUDE_DIRS}")
+  message(STATUS "")
+  message(STATUS "Python library status:")
+  message(STATUS "    executable: ${PYTHON_EXECUTABLE}")
+  #message(STATUS "    version: ${PYTHON_VERSION_STRING}")
+  #message(STATUS "    libraries: ${PYTHON_LIBRARIES}")
+  message(STATUS "    library: ${PYTHON_LIBRARY}")
+  message(STATUS "    include path: ${PYTHON_INCLUDE_DIRS}")
+  if(NOT NUMPY_INCLUDE_DIR)
+    # message(FATAL_ERROR "You must define NUMPY_INCLUDE_DIR by 'cmake -D NUMPY_INCLUDE_DIR=/python/lib/site-packages/numpy/core/include ..'")
+    exec_program ("${PYTHON_EXECUTABLE}"
+      ARGS "-c \"import numpy; print(numpy.get_include())\""
+      OUTPUT_VARIABLE NUMPY_INCLUDE_DIR
+      RETURN_VALUE NUMPY_NOT_FOUND)
+  endif()
+  message(STATUS "NUMPY_INCLUDE_DIR: ${NUMPY_INCLUDE_DIR}\n")
 endif()
 
-#file(GLOB sources FrameProcessor.cpp PreProcessor.cpp VideoAnalysis.cpp VideoCapture.cpp)
-file(GLOB main Main.cpp FrameProcessor.cpp PreProcessor.cpp VideoAnalysis.cpp VideoCapture.cpp)
-file(GLOB demo Demo.cpp)
-file(GLOB demo2 Demo2.cpp)
+if(NOT BGS_PYTHON_ONLY)
+  file(GLOB main_src src/*.cpp src/*.c)
+  file(GLOB main_inc src/*.h src/*.hpp)
+endif()
+
+file(GLOB_RECURSE utils_src src/utils/*.cpp src/utils/*.c)
+file(GLOB_RECURSE utils_inc src/utils/*.h src/utils/*.hpp)
+
+file(GLOB_RECURSE tools_src src/tools/*.cpp src/tools/*.c)
+file(GLOB_RECURSE tools_inc src/tools/*.h src/tools/*.hpp)
 
-# list(REMOVE_ITEM sources ${demo} ${demo2})
+file(GLOB_RECURSE bgs_src src/algorithms/*.cpp src/algorithms/*.c)
+file(GLOB_RECURSE bgs_inc src/algorithms/*.h src/algorithms/*.hpp)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${OpenCV_INCLUDE_DIRS})
 
-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})
-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} ${LibArchive_INCLUDE_DIRS})
+  file(GLOB_RECURSE bgs_python_src wrapper/python/*.cpp)
+  file(GLOB_RECURSE bgs_python_inc wrapper/python/*.h)
+
+  include_directories(${CMAKE_CURRENT_SOURCE_DIR}/modules/pybind11/include)
+  #include_directories(${Boost_INCLUDE_DIRS})
+  include_directories(${PYTHON_INCLUDE_DIRS})
+  include_directories(${NUMPY_INCLUDE_DIR})
 endif()
 
 # GMG is not available in older OpenCV versions
 if(${OpenCV_VERSION} VERSION_LESS 2.4.3)
-	file(GLOB gmg package_bgs/GMG.cpp)
-	list(REMOVE_ITEM bgs_src ${gmg})
+  file(GLOB gmg src/algorithms/GMG.cpp)
+  list(REMOVE_ITEM bgs_src ${gmg})
 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_LIBRARIES})
-	target_compile_definitions(libbgs PRIVATE BGS_PYTHON_SUPPORT=1)
+if(BGS_CORE_STATIC)
+  message(STATUS "Bulding bgslibrary_core STATIC")
+  add_library(bgslibrary_core STATIC ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
+  #set_property(TARGET bgslibrary_core PROPERTY POSITION_INDEPENDENT_CODE ON)
 else()
-	#add_library(libbgs STATIC ${sources} ${bgs_src} ${analysis_src})
-	add_library(libbgs STATIC ${bgs_src} ${analysis_src})
-	target_link_libraries(libbgs ${OpenCV_LIBS})
+  message(STATUS "Bulding bgslibrary_core SHARED")
+  add_library(bgslibrary_core SHARED ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
+  target_link_libraries(bgslibrary_core ${OpenCV_LIBS})
+  # generates the export header bgslibrary_core_EXPORTS.h automatically
+  include(GenerateExportHeader)
+  GENERATE_EXPORT_HEADER(bgslibrary_core
+      BASE_NAME bgslibrary_core
+      EXPORT_MACRO_NAME bgslibrary_core_EXPORTS
+      EXPORT_FILE_NAME bgslibrary_core_EXPORTS.h
+      STATIC_DEFINE BGSLIBRARY_CORE_EXPORTS_BUILT_AS_STATIC)
+  #set_property(TARGET bgslibrary_core PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc})
 endif()
-set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_include})
-if(WIN32)
-	# set_property(TARGET libbgs PROPERTY SUFFIX ".lib")
-else()
-	set_property(TARGET libbgs PROPERTY OUTPUT_NAME "bgs")
+
+if(BGS_PYTHON_SUPPORT)
+  #add_library(bgs_python SHARED ${bgs_src} ${tools_src})
+  #pybind11_add_module(bgs_python ${bgs_src} ${tools_src})
+  pybind11_add_module(bgs_python ${bgs_python_src} ${bgs_python_inc})
+
+  target_link_libraries(bgs_python PRIVATE bgslibrary_core ${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)
+
+  # Set the output library name to bgslibrary because that's what setup.py and distutils expects.
+  set_property(TARGET bgs_python PROPERTY OUTPUT_NAME "pybgs")
+  #set_property(TARGET bgs_python PROPERTY POSITION_INDEPENDENT_CODE ON)
 endif()
 
-add_executable(bgslibrary ${main})
-target_link_libraries(bgslibrary ${OpenCV_LIBS} libbgs)
-# set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs)
+#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()
 
-add_executable(bgs_demo ${demo})
-target_link_libraries(bgs_demo ${OpenCV_LIBS} ${LibArchive_LIBRARIES} libbgs)
+if(NOT BGS_PYTHON_ONLY)
+  add_executable(bgslibrary ${main_src} ${main_inc})
+  target_link_libraries(bgslibrary ${OpenCV_LIBS} bgslibrary_core)
+  # set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs)
+endif()
 
-add_executable(bgs_demo2 ${demo2})
-target_link_libraries(bgs_demo2 ${OpenCV_LIBS} ${LibArchive_LIBRARIES} libbgs)
+if(UNIX AND BGS_PYTHON_SUPPORT)
+  execute_process(
+    COMMAND "${PYTHON_EXECUTABLE}" -c "if True:
+      from distutils import sysconfig as sc
+      print(sc.get_python_lib(prefix='', plat_specific=True))"
+    OUTPUT_VARIABLE PYTHON_SITE
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+  )
 
-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"
-)
+  message(STATUS "")
+  message(STATUS "The bgslibrary python package will be installed at: ${PYTHON_SITE}\n")
+
+  install(TARGETS bgs_python DESTINATION ${PYTHON_SITE})
+  #install(FILES ${mypackage_python_files} DESTINATION ${PYTHON_SITE}/mypackage)
+  #install(TARGETS bgs_python DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
+endif()
+
+if(NOT BGS_PYTHON_ONLY)
+  install(TARGETS bgslibrary_core
+    bgslibrary
+    RUNTIME DESTINATION bin COMPONENT app
+    LIBRARY DESTINATION lib COMPONENT runtime
+    ARCHIVE DESTINATION lib COMPONENT runtime
+    #PUBLIC_HEADER DESTINATION include/bgslibrary COMPONENT dev
+    FRAMEWORK DESTINATION "/Library/Frameworks"
+  )
+
+  if(UNIX)
+    # to avoid: error while loading shared libraries: libbgslibrary_core.so
+    message(STATUS "You might need to run:")
+    message(STATUS "$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib")
+    message(STATUS "$ export LD_LIBRARY_PATH")
+    message(STATUS "after 'make install' to avoid error while loading libbgslibrary_core\n")
+  endif()
+
+  if(WIN32)
+    message(STATUS "You might need to add ${CMAKE_CURRENT_BINARY_DIR} to your PATH to be able to run your applications.")
+    message(STATUS "> set PATH=%PATH%;${CMAKE_CURRENT_BINARY_DIR}\n")
+  endif()
+endif()
diff --git a/COPYING.txt b/COPYING.txt
deleted file mode 100644
index 94a9ed024d3859793618152ea559a168bbcbb5e2..0000000000000000000000000000000000000000
--- a/COPYING.txt
+++ /dev/null
@@ -1,674 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program 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.
-
-    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Config.h b/Config.h
deleted file mode 100644
index 61a992d91961a77e1d13b7f3963d9bb46b05145a..0000000000000000000000000000000000000000
--- a/Config.h
+++ /dev/null
@@ -1,25 +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
-
-namespace bgslibrary
-{
-  const int KEY_REPEAT = 'r';
-  const int KEY_SPACE = 32;
-  const int KEY_ESC = 27;
-  const int KEY_ESC2 = 'q';
-}
diff --git a/Demo.cpp b/Demo.cpp
deleted file mode 100644
index 644e9194375b80887c1507d2fd7c6cc07b60ad85..0000000000000000000000000000000000000000
--- a/Demo.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
-./bgs_demo -i test45/ -a 100 -o test45/results
-*/
-
-//cpp c
-#include <iostream>
-#include <algorithm>
-#include <cstdlib>
-#include <stdio.h>      /* printf, scanf, puts, NULL */
-#include <stdlib.h>     /* srand, rand */
-#include <time.h>       /* time */
-#include <ctime>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <archive.h>
-#include <archive_entry.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-//cpp 11X
-#include <regex>
-
-
-#define PROCESS_CENTER_VERSION_MAJOR 2
-#define PROCESS_CENTER_VERSION_MINOR 0
-#define PROCESS_CENTER_VERSION_MINOR_FIXES 1
-
-//opencv
-#include <opencv2/opencv.hpp>
-//bgslibrary
-#include "package_bgs/bgslibrary.h"
-//my class
-#include "package_bgs/Tapter.h"
-#include "package_bgs/ttoolbox.h"
-
-using namespace cv;
-using namespace std;
-
-int g_badSignalFlagAbort = 0;
-
-void my_handler(int signum);
-
-char* getCmdOption(char ** begin, char ** end, const std::string & option);
-
-bool cmdOptionExists(char** begin, char** end, const std::string& option);
-
-std::vector<char> copyDataInBuffer(struct archive *aw);
-
-//! we convert our actual jpg file number to framenumber
-int toFrameNumber(std::string filename);
-
-int main(int argc, char * argv[])
-{
-    signal(SIGUSR1, my_handler);
-
-    std::cout << "using processcenter  " <<PROCESS_CENTER_VERSION_MAJOR <<"."<< PROCESS_CENTER_VERSION_MINOR<<"."<<PROCESS_CENTER_VERSION_MINOR_FIXES<< endl;
-    std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
-    //!** parse programm input****************/
-    if(cmdOptionExists(argv, argv+argc, "-h"))
-    {
-        cout <<" error: please use command as\n./bgs_demo -i inputTarFile -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath -p camparameterFile.xml"<<endl;
-        return  EXIT_FAILURE;
-    }
-    if(!cmdOptionExists(argv, argv+argc, "-i")||!cmdOptionExists(argv, argv+argc, "-a")||!cmdOptionExists(argv, argv+argc, "-o") ||!cmdOptionExists(argv, argv+argc, "-p"))
-    {
-        cout <<" error: please use command as\n./bgs_demo -i inputTarFile -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath -p camparameterFile.xml"<<endl;
-        return  EXIT_FAILURE;
-    }
-
-    char *testFile = getCmdOption(argv, argv + argc, "-i");
-    std::string inputFile(".");
-    if (testFile)
-    {
-        //test dir exists
-        inputFile = string(testFile);
-    }
-    int amountFiles = -1;
-    char *testFileAmount = getCmdOption(argv, argv + argc, "-a");
-    if (testFileAmount)
-    {
-        string s(testFileAmount);
-        stringstream foo(s);
-        foo >> amountFiles;
-    }
-
-
-    char *centerFile = getCmdOption(argv, argv + argc, "-c");
-    std::string centerFileString(".");
-    if (centerFile)
-    {
-        //test dir exists
-        centerFileString = string(centerFile);
-    }
-
-    char *testOutputDir = getCmdOption(argv, argv + argc, "-o");
-    std::string outputDir(".");
-    if (testOutputDir)
-    {
-        //test dir exists
-        outputDir = string(testOutputDir);
-    }
-
-    char *camerFile = getCmdOption(argv, argv + argc, "-p");
-    std::string cameraParameterFile(".");
-    if (camerFile)
-    {
-        //test dir exists
-        cameraParameterFile = string(camerFile);
-    }
-
-
-    cout <<"args: -i "<<inputFile<<" -a "<<amountFiles << " -c" <<  centerFileString<<" -o " << outputDir <<" -p " << cameraParameterFile ;
-    //!**** end parse input***********/
-
-    //libarchive things
-
-    struct archive *archive;
-    struct archive *ext;
-    struct archive_entry *entry;
-    int r;
-    int flags = ARCHIVE_EXTRACT_TIME; // see https://linux.die.net/man/3/archive_write_disk for more flags
-    const char *filename = testFile;
-
-    archive = archive_read_new();
-    ext = archive_write_disk_new();
-    archive_write_disk_set_options(ext, flags);
-
-    archive_read_support_format_tar(archive);
-
-    //we get the filename
-    if (filename != NULL && strcmp(filename, "-") == 0)
-        filename = NULL;
-
-    //and open the handler
-    if ((r = archive_read_open_filename(archive, filename, 10240)))
-    {
-        cerr<<"archive_read_open_filename: error: "<< archive_error_string(archive) <<" will abort"<<  endl;
-        exit(1);
-    }
-
-    /* Background Subtraction Methods */
-    IBGS *bgs;
-
-    //bgs = new FrameDifference;
-    //bgs = new StaticFrameDifference;
-    //bgs = new WeightedMovingMean;
-    //bgs = new WeightedMovingVariance;
-    //bgs = new MixtureOfGaussianV1; // only on OpenCV 2.x
-    //bgs = new MixtureOfGaussianV2;
-    //bgs = new AdaptiveBackgroundLearning;
-    //bgs = new AdaptiveSelectiveBackgroundLearning;
-    //bgs = new GMG; // only on OpenCV 2.x
-    //bgs = new KNN; // only on OpenCV 3.x
-    //bgs = new DPAdaptiveMedian;
-    //bgs = new DPGrimsonGMM;
-    //bgs = new DPZivkovicAGMM;
-    //bgs = new DPMean;
-    //bgs = new DPWrenGA;
-    //bgs = new DPPratiMediod;
-    //bgs = new DPEigenbackground;
-    //bgs = new DPTexture;
-    //bgs = new T2FGMM_UM;
-    //bgs = new T2FGMM_UV;
-    //bgs = new T2FMRF_UM;
-    //bgs = new T2FMRF_UV;
-    //bgs = new FuzzySugenoIntegral;
-    //bgs = new FuzzyChoquetIntegral;
-    //bgs = new MultiLayer;
-    bgs = new PixelBasedAdaptiveSegmenter;
-    //bgs = new LBSimpleGaussian;
-    //bgs = new LBFuzzyGaussian;
-    //bgs = new LBMixtureOfGaussians;
-    //bgs = new LBAdaptiveSOM;
-    //bgs = new LBFuzzyAdaptiveSOM;
-    //bgs = new LBP_MRF;
-    //bgs = new VuMeter;
-    //bgs = new KDE;
-    //bgs = new IndependentMultimodal;
-    //bgs = new MultiCue;
-    //bgs = new SigmaDelta;
-    //bgs = new SuBSENSE;
-    //bgs = new LOBSTER;
-    //bgs = new PAWCS;
-    //bgs = new TwoPoints;
-    //bgs = new ViBe;
-    //bgs = new Tapter;
-
-    //Tapter *bgs = new Tapter;
-
-    //see paper https://dl.acm.org/citation.cfm?id=2321600
-    //https://ieeexplore.ieee.org/document/4527178/
-    //was in benchmark on top https://www.researchgate.net/publication/259340906_A_comprehensive_review_of_background_subtraction_algorithms_evaluated_with_synthetic_and_real_videos
-    //my own adapter to use the model
-
-    //init the random number generator
-    srand (time(NULL));
-
-    clock_t beginAll = clock();
-
-    //! we read the center config file for cut out the ROI
-    //TODO merge this config with the Tapter.xml ??
-    //circle param
-    int circleCenterX = 880;
-    int circleCenterY = 750;
-    int circleRadius = 700;
-    cv::String  configFileNameCenter(centerFileString);
-    //read the config
-    cout  << "parameter of centerConfigFile.xml"<<endl;
-    FileStorage fsCen;
-    fsCen.open(configFileNameCenter, FileStorage::READ);
-    if (!fsCen.isOpened())
-    {
-        cout << "error during open " <<centerFileString <<  " will abort\n ";
-        return EXIT_FAILURE;
-    }
-
-    circleCenterX = (int) fsCen["circleCenterX"];
-    cout  <<"circleCenterX: "<< circleCenterX<<endl;
-
-    circleCenterY = (int) fsCen["circleCenterY"];
-    cout  <<"circleCenterY: "<< circleCenterY<<endl;
-
-    circleRadius = (int) fsCen["circleRadius"];
-    cout  <<"circleRadius: "<< circleRadius<<endl;
-    fsCen.release();
-
-
-    //we open the camera config file
-    cv::String  camParam (cameraParameterFile);
-    Mat intrinsicsCameraMatrix, distortionCoeff;
-    {
-        cout  << "read cam parameter of: "<< cameraParameterFile ;
-        FileStorage fs;
-        fs.open(camParam, FileStorage::READ);
-        if (!fs.isOpened())
-        {
-            cerr << "error during open " << cameraParameterFile <<  " will abort\n ";
-            return -1;
-        }
-        fs["camera_matrix"] >> intrinsicsCameraMatrix;
-        std::cout << "camera_matrix = "<< intrinsicsCameraMatrix<<endl;
-        fs["distortion_coefficients"] >> distortionCoeff;
-        std::cout << "distortion_coefficients"<< distortionCoeff<<endl;
-    }
-
-
-    cout <<"a) we process all frames "<<endl;
-
-    int everyPic= 60*5;
-    //std::string fileName;
-    int frameCounter=0;
-    int myFileTarWriterHeaderCounter = 0;
-    int frameCounterOld = -1;
-    vector<string> myFileErrorList;//list for pure io error
-    vector<string> myFileListNoContour; //list for no contours found;
-    vector<string> myFileListAfterContourSelection; //list for no contours found after selection;
-
-    //the corruption check is done beforehand
-    //vector<string> myFileListCorrupted; //list all corrupted jpg files
-
-
-    //here we loop over all picture of the tar archive, independing how many this are
-    for (;;)
-    {
-
-        //measure time consumption
-        clock_t begin = clock();  //for every single file
-        std::vector<char> vec;
-
-        //we read the next header
-        r = archive_read_next_header(archive, &entry);
-        if (r == ARCHIVE_EOF)
-            break;
-        if (r != ARCHIVE_OK)
-        {
-            cerr<<"archive_read_next_header: error: "<< archive_error_string(archive) <<" will abort"<<  endl;
-            exit(1);
-        }
-
-        //we get the filename
-        const char *fileNamePtr = archive_entry_pathname(entry);
-        std::string filename(fileNamePtr,strlen(fileNamePtr) );
-        //cout << "fileName: "<< filename <<endl;
-        //we convert it to a framenumber
-        frameCounter = toFrameNumber(filename);
-
-        if(frameCounterOld>frameCounter)
-        {
-            cerr <<" error during read in the file number, we do have non montonic order, will abort";
-            exit(1);
-        }
-
-        frameCounterOld = frameCounter;
-
-        r = archive_write_header(ext, entry);
-        if (r != ARCHIVE_OK)
-        {
-            cerr<<"archive_write_header() error: "<< archive_error_string(ext)<<endl;
-	   myFileTarWriterHeaderCounter++;
-	   continue; //we overjump all in our for loop
-        }
-        //else
-        //{
-            //we copy all data to the buffer vector
-            vec = copyDataInBuffer(archive);
-            if(vec.empty())
-                cerr << "error during load data into buffer";
-
-            r = archive_write_finish_entry(ext);
-            if (r != ARCHIVE_OK)
-            {
-                cerr<<"archive_write_finish_entry: error: "<< archive_error_string(ext) <<" will abort"<<  endl;
-                exit(1);
-            }
-        //}
-        //we read the image buffer as a jpg picture and decode it
-        Mat img_input = imdecode(Mat(vec), 1);
-
-        //        //we define the type better to prevent error
-        //        fileName = std::string(inputFile + TToolBox::getFileName(frameCounter));
-        //        cv::String fileNameCV(fileName);
-
-        cout <<"\t"<<frameCounter<<"\tof \t"<<amountFiles<<"  load file :"<< filename<<endl;
-
-        //of data is present
-        if(img_input.data )
-        {
-
-            //! step 0 we take care about the lense distortion
-            //! correct lense distortion
-            Mat imgLenseCorrection = img_input.clone();
-            //see https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#undistort
-            cv::undistort(img_input, imgLenseCorrection, intrinsicsCameraMatrix, distortionCoeff);
-
-            //! we cut out a smaller ROI,
-            //! step 1)
-            img_input = TToolBox::cropImageCircle(imgLenseCorrection,circleCenterX,circleCenterY,circleRadius);
-
-            //!  normal bgs processing
-            //! step 2)
-            cv::Mat img_mask;
-            cv::Mat img_bkgmodel;
-
-            bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
-
-            //! step 3) we make  we apply a edge detection
-            //TODO make this in a function, how many times is this listed ??
-            //TODO read from tapter config
-            //TODO all parameter from applyCannyEdgeAndCalcCountours also !!
-            double threshholdMin = 150;
-            double threshholdMax = 200;
-            int apertureSize = 3;
-            std::vector<vector<Point> > contours = TToolBox::applyCannyEdgeAndCalcCountours(img_mask,threshholdMin,threshholdMax,apertureSize);
-
-            //define what we will write down
-            std::vector<vector<Point> > contourSelection;
-            vector<Point2f> massCenters;
-            vector<Point> conHull;
-            Point2f muConvexHullMassCenter(0.0,0.0);
-
-            if(!contours.empty())
-            {
-
-                //! step 4) we make a selection out of all counters with area sizes******************************
-
-                //we calc all min rotated  rectangles for all contour from candy egde detect
-                //we exlcude very small one and very big ones
-                vector<RotatedRect> minRect( contours.size() );
-
-                //calc boxes around the contours
-                for( size_t i = 0; i < contours.size(); i++ )
-                    minRect[i] = minAreaRect( Mat(contours[i]) ); //may use boundingRect ?? to use fix non rotated rectangles ?
-
-                vector<Point2f> recCenterPoints;
-                float areaMinThreshold = 150;
-                float areaMaxThreshold = 300000; //old max threshold was to small //TODO apply moving filter ??, an more adaptive approach
-
-                //iterate all rectangles
-                for( size_t i = 0; i< minRect.size(); i++ )
-                {
-                    Point2f rect_points[4];
-                    //get all points of the retange
-                    minRect[i].points( rect_points );
-
-                    //construct contour based on rectangle points because contour != rectangle with points
-                    vector<Point> contourRect;
-                    for(int j=0;j<4;j++)
-                        contourRect.push_back(rect_points[j]);
-
-                    //calc the area of the contour
-                    double area0 = contourArea(contourRect);
-                    //over stepp all small areas
-                    if(area0<areaMinThreshold||area0>areaMaxThreshold)
-                    {
-                        //cout<<i<<":area0:"<<area0<<" dismissed "<<endl;
-                        //skipe if the area is too small
-                        continue;
-                    }
-                    else
-                    {
-                        //cout<<i<<":area0:"<<area0<<" choose "<<endl;
-
-                        //get the center of this rectangle
-                        Point2f center = minRect[i].center;
-                        recCenterPoints.push_back(center);
-
-                        //we also add the this contour to a selection
-                        contourSelection.push_back(contours[i]);
-
-                    }
-                }//end iterate all min rectangle
-
-                if(!contourSelection.empty())
-                {
-                    //! step 5) we calc the moments from the contour selection
-                    vector<Moments> mu(contourSelection.size() );
-                    for( size_t i = 0; i < contourSelection.size(); i++ )
-                    {
-                        mu[i] = moments( contourSelection[i], false );
-                    }
-
-                    //  Get the mass centers:
-                    massCenters =  vector<Point2f>( contourSelection.size() );
-                    for( size_t i = 0; i < contourSelection.size(); i++ )
-                    {
-                        massCenters[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );
-                    }
-
-                    //! step 6) calc convex hull of all points of the contour selection *********
-                    //TODO produce center of convex hull of all polygones
-                    //TODO double check if ne contour sharing a center point ? nearby ??
-
-                    //we merge all points
-                    vector<Point> allContourPoints;
-                    for (size_t cC = 0; cC < contourSelection.size(); ++cC)
-                        for(size_t cP =0; cP < contourSelection[cC].size(); cP++)
-                        {
-                            Point currentContourPixel = contourSelection[cC][cP];
-                            allContourPoints.push_back(currentContourPixel);
-                        }
-
-                    // calc the hull ******************
-                    conHull = vector<Point>(allContourPoints.size());
-                    convexHull( Mat(allContourPoints), conHull, false );
-                    //    Point roiCenter;
-                    //    float roiRadius;
-
-                    //calc the min circle around
-                    //minEnclosingCircle(conHull,roiCenter,roiRadius);
-                    //we calc the mass center of the convex hull
-
-                    ///we calc the mass center of the convex hull
-                    Moments muConvexHull;
-                    if(!conHull.empty())
-                    {
-                        muConvexHull = moments(conHull, true );
-                        muConvexHullMassCenter= Point2f( muConvexHull.m10/muConvexHull.m00 , muConvexHull.m01/muConvexHull.m00 );
-                    }
-                }
-                else //end after selection is empty
-                {
-                    cerr<<"error, no contour found after selection in file: "<< filename<<endl;
-                    myFileListAfterContourSelection.push_back(filename);
-                }
-            }//end if contours are empty, to canny edge found nothing
-            else
-            {
-                cerr<<"error, no contour found at all in file: "<< filename<<endl;
-                myFileListNoContour.push_back(filename);
-
-            }
-#ifdef  MC_SHOW_STEP_ANALYSE
-
-            if(!conHull.empty())//if we any elements, we process further
-            {
-                Mat imgConvexHull = Mat::zeros( img_input.size(), CV_8UC3 );
-                imgConvexHull =  Scalar(255,255,255); //fille the picture
-
-                Scalar colorB( 0,0,255,255 );//red
-                polylines(imgConvexHull, hullComplete, true, colorB, 1, 8);
-
-                //draw circle around
-                //circle( imgConvexHull, roiCenter, (int) roiRadius, colorB, 2, 8, 0 );
-
-                //we draw it
-                cv::String outpath2=  outputDir;
-                std::ostringstream convert2;
-                convert2 << outpath2 <<TToolBox::mNzero(frameCounter) <<"_convex_hull.jpg";
-                cv::imwrite(convert2.str().c_str(), imgConvexHull);
-            }
-            else
-                cout<<"convex hull has no points will skip file: "<<i<<endl;
-
-#endif
-
-            //cout <<" found center at : "<< massCenters.at(0).x<< ";"<<massCenters.at(0).y<<endl;
-            //! step 8: we write down all our results in yml file
-            std::string nameOutPutFileData =  outputDir + TToolBox::mNzero(frameCounter) + ".yml";
-
-            //cout <<"output file:" << nameOutPutFileData;
-
-            FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE);
-            fs << "masscenters" <<  massCenters;
-            fs << "polygonselection"<< contourSelection;
-            fs << "convexhull"<<conHull;
-            fs << "masscenterconvexhull"<<muConvexHullMassCenter;
-            fs.release();
-
-            //! we write from time to time a dbg picture
-            if(frameCounter%everyPic==0)
-            {
-                Scalar colorRed( 0,0,255,255 );//red
-                RNG rng(4344234);
-                Mat imgDebugPaint2 = Mat::zeros( img_input.size(), CV_8UC3 );
-                imgDebugPaint2 =  Scalar(255,255,255); //fill the picture white
-
-                //we write all polyies of the selection and the mass centers with a random color
-                for( size_t i = 0; i< contourSelection.size(); i++ )
-                {
-                    //random color
-                    Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
-                    //contour
-                    drawContours( imgDebugPaint2, contourSelection, i, color, 1, LINE_AA);
-                    //draw the center
-                    circle( imgDebugPaint2, massCenters[i], 4, color, -1, 8, 0 );
-                }
-
-                //we write the convex hull
-                if(!conHull.empty())
-                {
-                    //the poly
-                    polylines(imgDebugPaint2, conHull, true, colorRed, 1, 8);
-                    //the center
-                    circle( imgDebugPaint2,muConvexHullMassCenter, 4, colorRed, -1, 8, 0 );
-                }
-
-                //we make a copy
-                Mat imgOverlay2 = img_input.clone();
-                //we add a overlay of our paitings
-                addWeighted( imgDebugPaint2, 0.7, imgOverlay2, 0.3, 0.0, imgOverlay2);
-                //we write the file down
-                std::string nameOutPutFileDBGpic =  outputDir + TToolBox::mNzero(frameCounter) + std::string(".jpg");
-
-                imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2);
-
-            }//end if we write a dbg picture
-
-
-        }//end if the loaded picture has data
-        else
-        {
-            cerr<<"error loading file: "<< filename<<", will skip this file"<<endl;
-            myFileErrorList.push_back(filename);
-        }
-
-        //    }//end if not corrupted picture
-        //    else
-        //    {
-        //        cerr<<"error file: "<< fileName<<" is corrupted, will ignore it"<<endl;
-        //        myFileListCorrupted.push_back(fileName);
-
-        //    }
-
-
-        //we calc the time which we used for a picture
-        clock_t end = clock();
-        double elapsedSecs = double(end - begin) / CLOCKS_PER_SEC;
-
-
-        //we calc the time which was used for all picture
-        clock_t endAll = clock();
-        double elapsedSecTotal = double(endAll - beginAll) / CLOCKS_PER_SEC;
-        cout <<"process single pic:\t"<<elapsedSecs<<" s  - \t\t"<<(int)(elapsedSecTotal/60)<<" min -\t"<<(int)(elapsedSecTotal/60/60)<<" h"<<endl;
-
-        if(g_badSignalFlagAbort)
-            frameCounter = amountFiles; //we abort
-
-        //if(frameCounter>10)exit(0); //the test abort function
-
-    }//end for ever loop
-
-    //finishing time
-    clock_t endAll = clock();
-    double elapsed = double(endAll - beginAll) / CLOCKS_PER_SEC;
-    cout <<"process : "<<amountFiles<<" files took:\t"<<(int)(elapsed/60)<<" min -\t"<<(int)(elapsed/60/60)<<" h \n in total"<<endl;
-
-    //    //we write the random file list to a file
-    //    std::string nameOutRandomFile =  outputDir + "randlist.yml";
-    //    FileStorage fs(nameOutRandomFile.c_str(), FileStorage::WRITE);
-    //    fs << "randomlist" <<  myRandomTrainList;
-    //    fs.release();
-
-    //TODO we should merge the file
-
-    cout<< "amount of libarchive read header errors :"<< myFileTarWriterHeaderCounter;
-
-    //we write the random file list to a file
-    std::string nameOutErrorList =  outputDir + "fileErrorList.yml";
-    cout <<"amount of file errors: "<< myFileErrorList.size()<<endl;
-    FileStorage fs2(nameOutErrorList.c_str(), FileStorage::WRITE);
-    fs2 << "fileErrorIOs" <<  myFileErrorList;
-
-    //we write error list no contours found in file
-    cout <<"amount contour errors with canny edge: "<< myFileListNoContour.size()<<endl;
-    fs2 << "fileErrorNoContours" <<  myFileListNoContour;
-
-    //we write error list no contours found in file
-    cout <<"amount contour errors after selection: "<< myFileListAfterContourSelection.size()<<endl;
-    fs2 << "fileErrorNoContoursAfterSelections" <<  myFileListAfterContourSelection;
-
-
-    //    //we write error list no contours found in file
-    //    cout <<"amount of corrupted jpg files: "<< myFileListCorrupted.size()<<endl;
-    //    fs2 << "fileErrorIOcorruptFiles" <<  myFileListCorrupted;
-
-    //the bgs related things
-    delete bgs;
-
-    //opencv related things
-    fs2.release();
-    //    capture.release();
-    cvDestroyAllWindows();
-
-    //close lib archive related things
-    archive_read_close(archive);
-    archive_read_free(archive);
-
-    archive_write_close(ext);
-    archive_write_free(ext);
-
-    return 0;
-}
-
-
-
-std::vector<char> copyDataInBuffer(struct archive *aw)
-{
-    int r;
-    const void *buff;
-    std::vector<char> vec;
-    size_t size;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-    int64_t offset;
-#else
-    off_t offset;
-#endif
-    //forever till we get a specific return
-    for (;;) {
-        r = archive_read_data_block(aw, &buff, &size, &offset);
-        if (r == ARCHIVE_EOF)
-        {
-            return vec; // everything fine, were are just at the end
-        }
-
-        if (r != ARCHIVE_OK)
-        {
-            cerr << "error during read archive "<<endl;
-            return vec;
-        }
-
-        //a good discussion :  https://stackoverflow.com/questions/259297/how-do-you-copy-the-contents-of-an-array-to-a-stdvector-in-c-without-looping
-        // Method 4: vector::insert
-        {
-            //we rename our pointer to avoid a weird compiler warning
-            char *foo = (char*) buff;
-            vec.insert(vec.end(), &foo[0], &foo[size]);
-        }
-
-    }
-
-    return vec;
-}
-void my_handler(int signum)
-{
-    if (signum == SIGUSR1)
-    {
-        g_badSignalFlagAbort = 1;
-        cerr << "receive signal to abort"<<endl;
-    }
-}
-
-char* getCmdOption(char ** begin, char ** end, const std::string & option)
-{
-    char ** itr = std::find(begin, end, option);
-    if (itr != end && ++itr != end)
-    {
-        return *itr;
-    }
-    return 0;
-}
-
-bool cmdOptionExists(char** begin, char** end, const std::string& option)
-{
-    return std::find(begin, end, option) != end;
-}
-
-int toFrameNumber(std::string filename)
-{
-    int retVal = -1;
-
-    //we cut out all non needed substrings
-    filename = regex_replace(filename, regex("/"), "");
-    filename = regex_replace(filename, regex("data_sized"), "");
-    filename = regex_replace(filename, regex("jpg"), "");
-    filename = regex_replace(filename, regex("\\."), "");
-
-    retVal = std::stoi( filename );
-
-    //cout <<"filename out:" << filename << " number: "<< retVal << endl;
-
-    return retVal;
-}
diff --git a/Demo.py b/Demo.py
deleted file mode 100644
index 71bc35232e73fe4ff54b70d40d3690b274c31af7..0000000000000000000000000000000000000000
--- a/Demo.py
+++ /dev/null
@@ -1,84 +0,0 @@
-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()
-
-video_file = "dataset/video.avi"
-
-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)
-while True:
-	flag, frame = capture.read()
-	
-	if flag:
-		cv2.imshow('video', frame)
-		pos_frame = capture.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
-		#print str(pos_frame)+" frames"
-		
-		img_output = bgs.apply(frame)
-		img_bgmodel = bgs.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)
-		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):
-		break
-
-cv2.destroyAllWindows()
diff --git a/Demo2.cpp b/Demo2.cpp
deleted file mode 100644
index eef22d47c9fcc7ae707e4e0313c65b497db5fa48..0000000000000000000000000000000000000000
--- a/Demo2.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-./bgs_demo -i test45/ -a 100 -o test45/results/
-based  on original demo.cpp
-*/
-
-// c
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <archive.h>
-#include <archive_entry.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-//cpp c
-#include <iostream>
-#include <algorithm>
-#include <vector>
-#include <cstdlib>
-#include <stdio.h>      /* printf, scanf, puts, NULL */
-#include <stdlib.h>     /* srand, rand */
-#include <time.h>       /* time */
-#include <ctime>
-
-#define PROCESS_CENTER_VERSION_MAJOR 0
-#define PROCESS_CENTER_VERSION_MINOR 2
-
-//opencv
-#include <opencv2/opencv.hpp>
-//bgslibrary
-#include "package_bgs/bgslibrary.h"
-//my class
-#include "package_bgs/Tapter.h"
-#include "package_bgs/ttoolbox.h"
-
-using namespace cv;
-using namespace std;
-
-char* getCmdOption(char ** begin, char ** end, const std::string & option)
-{
-    char ** itr = std::find(begin, end, option);
-    if (itr != end && ++itr != end)
-    {
-        return *itr;
-    }
-    return 0;
-}
-
-bool cmdOptionExists(char** begin, char** end, const std::string& option)
-{
-    return std::find(begin, end, option) != end;
-}
-
-
-static std::vector<char> copyDataInBuffer(struct archive *aw);
-
-//static void	errmsg(const char *);
-//static void	fail(const char *, const char *, int);
-//static void	msg(const char *);
-//static void	warn(const char *, const char *);
-
-
-
-int main(int argc, char * argv[])
-{
-    std::cout << "using produce bk  " <<PROCESS_CENTER_VERSION_MAJOR <<"."<< PROCESS_CENTER_VERSION_MINOR << endl;
-    std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
-    //!** parse programm input****************/
-    if(cmdOptionExists(argv, argv+argc, "-h"))
-    {
-        cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
-        return  EXIT_FAILURE;
-    }
-    if(!cmdOptionExists(argv, argv+argc, "-i")||!cmdOptionExists(argv, argv+argc, "-a")||!cmdOptionExists(argv, argv+argc, "-o") )
-    {
-        cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
-        return  EXIT_FAILURE;
-    }
-
-    char *testInputDir = getCmdOption(argv, argv + argc, "-i");
-    string inputDir(".");
-    if (testInputDir)
-    {
-        //test dir exists
-        inputDir = string(testInputDir);
-    }
-    int amountFiles = -1;
-    char *testFileAmount = getCmdOption(argv, argv + argc, "-a");
-    if (testFileAmount)
-    {
-        string s(testFileAmount);
-        stringstream foo(s);
-        foo >> amountFiles;
-    }
-
-
-    char *centerFile = getCmdOption(argv, argv + argc, "-c");
-    string centerFileString(".");
-    if (centerFile)
-    {
-        //test dir exists
-        centerFileString = string(centerFile);
-    }
-
-    char *testOutputDir = getCmdOption(argv, argv + argc, "-o");
-    string outputDir(".");
-    if (testOutputDir)
-    {
-        //test dir exists
-        outputDir = string(testOutputDir);
-    }
-
-    struct archive *archive;
-    struct archive *ext;
-    struct archive_entry *entry;
-    int r;
-    int flags = ARCHIVE_EXTRACT_TIME; // see https://linux.die.net/man/3/archive_write_disk for more flags
-    const char *filename = "data_sized.tar";
-
-    archive = archive_read_new();
-    ext = archive_write_disk_new();
-    archive_write_disk_set_options(ext, flags);
-
-    archive_read_support_format_tar(archive);
-
-    //we get the filename
-    if (filename != NULL && strcmp(filename, "-") == 0)
-        filename = NULL;
-
-    //and open the handler
-    if ((r = archive_read_open_filename(archive, filename, 10240)))
-    {
-        cerr<<"archive_read_open_filename: error: "<< archive_error_string(archive) <<" will abort"<<  endl;
-        exit(1);
-        //      fail("archive_read_open_filename()",
-        //             archive_error_string(a), r);
-    }
-
-    int counter = 0;
-    for (;;) {
-        r = archive_read_next_header(archive, &entry);
-        if (r == ARCHIVE_EOF)
-            break;
-        if (r != ARCHIVE_OK)
-        {
-            cerr<<"archive_read_next_header: error: "<< archive_error_string(archive) <<" will abort"<<  endl;
-            exit(1);
-            //            fail("archive_read_next_header()",
-            //                 archive_error_string(a), 1);
-        }
-        //msg("x ");
-        ///char *buffer = malloc (sizeof(char) * 400000);
-        //Mat img =Mat::zeros(1936,1456,CV_8UC3);
-
-        //new way
-        //std::ifstream file("img.jpg");
-        std::vector<char> vec;
-
-        //        file >> std::noskipws;
-        //        std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(data));
-
-        const char *fileNamePtr = archive_entry_pathname(entry);
-        std::string filename(fileNamePtr,strlen(fileNamePtr) );
-        cout << "fileName: "<< filename <<endl;
-
-        //TODO we should test what file we have, this filenumber n = n  - 1 ??
-
-        //msg(archive_entry_pathname(entry));
-        r = archive_write_header(ext, entry);
-        if (r != ARCHIVE_OK)
-        {
-            cerr<<"archive_write_header() error: "<< archive_error_string(ext)<<endl;
-        }
-        else
-        {
-            vec = copyDataInBuffer(archive);//no // we cast the data pointer to void, because we know what we do ??
-            if(vec.empty())
-                cerr << "error during load data into buffer";
-
-            r = archive_write_finish_entry(ext);
-            if (r != ARCHIVE_OK)
-            {
-                cerr<<"archive_write_finish_entry: error: "<< archive_error_string(ext) <<" will abort"<<  endl;
-                exit(1);
-
-//                fail("archive_write_finish_entry()",
-//                     archive_error_string(ext), 1);
-            }
-        }
-        //we read the image buffer as a jpg picture and decode it
-        Mat img2 = imdecode(Mat(vec), 1);
-
-//        //here we could use our image
-//        //we show what we got
-//        namedWindow( "Display window", WINDOW_AUTOSIZE );// Create a window for display.
-//        imshow( "Display window", img2 );                   // Show our image inside it.
-//        cv::imwrite("foo.jpg", img2);
-
-//        //msg("\n");
-        if(counter > 10) exit(1);
-        counter ++;
-
-//        waitKey(0);
-
-
-    }
-    archive_read_close(archive);
-    archive_read_free(archive);
-
-    archive_write_close(ext);
-    archive_write_free(ext);
-
-    return 0;
-}
-
-static std::vector<char> copyDataInBuffer(struct archive *aw)
-{
-    int r;
-    const void *buff;
-    std::vector<char> vec;
-    size_t size;
-#if ARCHIVE_VERSION_NUMBER >= 3000000
-    int64_t offset;
-#else
-    off_t offset;
-#endif
-    //    unsigned int myOffsetCounter = 0;
-    //    int counterIteration = 0;
-
-    //    ofstream myfile;
-    //    myfile.open ("tmpPicture.jpg", ios::out | ios::binary);
-    //    if (!myfile.is_open())
-    //        return vec;
-
-    for (;;) {
-        r = archive_read_data_block(aw, &buff, &size, &offset);
-        if (r == ARCHIVE_EOF)
-        {
-            return vec; // everything fine, were are just at the end
-        }
-
-        if (r != ARCHIVE_OK)
-        {
-            cerr << "error during read archive "<<endl;
-            return vec;
-        }
-        //r = archive_write_data_block(aw, buff, size, offset);
-        //we mem copy the buffer
-        //cout <<counterIteration++<< " offset: "<< offset<< " size: "<< size<<endl;
-
-        //memcpy(  &buffer[myOffsetCounter], (char*) buff, size * sizeof( char ) );
-        //we simply copy it to the end
-        //std::copy ( buff, buff+size, vec.end() );
-        //myOffsetCounter += size;
-
-        //a good discussion :  https://stackoverflow.com/questions/259297/how-do-you-copy-the-contents-of-an-array-to-a-stdvector-in-c-without-looping
-        // Method 4: vector::insert
-        {
-            //we rename our pointer to avoid a weird compiler warning
-            char *foo = (char*) buff;
-            vec.insert(vec.end(), &foo[0], &foo[size]);
-        }
-
-
-        //myfile.write ((char*)buff,size);
-        //        if (r != ARCHIVE_OK) {
-        //            warn("archive_write_data_block()",
-        //                 archive_error_string(aw));
-        //            return (r);
-        //        }
-    }
-    //myfile.close();
-
-    return vec;
-}
-
-//static void
-//msg(const char *m)
-//{
-//    write(1, m, strlen(m));
-//}
-
-//static void
-//errmsg(const char *m)
-//{
-//    write(2, m, strlen(m));
-//}
-
-//static void
-//warn(const char *f, const char *m)
-//{
-//    errmsg(f);
-//    errmsg(" failed: ");
-//    errmsg(m);
-//    errmsg("\n");
-//}
-
-//static void
-//fail(const char *f, const char *m, int r)
-//{
-//    warn(f, m);
-//    exit(r);
-//}
diff --git a/Demo2.cpp.bk b/Demo2.cpp.bk
deleted file mode 100644
index e518a8c9b576f5d7d45e37b6c7b6437ea6f344be..0000000000000000000000000000000000000000
--- a/Demo2.cpp.bk
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
-./bgs_demo -i test45/ -a 100 -o test45/results/
-based  on original demo.cpp
-*/
-
-//cpp c
-#include <iostream>
-#include <algorithm>
-#include <cstdlib>
-#include <stdio.h>      /* printf, scanf, puts, NULL */
-#include <stdlib.h>     /* srand, rand */
-#include <time.h>       /* time */
-#include <ctime>
-
-
-#define PROCESS_CENTER_VERSION_MAJOR 0
-#define PROCESS_CENTER_VERSION_MINOR 2
-
-//opencv
-#include <opencv2/opencv.hpp>
-//bgslibrary
-#include "package_bgs/bgslibrary.h"
-//my class
-#include "package_bgs/Tapter.h"
-#include "package_bgs/ttoolbox.h"
-
-using namespace cv;
-using namespace std;
-
-char* getCmdOption(char ** begin, char ** end, const std::string & option)
-{
-    char ** itr = std::find(begin, end, option);
-    if (itr != end && ++itr != end)
-    {
-        return *itr;
-    }
-    return 0;
-}
-
-bool cmdOptionExists(char** begin, char** end, const std::string& option)
-{
-    return std::find(begin, end, option) != end;
-}
-
-
-int main(int argc, char * argv[])
-{
-    std::cout << "using produce bk  " <<PROCESS_CENTER_VERSION_MAJOR <<"."<< PROCESS_CENTER_VERSION_MINOR << endl;
-    std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
-    //!** parse programm input****************/
-    if(cmdOptionExists(argv, argv+argc, "-h"))
-    {
-        cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
-        return  EXIT_FAILURE;
-    }
-    if(!cmdOptionExists(argv, argv+argc, "-i")||!cmdOptionExists(argv, argv+argc, "-a")||!cmdOptionExists(argv, argv+argc, "-o") )
-    {
-        cout <<" error: please use command as\n./bgs_demo -i pathToInputDir -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath"<<endl;
-        return  EXIT_FAILURE;
-    }
-
-    char *testInputDir = getCmdOption(argv, argv + argc, "-i");
-    string inputDir(".");
-    if (testInputDir)
-    {
-        //test dir exists
-        inputDir = string(testInputDir);
-    }
-    int amountFiles = -1;
-    char *testFileAmount = getCmdOption(argv, argv + argc, "-a");
-    if (testFileAmount)
-    {
-        string s(testFileAmount);
-        stringstream foo(s);
-        foo >> amountFiles;
-    }
-
-
-    char *centerFile = getCmdOption(argv, argv + argc, "-c");
-    string centerFileString(".");
-    if (centerFile)
-    {
-        //test dir exists
-        centerFileString = string(centerFile);
-    }
-
-    char *testOutputDir = getCmdOption(argv, argv + argc, "-o");
-    string outputDir(".");
-    if (testOutputDir)
-    {
-        //test dir exists
-        outputDir = string(testOutputDir);
-    }
-
-    cout <<"args: -i "<<inputDir<<" -a "<<amountFiles << " -c" <<  centerFileString<<" -o " << outputDir;
-    //!**** end parse input***********/
-
-    //./program -i pathToInputDir -a amountOfJpgFiles -o outPutPath
-
-    //pathToInputDir
-    //----should have
-    //      centerFile.xml
-    //      -data/
-    //          #which include all jpg and tt files
-    //      first file mus be: 0000000000.jpg
-    //      -bk.jpg
-    //          #is the neutral bk file for training the bgs method
-    //
-
-
-    //    VideoCapture capture;
-
-    //    if (argc > 1)
-    //    {
-    //        std::cout << "Openning: " << argv[1] << std::endl;
-    //        capture.open(argv[1]);
-    //    }
-    //    else
-    //        capture.open(0);
-
-    //    if (!capture.isOpened())
-    //    {
-    //        std::cerr << "Cannot initialize video!" << std::endl;
-    //        return -1;
-    //    }
-
-    /* Background Subtraction Methods */
-    //IBGS *bgs;
-
-    //bgs = new FrameDifference;
-    //bgs = new StaticFrameDifference;
-    //bgs = new WeightedMovingMean;
-    //bgs = new WeightedMovingVariance;
-    //bgs = new MixtureOfGaussianV1; // only on OpenCV 2.x
-    //bgs = new MixtureOfGaussianV2;
-    //bgs = new AdaptiveBackgroundLearning;
-    //bgs = new AdaptiveSelectiveBackgroundLearning;
-    //bgs = new GMG; // only on OpenCV 2.x
-    //bgs = new KNN; // only on OpenCV 3.x
-    //bgs = new DPAdaptiveMedian;
-    //bgs = new DPGrimsonGMM;
-    //bgs = new DPZivkovicAGMM;
-    //bgs = new DPMean;
-    //bgs = new DPWrenGA;
-    //bgs = new DPPratiMediod;
-    //bgs = new DPEigenbackground;
-    //bgs = new DPTexture;
-    //bgs = new T2FGMM_UM;
-    //bgs = new T2FGMM_UV;
-    //bgs = new T2FMRF_UM;
-    //bgs = new T2FMRF_UV;
-    //bgs = new FuzzySugenoIntegral;
-    //bgs = new FuzzyChoquetIntegral;
-    //bgs = new MultiLayer;
-    //bgs = new PixelBasedAdaptiveSegmenter;
-    //bgs = new LBSimpleGaussian;
-    //bgs = new LBFuzzyGaussian;
-    //bgs = new LBMixtureOfGaussians;
-    //bgs = new LBAdaptiveSOM;
-    //bgs = new LBFuzzyAdaptiveSOM;
-    //bgs = new LBP_MRF;
-    //bgs = new VuMeter;
-    //bgs = new KDE;
-    //bgs = new IndependentMultimodal;
-    //bgs = new MultiCue;
-    //bgs = new SigmaDelta;
-    //bgs = new SuBSENSE;
-    //bgs = new LOBSTER;
-    //bgs = new PAWCS;
-    //bgs = new TwoPoints;
-    //bgs = new ViBe;
-    //bgs = new Tapter;
-
-    Tapter *bgs = new Tapter;
-
-    //    bgs->setPathOut(outputDir);
-    //    bgs->setInitialFrameCounter(0);
-    //    bgs->setFlagWrite(0);
-    //    bgs->setFlagWriteDBGpic(0);
-
-
-    //see paper https://dl.acm.org/citation.cfm?id=2321600
-    //https://ieeexplore.ieee.org/document/4527178/
-    //was in benchmark on top https://www.researchgate.net/publication/259340906_A_comprehensive_review_of_background_subtraction_algorithms_evaluated_with_synthetic_and_real_videos
-    //my own adapter to use the model
-
-    int i= 0;
-    cv::Mat img_input;
-
-    //init the random number generator
-    srand (time(NULL));
-
-    clock_t beginAll = clock();
-
-    //! we read the center config file for cut out the ROI
-    //TODO merge this config with the Tapter.xml ??
-    //circle param
-    int circleCenterX = 880;
-    int circleCenterY = 750;
-    int circleRadius = 700;
-    cv::String  configFileNameCenter(centerFileString);
-    //read the config
-    cout  << "parameter of centerConfigFile.xml"<<endl;
-    FileStorage fsCen;
-    fsCen.open(configFileNameCenter, FileStorage::READ);
-    if (!fsCen.isOpened())
-    {
-        cout << "error during open " <<centerFileString <<  " will abort\n ";
-        return EXIT_FAILURE;
-    }
-
-    circleCenterX = (int) fsCen["circleCenterX"];
-    cout  <<"circleCenterX: "<< circleCenterX<<endl;
-
-    circleCenterY = (int) fsCen["circleCenterY"];
-    cout  <<"circleCenterY: "<< circleCenterY<<endl;
-
-    circleRadius = (int) fsCen["circleRadius"];
-    cout  <<"circleRadius: "<< circleRadius<<endl;
-    fsCen.release();
-
-    //    //first the static pic**********
-    //    //std::string fileName = getFileName(begin);
-    //    std::string staticFile = inputDir+"/bk.jpg";
-    //    cout <<"a) load first static background pic :"<< staticFile<<endl;
-    //    img_input = imread(staticFile.c_str(), CV_LOAD_IMAGE_COLOR);
-    //    if(img_input.data )
-    //    {
-    //        //we cut out a smaller ROI
-    //        img_input = TToolBox::cropImageCircle(img_input,circleCenterX,circleCenterY,circleRadius);
-
-    //        cv::Mat img_mask;
-    //        cv::Mat img_bkgmodel;
-    //        bgs->process(img_input, img_mask, img_bkgmodel);
-    //    }
-    //    else
-    //    {
-    //        cout<<"error loading file: "<< staticFile<<", will abort"<<endl;
-    //        return  EXIT_FAILURE;
-    //    }
-
-    std::string fileName;
-
-    //! we train with first x on random draws
-    //int amountTrainingSteps = 2;
-    //    //we open the config file and readin
-    //    cv::String  configFileName("./config/Tapter.xml");
-    //    {//read the config
-    //        FileStorage fs;
-    //        fs.open(configFileName, FileStorage::READ);
-    //        if (!fs.isOpened())
-    //        {
-    //            cout << "error during open " << configFileName <<  " will abort " <<endl;
-    //            return EXIT_FAILURE;
-    //        }
-    //        //param
-    //        amountTrainingSteps = (int) fs["trainingSteps"];
-    //        //cout <<"amountTrainingSteps: "<< amountTrainingSteps<< endl;
-    //        fs.release();
-    //    }
-
-    cout <<"a) we choose two random file "<< fileName<<endl;
-    //int j=255;
-
-    vector<Mat> picsMask;
-    vector<Mat> picsOrigin;
-    int maxTrain = 10;
-    vector<string> myRandomTrainList; //we save all draws in a list which will save to the results
-    for(i=0;i<maxTrain;i++)
-    {
-
-        //random index
-        int index  = rand() % amountFiles; //TODO: double check no double draw ??
-        fileName = inputDir +  TToolBox::getFileName(index);
-        myRandomTrainList.push_back(fileName);
-
-        cout <<"\t"<<i <<"\t of \t"<<maxTrain<<" rnd file :"<< fileName<<endl;
-        img_input = imread(fileName.c_str(), CV_LOAD_IMAGE_COLOR);
-
-
-        if(img_input.data )
-        {
-
-            //we cut out a smaller ROI
-            img_input = TToolBox::cropImageCircle(img_input,circleCenterX,circleCenterY,circleRadius);
-
-            //cv::imshow("input", img_input);
-            cv::Mat img_mask;
-            cv::Mat img_bkgmodel;
-
-            //            //adapter learning rate
-            //            if(j>62)
-            //                bgs->setLearningRate(j);
-
-
-            bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
-
-            if(i>=(maxTrain-2))
-            {
-                picsMask.push_back(img_mask.clone());
-                picsOrigin.push_back(img_input.clone());
-            }
-
-            //            //we save the bk gmodel
-            //            std::string bkTestFileName = inputDir + "bk_"+TToolBox::mNzero(i)+".jpg";
-            //            imwrite(bkTestFileName.c_str(),img_bkgmodel);
-        }
-        else
-        {
-            cout<<"error loading file: "<< fileName<<", will abort"<<endl;
-            return  EXIT_FAILURE;
-        }
-    }
-
-
-    cout <<"b) we calc the two polygones of the points"<< fileName<<endl;
-
-    if(picsMask.empty())
-    {
-        cout<<"error no pics loaded"<<endl;
-        return  EXIT_FAILURE;
-    }
-    else
-        cout<<"pics.size(): "<<picsMask.size()<<endl;
-
-    int frameCounter = 0;
-    //vector<vector<vector<Point>>> polyGones;
-    vector<RotatedRect> rectanglesPicA;//we will save the rectangles for each polygone which was selected
-    vector<RotatedRect> rectanglesPicB;
-
-    for(frameCounter=0;frameCounter<2;frameCounter++)
-    {
-        Mat img_mask = picsMask[frameCounter];
-
-        //! step 3) we make  we apply a edge detection
-        //TODO make this in a function, how many times is this listed ??
-        //TODO read from tapter config
-        //TODO all parameter from applyCannyEdgeAndCalcCountours also !!
-        double threshholdMin = 150;
-        double threshholdMax = 200;
-        int apertureSize = 3;
-        std::vector<vector<Point> > contours = TToolBox::applyCannyEdgeAndCalcCountours(img_mask,threshholdMin,threshholdMax,apertureSize);
-
-
-        //        //TODO: we need to  order the points to get a nice polygon, otherwise not usefull
-        //        //we also try to find the aproximate polygon*****************
-        ////        vector<Point> aproxiCurve;
-
-        ////        //  //see https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html#a167a8e0a3a3d86e84b70e33483af4466
-        ////        //  if(aproxiCurve::checkVector(10,CV_32F)==-1)
-        ////        //      cout<<"error wrong format of vector"<<endl;
-
-        ////        //calc 0.1 percent of arc length of convex hull
-        ////        double epsilon =  0.1  * cv::arcLength(hullComplete,true);
-
-        ////        //see https://docs.opencv.org/2.4.13.2/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#approxpolydp
-        ////        cv::approxPolyDP(allContourPoints,aproxiCurve,epsilon,false);
-
-        ////#ifdef  MC_SHOW_STEP_ANALYSE
-        ////        if(aproxiCurve.size()>=2)//we only draw if we have at least a line
-        ////        {
-        ////            Mat imgPolyApr = Mat::zeros( img_input.size(), CV_8UC3 );
-        ////            imgPolyApr =  Scalar(255,255,255); //fille the picture
-        ////            Scalar colorC( 0,0,255,255 );//red
-
-
-        ////            //for(imgPolyApr)
-
-        ////            polylines(imgPolyApr, aproxiCurve, true, colorC, 1, 8);
-
-        ////            cv::String outpath3=  "/homes/tb55xemi/work/bugTrainingSet/testRec/rec04379437pp/result/";
-        ////            std::ostringstream convert3;
-        ////            convert3 << outpath3 << frameCounter <<"_appr_poly.jpg";
-        ////            cv::imwrite(convert3.str().c_str(), imgPolyApr);
-        ////        }
-        ////        else
-        ////            cout<<"approximate poly has not enough points will skip file: "<<frameCounter<<endl;
-
-        ////#endif
-
-
-        //! step 4) we make a selection out of all counters with area sizes******************************
-        vector<vector<Point> > contourSelection;
-        //we exlcude very small one and very big ones
-
-        //we calc all min rotated  rectangles for all contour from candy egde detect
-        vector<RotatedRect> minRect( contours.size() );
-
-        //calc boxes around the contours
-        for( size_t i = 0; i < contours.size(); i++ )
-            minRect[i] = minAreaRect( Mat(contours[i]) ); //may use boundingRect ?? to use fix non rotated rectangles ?
-
-        vector<Point2f> recCenterPoints;
-        float areaMinThreshold = 150;
-        float areaMaxThreshold = 15000; //TODO apply moving filter ??, an more adaptive approach
-
-        //iterate all rectangles
-        for( size_t i = 0; i< minRect.size(); i++ )
-        {
-            Point2f rect_points[4];
-            //get all points of the retange
-            minRect[i].points( rect_points );
-
-            //construct contour based on rectangle points because contour != rectangle with points
-            vector<Point> contourRect;
-            for(int j=0;j<4;j++)
-                contourRect.push_back(rect_points[j]);
-
-            //calc the area of the contour
-            double area0 = contourArea(contourRect);
-            //over stepp all small areas
-            if(area0<areaMinThreshold||area0>areaMaxThreshold)
-            {
-                cout<<i<<":area0:"<<area0<<" dismissed "<<endl;
-                //skipe if the area is too small
-                continue;
-            }
-            else
-            {
-                cout<<i<<":area0:"<<area0<<" choose "<<endl;
-                //we add the rectangles to the list
-                if(frameCounter==0)
-                    rectanglesPicA.push_back(minRect[i]);
-                if(frameCounter==1)
-                    rectanglesPicB.push_back(minRect[i]);
-
-                //get the center of this rectangle
-                Point2f center = minRect[i].center;
-                recCenterPoints.push_back(center);
-
-                //we also add the this contour to a selection
-                contourSelection.push_back(contours[i]);
-
-            }
-        }//end iterate all min rectangle
-
-        //            //! step 5) we calc the moments from the contour selection
-        //            vector<Moments> mu(contourSelection.size() );
-        //            for( size_t i = 0; i < contourSelection.size(); i++ )
-        //            {
-        //                mu[i] = moments( contourSelection[i], false );
-        //            }
-
-        //            //  Get the mass centers:
-        //            vector<Point2f> massCenters( contourSelection.size() );
-        //            for( size_t i = 0; i < contourSelection.size(); i++ )
-        //            {
-        //                massCenters[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );
-        //            }
-
-        //            //! step 6) calc convex hull of all points of the contour selection *********
-        //            //TODO produce center of convex hull of all polygones
-        //            //TODO double check if ne contour sharing a center point ? nearby ??
-
-        //            //we merge all points
-        //            vector<Point> allContourPoints;
-        //            for (size_t cC = 0; cC < contourSelection.size(); ++cC)
-        //                for(size_t cP =0; cP < contourSelection[cC].size(); cP++)
-        //                {
-        //                    Point currentContourPixel = contourSelection[cC][cP];
-        //                    allContourPoints.push_back(currentContourPixel);
-        //                }
-
-        //            // calc the hull ******************
-        //            vector<Point> conHull(allContourPoints.size());
-        //            convexHull( Mat(allContourPoints), conHull, false );
-        //            //    Point roiCenter;
-        //            //    float roiRadius;
-
-        //            //calc the min circle around
-        //            //minEnclosingCircle(conHull,roiCenter,roiRadius);
-        //            //we calc the mass center of the convex hull
-
-        //            ///we calc the mass center of the convex hull
-        //            Moments muConvexHull;
-        //            Point2f muConvexHullMassCenter(0.0,0.0);
-        //            if(!conHull.empty())
-        //            {
-        //                muConvexHull = moments(conHull, true );
-        //                muConvexHullMassCenter= Point2f( muConvexHull.m10/muConvexHull.m00 , muConvexHull.m01/muConvexHull.m00 );
-        //            }
-
-        //#ifdef  MC_SHOW_STEP_ANALYSE
-
-        //            if(!conHull.empty())//if we any elements, we process further
-        //            {
-        //                Mat imgConvexHull = Mat::zeros( img_input.size(), CV_8UC3 );
-        //                imgConvexHull =  Scalar(255,255,255); //fille the picture
-
-        //                Scalar colorB( 0,0,255,255 );//red
-        //                polylines(imgConvexHull, hullComplete, true, colorB, 1, 8);
-
-        //                //draw circle around
-        //                //circle( imgConvexHull, roiCenter, (int) roiRadius, colorB, 2, 8, 0 );
-
-        //                //we draw it
-        //                cv::String outpath2=  outputDir;
-        //                std::ostringstream convert2;
-        //                convert2 << outpath2 <<TToolBox::mNzero(frameCounter) <<"_convex_hull.jpg";
-        //                cv::imwrite(convert2.str().c_str(), imgConvexHull);
-        //            }
-        //            else
-        //                cout<<"convex hull has no points will skip file: "<<i<<endl;
-
-        //#endif
-
-        //            //! step 8: we write down all our results in yml file
-        //            std::string nameOutPutFileData =  outputDir + TToolBox::mNzero(frameCounter) + ".yml";
-
-        //            FileStorage fs(nameOutPutFileData.c_str(), FileStorage::WRITE);
-        //            fs << "masscenters" <<  massCenters;
-        //            fs << "polygonselection"<< contourSelection;
-        //            fs << "convexhull"<<conHull;
-        //            fs << "masscenterconvexhull"<<muConvexHullMassCenter;
-        //            fs.release();
-
-
-        //            //! we write from time to time a dbg picture
-        //            if(frameCounter%everyPic==0)
-        //            {
-        //                Scalar colorRed( 0,0,255,255 );//red
-        //                RNG rng(4344234);
-        //                Mat imgDebugPaint2 = Mat::zeros( img_input.size(), CV_8UC3 );
-        //                imgDebugPaint2 =  Scalar(255,255,255); //fill the picture white
-
-        //                //we write all polyies of the selection and the mass centers with a random color
-        //                for( size_t i = 0; i< contourSelection.size(); i++ )
-        //                {
-        //                    //random color
-        //                    Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
-        //                    //contour
-        //                    drawContours( imgDebugPaint2, contourSelection, i, color, 1, LINE_AA);
-        //                    //draw the center
-        //                    circle( imgDebugPaint2, massCenters[i], 4, color, -1, 8, 0 );
-        //                }
-
-        //                //we write the convex hull
-        //                if(!conHull.empty())
-        //                {
-        //                    //the poly
-        //                    polylines(imgDebugPaint2, conHull, true, colorRed, 1, 8);
-        //                    //the center
-        //                    circle( imgDebugPaint2,muConvexHullMassCenter, 4, colorRed, -1, 8, 0 );
-        //                }
-
-        //                //we make a copy
-        //                Mat imgOverlay2 = img_input.clone();
-        //                //we add a overlay of our paitings
-        //                addWeighted( imgDebugPaint2, 0.7, imgOverlay2, 0.3, 0.0, imgOverlay2);
-        //                //we write the file down
-        //                std::string nameOutPutFileDBGpic =  outputDir + TToolBox::mNzero(frameCounter) + ".jpg";
-        //                imwrite(nameOutPutFileDBGpic.c_str(),imgOverlay2);
-
-        //            }
-
-    }//end for iterate frame
-
-
-    if(rectanglesPicA.empty()||rectanglesPicB.empty())
-        cout<<"error no retangles found in pics "<<endl;
-
-    Mat picA = picsOrigin[0].clone();
-    Mat picB = picsOrigin[1].clone();
-    //now we iterate all rectangles in picA and will produce pictures
-    for(size_t i=0;i<rectanglesPicA.size();i++)
-    {
-        std::string filenName = outputDir + "bk_candidate_a_" + TToolBox::mNzero(i) + ".jpg";
-        cout << "process picA i"<<i<<" name" <<filenName << endl;
-
-        //get the points
-        RotatedRect rectA= rectanglesPicA[i];
-        Point2f rectApoints[4];
-        //get all points of the retange
-        rectA.points( rectApoints );
-        //@see https://docs.opencv.org/3.4.0/db/dd6/classcv_1_1RotatedRect.html#a69d648b086f26dbce0029facae9bfb2d
-        //The points array for storing rectangle vertices.
-        //The order is bottomLeft, topLeft, topRight, bottomRight.
-        Point2f corner = rectApoints[1];
-        //we should add some offset
-        int offset = 50; //TODO double check offset
-        Point2f cornerOffset= Point2f((float)( corner.x-offset), (float) (corner.y-offset));
-
-
-        Rect rect = rectA.boundingRect();
-        //TODO check if out of our area
-        Rect rectOffset = Rect((float) (cornerOffset.x),(float) (cornerOffset.y),(float)(rect.width + offset) ,(float) (rect.height+offset  )) ;
-        Mat imageRoi = picB(rectOffset);
-
-        //        std::string filenNameROI = outputDir + "bk_test_a_roi_" + TToolBox::mNzero(i) + ".jpg";
-        //        imwrite(filenNameROI.c_str(),imageRoi);
-
-        //imageRoi =  Scalar( 255, 0, 0); //fill blue)
-
-        //        std::cout << "rect size: " << rect.size() << std::endl;
-        //        std::cout << "tempResult cols,rows: " << picB.cols << ", " << picB.rows << endl;
-
-        cv::Rect  rectROI(cornerOffset.x,cornerOffset.y, imageRoi.cols, imageRoi.rows);
-        imageRoi.copyTo(picA(rectROI));
-
-        cout << "."<<endl;
-
-        imwrite(filenName.c_str(),picA);
-    }
-    //now we iterate all rectangles and will produce pictures
-    for(size_t i=0;i<rectanglesPicB.size();i++)
-    {
-
-        std::string filenName = outputDir + "bk_candidate_b_" + TToolBox::mNzero(i) + ".jpg";
-        cout << "process picB i"<<i<<" name" <<filenName << endl;
-
-        //get the points
-        RotatedRect rectB= rectanglesPicB[i];
-        Point2f rectBpoints[4];
-        //get all points of the retange
-        rectB.points( rectBpoints );
-        //@see https://docs.opencv.org/3.4.0/db/dd6/classcv_1_1RotatedRect.html#a69d648b086f26dbce0029facae9bfb2d
-        //The points array for storing rectangle vertices.
-        //The order is bottomLeft, topLeft, topRight, bottomRight.
-        Point2f corner = rectBpoints[1];
-        //we should add some offset
-        int offset = 50; //TODO double check offset
-        Point2f cornerOffset= Point2f((float)( corner.x-offset), (float) (corner.y-offset));
-
-        Rect rect = rectB.boundingRect();
-        //TODO check if out of our area
-        Rect rectOffset = Rect((float) (cornerOffset.x),(float)(cornerOffset.y),(float)(rect.width+offset) ,(float) (rect.height+offset)) ;
-        Mat imageRoi = picA(rectOffset);
-
-        //        std::string filenNameROI = outputDir + "bk_test_a_roi_" + TToolBox::mNzero(i) + ".jpg";
-        //        imwrite(filenNameROI.c_str(),imageRoi);
-
-        //imageRoi =  Scalar( 255, 0, 0); //fill blue)
-
-        //        std::cout << "rect size: " << rect.size() << std::endl;
-        //        std::cout << "tempResult cols,rows: " << picB.cols << ", " << picB.rows << endl;
-
-        cv::Rect  rectROI(cornerOffset.x,cornerOffset.y, imageRoi.cols, imageRoi.rows);
-        imageRoi.copyTo(picB(rectROI));
-
-        cout << "."<<endl;
-
-        imwrite(filenName.c_str(),picB);
-
-    }
-
-    //        //we calc the time which we used for a picture
-    //        clock_t end = clock();
-    //        double elapsedSecs = double(end - begin) / CLOCKS_PER_SEC;
-
-
-    //        //we calc the time which was used for all picture
-    //        clock_t endAll = clock();
-    //        double elapsedSecTotal = double(endAll - beginAll) / CLOCKS_PER_SEC;
-    //        cout <<"process single pic:\t"<<elapsedSecs<<" s  - \t\t"<<(int)(elapsedSecTotal/60)<<" min -\t"<<(int)(elapsedSecTotal/60/60)<<" h"<<endl;
-
-
-
-
-    delete bgs;
-
-    //    capture.release();
-    cvDestroyAllWindows();
-
-    return 0;
-}
diff --git a/FrameProcessor.cpp b/FrameProcessor.cpp
deleted file mode 100644
index 50881219f6d4bf5e703840f3912204b006777686..0000000000000000000000000000000000000000
--- a/FrameProcessor.cpp
+++ /dev/null
@@ -1,635 +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 "FrameProcessor.h"
-#include <iomanip>
-
-namespace bgslibrary
-{
-  FrameProcessor::FrameProcessor() : firstTime(true), frameNumber(0), duration(0), tictoc(""), frameToStop(0)
-  {
-    std::cout << "FrameProcessor()" << std::endl;
-
-    loadConfig();
-    saveConfig();
-  }
-
-  FrameProcessor::~FrameProcessor()
-  {
-    std::cout << "~FrameProcessor()" << std::endl;
-  }
-
-  void FrameProcessor::init()
-  {
-    if (enablePreProcessor)
-      preProcessor = new PreProcessor;
-
-    if (enableFrameDifference)
-      frameDifference = new FrameDifference;
-
-    if (enableStaticFrameDifference)
-      staticFrameDifference = new StaticFrameDifference;
-
-    if (enableWeightedMovingMean)
-      weightedMovingMean = new WeightedMovingMean;
-
-    if (enableWeightedMovingVariance)
-      weightedMovingVariance = new WeightedMovingVariance;
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMixtureOfGaussianV1)
-      mixtureOfGaussianV1 = new MixtureOfGaussianV1;
-#endif
-
-    if (enableMixtureOfGaussianV2)
-      mixtureOfGaussianV2 = new MixtureOfGaussianV2;
-
-    if (enableAdaptiveBackgroundLearning)
-      adaptiveBackgroundLearning = new AdaptiveBackgroundLearning;
-
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    if (enableGMG)
-      gmg = new GMG;
-#endif
-
-    if (enableDPAdaptiveMedian)
-      dpAdaptiveMedian = new DPAdaptiveMedian;
-
-    if (enableDPGrimsonGMM)
-      dpGrimsonGMM = new DPGrimsonGMM;
-
-    if (enableDPZivkovicAGMM)
-      dpZivkovicAGMM = new DPZivkovicAGMM;
-
-    if (enableDPMean)
-      dpTemporalMean = new DPMean;
-
-    if (enableDPWrenGA)
-      dpWrenGA = new DPWrenGA;
-
-    if (enableDPPratiMediod)
-      dpPratiMediod = new DPPratiMediod;
-
-    if (enableDPEigenbackground)
-      dpEigenBackground = new DPEigenbackground;
-
-    if (enableDPTexture)
-      dpTexture = new DPTexture;
-
-    if (enableT2FGMM_UM)
-      type2FuzzyGMM_UM = new T2FGMM_UM;
-
-    if (enableT2FGMM_UV)
-      type2FuzzyGMM_UV = new T2FGMM_UV;
-
-    if (enableT2FMRF_UM)
-      type2FuzzyMRF_UM = new T2FMRF_UM;
-
-    if (enableT2FMRF_UV)
-      type2FuzzyMRF_UV = new T2FMRF_UV;
-
-    if (enableFuzzySugenoIntegral)
-      fuzzySugenoIntegral = new FuzzySugenoIntegral;
-
-    if (enableFuzzyChoquetIntegral)
-      fuzzyChoquetIntegral = new FuzzyChoquetIntegral;
-
-    if (enableLBSimpleGaussian)
-      lbSimpleGaussian = new LBSimpleGaussian;
-
-    if (enableLBFuzzyGaussian)
-      lbFuzzyGaussian = new LBFuzzyGaussian;
-
-    if (enableLBMixtureOfGaussians)
-      lbMixtureOfGaussians = new LBMixtureOfGaussians;
-
-    if (enableLBAdaptiveSOM)
-      lbAdaptiveSOM = new LBAdaptiveSOM;
-
-    if (enableLBFuzzyAdaptiveSOM)
-      lbFuzzyAdaptiveSOM = new LBFuzzyAdaptiveSOM;
-
-    if (enableLbpMrf)
-      lbpMrf = new LBP_MRF;
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMultiLayer)
-      multiLayer = new MultiLayer;
-#endif
-
-    if (enablePBAS)
-      pixelBasedAdaptiveSegmenter = new PixelBasedAdaptiveSegmenter;
-
-    if (enableVuMeter)
-      vuMeter = new VuMeter;
-
-    if (enableKDE)
-      kde = new KDE;
-
-    if (enableIMBS)
-      imbs = new IndependentMultimodal;
-
-    if (enableMultiCue)
-      multiCue = new MultiCue;
-
-    if (enableSigmaDelta)
-      sigmaDelta = new SigmaDelta;
-
-    if (enableSuBSENSE)
-      subSENSE = new SuBSENSE;
-
-    if (enableLOBSTER)
-      lobster = new LOBSTER;
-
-    if (enableForegroundMaskAnalysis)
-      foregroundMaskAnalysis = new ForegroundMaskAnalysis;
-  }
-
-  void FrameProcessor::process(std::string name, IBGS *bgs, const cv::Mat &img_input, cv::Mat &img_bgs)
-  {
-    if (tictoc == name)
-      tic(name);
-
-    cv::Mat img_bkgmodel;
-    bgs->process(img_input, img_bgs, img_bkgmodel);
-
-    if (tictoc == name)
-      toc();
-  }
-
-  void FrameProcessor::process(const cv::Mat &img_input)
-  {
-    frameNumber++;
-
-    if (enablePreProcessor)
-      preProcessor->process(img_input, img_preProcessor);
-
-    if (enableFrameDifference)
-      process("FrameDifference", frameDifference, img_preProcessor, img_frameDifference);
-
-    if (enableStaticFrameDifference)
-      process("StaticFrameDifference", staticFrameDifference, img_preProcessor, img_staticFrameDifference);
-
-    if (enableWeightedMovingMean)
-      process("WeightedMovingMean", weightedMovingMean, img_preProcessor, img_weightedMovingMean);
-
-    if (enableWeightedMovingVariance)
-      process("WeightedMovingVariance", weightedMovingVariance, img_preProcessor, img_weightedMovingVariance);
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMixtureOfGaussianV1)
-      process("MixtureOfGaussianV1", mixtureOfGaussianV1, img_preProcessor, img_mixtureOfGaussianV1);
-#endif
-
-    if (enableMixtureOfGaussianV2)
-      process("MixtureOfGaussianV2", mixtureOfGaussianV2, img_preProcessor, img_mixtureOfGaussianV2);
-
-    if (enableAdaptiveBackgroundLearning)
-      process("AdaptiveBackgroundLearning", adaptiveBackgroundLearning, img_preProcessor, img_adaptiveBackgroundLearning);
-
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    if (enableGMG)
-      process("GMG", gmg, img_preProcessor, img_gmg);
-#endif
-
-    if (enableDPAdaptiveMedian)
-      process("DPAdaptiveMedian", dpAdaptiveMedian, img_preProcessor, img_dpAdaptiveMedian);
-
-    if (enableDPGrimsonGMM)
-      process("DPGrimsonGMM", dpGrimsonGMM, img_preProcessor, img_dpGrimsonGMM);
-
-    if (enableDPZivkovicAGMM)
-      process("DPZivkovicAGMM", dpZivkovicAGMM, img_preProcessor, img_dpZivkovicAGMM);
-
-    if (enableDPMean)
-      process("DPMean", dpTemporalMean, img_preProcessor, img_dpTemporalMean);
-
-    if (enableDPWrenGA)
-      process("DPWrenGA", dpWrenGA, img_preProcessor, img_dpWrenGA);
-
-    if (enableDPPratiMediod)
-      process("DPPratiMediod", dpPratiMediod, img_preProcessor, img_dpPratiMediod);
-
-    if (enableDPEigenbackground)
-      process("DPEigenbackground", dpEigenBackground, img_preProcessor, img_dpEigenBackground);
-
-    if (enableDPTexture)
-      process("DPTexture", dpTexture, img_preProcessor, img_dpTexture);
-
-    if (enableT2FGMM_UM)
-      process("T2FGMM_UM", type2FuzzyGMM_UM, img_preProcessor, img_type2FuzzyGMM_UM);
-
-    if (enableT2FGMM_UV)
-      process("T2FGMM_UV", type2FuzzyGMM_UV, img_preProcessor, img_type2FuzzyGMM_UV);
-
-    if (enableT2FMRF_UM)
-      process("T2FMRF_UM", type2FuzzyMRF_UM, img_preProcessor, img_type2FuzzyMRF_UM);
-
-    if (enableT2FMRF_UV)
-      process("T2FMRF_UV", type2FuzzyMRF_UV, img_preProcessor, img_type2FuzzyMRF_UV);
-
-    if (enableFuzzySugenoIntegral)
-      process("FuzzySugenoIntegral", fuzzySugenoIntegral, img_preProcessor, img_fuzzySugenoIntegral);
-
-    if (enableFuzzyChoquetIntegral)
-      process("FuzzyChoquetIntegral", fuzzyChoquetIntegral, img_preProcessor, img_fuzzyChoquetIntegral);
-
-    if (enableLBSimpleGaussian)
-      process("LBSimpleGaussian", lbSimpleGaussian, img_preProcessor, img_lbSimpleGaussian);
-
-    if (enableLBFuzzyGaussian)
-      process("LBFuzzyGaussian", lbFuzzyGaussian, img_preProcessor, img_lbFuzzyGaussian);
-
-    if (enableLBMixtureOfGaussians)
-      process("LBMixtureOfGaussians", lbMixtureOfGaussians, img_preProcessor, img_lbMixtureOfGaussians);
-
-    if (enableLBAdaptiveSOM)
-      process("LBAdaptiveSOM", lbAdaptiveSOM, img_preProcessor, img_lbAdaptiveSOM);
-
-    if (enableLBFuzzyAdaptiveSOM)
-      process("LBFuzzyAdaptiveSOM", lbFuzzyAdaptiveSOM, img_preProcessor, img_lbFuzzyAdaptiveSOM);
-
-    if (enableLbpMrf)
-      process("LbpMrf", lbpMrf, img_preProcessor, img_lbpMrf);
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMultiLayer)
-    {
-      multiLayer->setStatus(MultiLayer::MLBGS_LEARN);
-      //multiLayer->setStatus(MultiLayer::MLBGS_DETECT);
-      process("MultiLayer", multiLayer, img_preProcessor, img_multiLayer);
-    }
-#endif
-
-    if (enablePBAS)
-      process("PBAS", pixelBasedAdaptiveSegmenter, img_preProcessor, img_pixelBasedAdaptiveSegmenter);
-
-    if (enableVuMeter)
-      process("VuMeter", vuMeter, img_preProcessor, img_vumeter);
-
-    if (enableKDE)
-      process("KDE", kde, img_preProcessor, img_kde);
-
-    if (enableIMBS)
-      process("IMBS", imbs, img_preProcessor, img_imbs);
-
-    if (enableMultiCue)
-      process("MultiCue", multiCue, img_preProcessor, img_multiCue);
-
-    if (enableSigmaDelta)
-      process("SigmaDelta", sigmaDelta, img_preProcessor, img_sigmaDelta);
-
-    if (enableSuBSENSE)
-      process("SuBSENSE", subSENSE, img_preProcessor, img_subSENSE);
-
-    if (enableLOBSTER)
-      process("LOBSTER", lobster, img_preProcessor, img_lobster);
-
-    if (enableForegroundMaskAnalysis)
-    {
-      foregroundMaskAnalysis->stopAt = frameToStop;
-      foregroundMaskAnalysis->img_ref_path = imgref;
-
-      foregroundMaskAnalysis->process(frameNumber, "FrameDifference", img_frameDifference);
-      foregroundMaskAnalysis->process(frameNumber, "StaticFrameDifference", img_staticFrameDifference);
-      foregroundMaskAnalysis->process(frameNumber, "WeightedMovingMean", img_weightedMovingMean);
-      foregroundMaskAnalysis->process(frameNumber, "WeightedMovingVariance", img_weightedMovingVariance);
-#if CV_MAJOR_VERSION == 2
-      foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV1", img_mixtureOfGaussianV1);
-#endif
-      foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV2", img_mixtureOfGaussianV2);
-      foregroundMaskAnalysis->process(frameNumber, "AdaptiveBackgroundLearning", img_adaptiveBackgroundLearning);
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-      foregroundMaskAnalysis->process(frameNumber, "GMG", img_gmg);
-#endif
-      foregroundMaskAnalysis->process(frameNumber, "DPAdaptiveMedian", img_dpAdaptiveMedian);
-      foregroundMaskAnalysis->process(frameNumber, "DPGrimsonGMM", img_dpGrimsonGMM);
-      foregroundMaskAnalysis->process(frameNumber, "DPZivkovicAGMM", img_dpZivkovicAGMM);
-      foregroundMaskAnalysis->process(frameNumber, "DPMean", img_dpTemporalMean);
-      foregroundMaskAnalysis->process(frameNumber, "DPWrenGA", img_dpWrenGA);
-      foregroundMaskAnalysis->process(frameNumber, "DPPratiMediod", img_dpPratiMediod);
-      foregroundMaskAnalysis->process(frameNumber, "DPEigenbackground", img_dpEigenBackground);
-      foregroundMaskAnalysis->process(frameNumber, "DPTexture", img_dpTexture);
-      foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UM", img_type2FuzzyGMM_UM);
-      foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UV", img_type2FuzzyGMM_UV);
-      foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UM", img_type2FuzzyMRF_UM);
-      foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UV", img_type2FuzzyMRF_UV);
-      foregroundMaskAnalysis->process(frameNumber, "FuzzySugenoIntegral", img_fuzzySugenoIntegral);
-      foregroundMaskAnalysis->process(frameNumber, "FuzzyChoquetIntegral", img_fuzzyChoquetIntegral);
-      foregroundMaskAnalysis->process(frameNumber, "LBSimpleGaussian", img_lbSimpleGaussian);
-      foregroundMaskAnalysis->process(frameNumber, "LBFuzzyGaussian", img_lbFuzzyGaussian);
-      foregroundMaskAnalysis->process(frameNumber, "LBMixtureOfGaussians", img_lbMixtureOfGaussians);
-      foregroundMaskAnalysis->process(frameNumber, "LBAdaptiveSOM", img_lbAdaptiveSOM);
-      foregroundMaskAnalysis->process(frameNumber, "LBFuzzyAdaptiveSOM", img_lbFuzzyAdaptiveSOM);
-      foregroundMaskAnalysis->process(frameNumber, "LbpMrf", img_lbpMrf);
-#if CV_MAJOR_VERSION == 2
-      foregroundMaskAnalysis->process(frameNumber, "MultiLayer", img_multiLayer);
-#endif
-      foregroundMaskAnalysis->process(frameNumber, "PBAS", img_pixelBasedAdaptiveSegmenter);
-      foregroundMaskAnalysis->process(frameNumber, "VuMeter", img_vumeter);
-      foregroundMaskAnalysis->process(frameNumber, "KDE", img_kde);
-      foregroundMaskAnalysis->process(frameNumber, "IMBS", img_imbs);
-      foregroundMaskAnalysis->process(frameNumber, "MultiCue", img_multiCue);
-      foregroundMaskAnalysis->process(frameNumber, "SigmaDelta", img_sigmaDelta);
-      foregroundMaskAnalysis->process(frameNumber, "SuBSENSE", img_subSENSE);
-      foregroundMaskAnalysis->process(frameNumber, "LOBSTER", img_lobster);
-    }
-
-    firstTime = false;
-  }
-
-  void FrameProcessor::finish(void)
-  {
-    /*if(enableMultiLayer)
-    multiLayer->finish();
-
-    if(enableLBSimpleGaussian)
-    lbSimpleGaussian->finish();
-
-    if(enableLBFuzzyGaussian)
-    lbFuzzyGaussian->finish();
-
-    if(enableLBMixtureOfGaussians)
-    lbMixtureOfGaussians->finish();
-
-    if(enableLBAdaptiveSOM)
-    lbAdaptiveSOM->finish();
-
-    if(enableLBFuzzyAdaptiveSOM)
-    lbFuzzyAdaptiveSOM->finish();*/
-
-    if (enableForegroundMaskAnalysis)
-      delete foregroundMaskAnalysis;
-
-    if (enableLOBSTER)
-      delete lobster;
-
-    if (enableSuBSENSE)
-      delete subSENSE;
-
-    if (enableSigmaDelta)
-      delete sigmaDelta;
-
-    if (enableMultiCue)
-      delete multiCue;
-
-    if (enableIMBS)
-      delete imbs;
-
-    if (enableKDE)
-      delete kde;
-
-    if (enableVuMeter)
-      delete vuMeter;
-
-    if (enablePBAS)
-      delete pixelBasedAdaptiveSegmenter;
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMultiLayer)
-      delete multiLayer;
-#endif
-
-    if (enableLBFuzzyAdaptiveSOM)
-      delete lbFuzzyAdaptiveSOM;
-
-    if (enableLBAdaptiveSOM)
-      delete lbAdaptiveSOM;
-
-    if (enableLBMixtureOfGaussians)
-      delete lbMixtureOfGaussians;
-
-    if (enableLBFuzzyGaussian)
-      delete lbFuzzyGaussian;
-
-    if (enableLBSimpleGaussian)
-      delete lbSimpleGaussian;
-
-#if !defined(_WIN32)
-    if (enableLbpMrf)
-      delete lbpMrf;
-#endif
-
-    if (enableFuzzyChoquetIntegral)
-      delete fuzzyChoquetIntegral;
-
-    if (enableFuzzySugenoIntegral)
-      delete fuzzySugenoIntegral;
-
-    if (enableT2FMRF_UV)
-      delete type2FuzzyMRF_UV;
-
-    if (enableT2FMRF_UM)
-      delete type2FuzzyMRF_UM;
-
-    if (enableT2FGMM_UV)
-      delete type2FuzzyGMM_UV;
-
-    if (enableT2FGMM_UM)
-      delete type2FuzzyGMM_UM;
-
-    if (enableDPTexture)
-      delete dpTexture;
-
-    if (enableDPEigenbackground)
-      delete dpEigenBackground;
-
-    if (enableDPPratiMediod)
-      delete dpPratiMediod;
-
-    if (enableDPWrenGA)
-      delete dpWrenGA;
-
-    if (enableDPMean)
-      delete dpTemporalMean;
-
-    if (enableDPZivkovicAGMM)
-      delete dpZivkovicAGMM;
-
-    if (enableDPGrimsonGMM)
-      delete dpGrimsonGMM;
-
-    if (enableDPAdaptiveMedian)
-      delete dpAdaptiveMedian;
-
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    if (enableGMG)
-      delete gmg;
-#endif
-
-    if (enableAdaptiveBackgroundLearning)
-      delete adaptiveBackgroundLearning;
-
-    if (enableMixtureOfGaussianV2)
-      delete mixtureOfGaussianV2;
-
-#if CV_MAJOR_VERSION == 2
-    if (enableMixtureOfGaussianV1)
-      delete mixtureOfGaussianV1;
-#endif
-
-    if (enableWeightedMovingVariance)
-      delete weightedMovingVariance;
-
-    if (enableWeightedMovingMean)
-      delete weightedMovingMean;
-
-    if (enableStaticFrameDifference)
-      delete staticFrameDifference;
-
-    if (enableFrameDifference)
-      delete frameDifference;
-
-    if (enablePreProcessor)
-      delete preProcessor;
-  }
-
-  void FrameProcessor::tic(std::string value)
-  {
-    processname = value;
-    duration = static_cast<double>(cv::getTickCount());
-  }
-
-  void FrameProcessor::toc()
-  {
-    duration = (static_cast<double>(cv::getTickCount()) - duration) / cv::getTickFrequency();
-    std::cout << processname << "\ttime(sec):" << std::fixed << std::setprecision(6) << duration << std::endl;
-  }
-
-  void FrameProcessor::saveConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/FrameProcessor.xml", 0, CV_STORAGE_WRITE);
-
-    cvWriteString(fs, "tictoc", tictoc.c_str());
-
-    cvWriteInt(fs, "enablePreProcessor", enablePreProcessor);
-
-    cvWriteInt(fs, "enableForegroundMaskAnalysis", enableForegroundMaskAnalysis);
-
-    cvWriteInt(fs, "enableFrameDifference", enableFrameDifference);
-    cvWriteInt(fs, "enableStaticFrameDifference", enableStaticFrameDifference);
-    cvWriteInt(fs, "enableWeightedMovingMean", enableWeightedMovingMean);
-    cvWriteInt(fs, "enableWeightedMovingVariance", enableWeightedMovingVariance);
-#if CV_MAJOR_VERSION == 2
-    cvWriteInt(fs, "enableMixtureOfGaussianV1", enableMixtureOfGaussianV1);
-#endif
-    cvWriteInt(fs, "enableMixtureOfGaussianV2", enableMixtureOfGaussianV2);
-    cvWriteInt(fs, "enableAdaptiveBackgroundLearning", enableAdaptiveBackgroundLearning);
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    cvWriteInt(fs, "enableGMG", enableGMG);
-#endif
-
-    cvWriteInt(fs, "enableDPAdaptiveMedian", enableDPAdaptiveMedian);
-    cvWriteInt(fs, "enableDPGrimsonGMM", enableDPGrimsonGMM);
-    cvWriteInt(fs, "enableDPZivkovicAGMM", enableDPZivkovicAGMM);
-    cvWriteInt(fs, "enableDPMean", enableDPMean);
-    cvWriteInt(fs, "enableDPWrenGA", enableDPWrenGA);
-    cvWriteInt(fs, "enableDPPratiMediod", enableDPPratiMediod);
-    cvWriteInt(fs, "enableDPEigenbackground", enableDPEigenbackground);
-    cvWriteInt(fs, "enableDPTexture", enableDPTexture);
-
-    cvWriteInt(fs, "enableT2FGMM_UM", enableT2FGMM_UM);
-    cvWriteInt(fs, "enableT2FGMM_UV", enableT2FGMM_UV);
-    cvWriteInt(fs, "enableT2FMRF_UM", enableT2FMRF_UM);
-    cvWriteInt(fs, "enableT2FMRF_UV", enableT2FMRF_UV);
-    cvWriteInt(fs, "enableFuzzySugenoIntegral", enableFuzzySugenoIntegral);
-    cvWriteInt(fs, "enableFuzzyChoquetIntegral", enableFuzzyChoquetIntegral);
-
-    cvWriteInt(fs, "enableLBSimpleGaussian", enableLBSimpleGaussian);
-    cvWriteInt(fs, "enableLBFuzzyGaussian", enableLBFuzzyGaussian);
-    cvWriteInt(fs, "enableLBMixtureOfGaussians", enableLBMixtureOfGaussians);
-    cvWriteInt(fs, "enableLBAdaptiveSOM", enableLBAdaptiveSOM);
-    cvWriteInt(fs, "enableLBFuzzyAdaptiveSOM", enableLBFuzzyAdaptiveSOM);
-
-    cvWriteInt(fs, "enableLbpMrf", enableLbpMrf);
-
-#if CV_MAJOR_VERSION == 2
-    cvWriteInt(fs, "enableMultiLayer", enableMultiLayer);
-#endif
-    cvWriteInt(fs, "enablePBAS", enablePBAS);
-    cvWriteInt(fs, "enableVuMeter", enableVuMeter);
-    cvWriteInt(fs, "enableKDE", enableKDE);
-    cvWriteInt(fs, "enableIMBS", enableIMBS);
-    cvWriteInt(fs, "enableMultiCue", enableMultiCue);
-    cvWriteInt(fs, "enableSigmaDelta", enableSigmaDelta);
-    cvWriteInt(fs, "enableSuBSENSE", enableSuBSENSE);
-    cvWriteInt(fs, "enableLOBSTER", enableLOBSTER);
-
-    cvReleaseFileStorage(&fs);
-  }
-
-  void FrameProcessor::loadConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/FrameProcessor.xml", 0, CV_STORAGE_READ);
-
-    tictoc = cvReadStringByName(fs, 0, "tictoc", "");
-
-    enablePreProcessor = cvReadIntByName(fs, 0, "enablePreProcessor", true);
-
-    enableForegroundMaskAnalysis = cvReadIntByName(fs, 0, "enableForegroundMaskAnalysis", false);
-
-    enableFrameDifference = cvReadIntByName(fs, 0, "enableFrameDifference", false);
-    enableStaticFrameDifference = cvReadIntByName(fs, 0, "enableStaticFrameDifference", false);
-    enableWeightedMovingMean = cvReadIntByName(fs, 0, "enableWeightedMovingMean", false);
-    enableWeightedMovingVariance = cvReadIntByName(fs, 0, "enableWeightedMovingVariance", false);
-#if CV_MAJOR_VERSION == 2
-    enableMixtureOfGaussianV1 = cvReadIntByName(fs, 0, "enableMixtureOfGaussianV1", false);
-#endif
-    enableMixtureOfGaussianV2 = cvReadIntByName(fs, 0, "enableMixtureOfGaussianV2", false);
-    enableAdaptiveBackgroundLearning = cvReadIntByName(fs, 0, "enableAdaptiveBackgroundLearning", false);
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    enableGMG = cvReadIntByName(fs, 0, "enableGMG", false);
-#endif
-
-    enableDPAdaptiveMedian = cvReadIntByName(fs, 0, "enableDPAdaptiveMedian", false);
-    enableDPGrimsonGMM = cvReadIntByName(fs, 0, "enableDPGrimsonGMM", false);
-    enableDPZivkovicAGMM = cvReadIntByName(fs, 0, "enableDPZivkovicAGMM", false);
-    enableDPMean = cvReadIntByName(fs, 0, "enableDPMean", false);
-    enableDPWrenGA = cvReadIntByName(fs, 0, "enableDPWrenGA", false);
-    enableDPPratiMediod = cvReadIntByName(fs, 0, "enableDPPratiMediod", false);
-    enableDPEigenbackground = cvReadIntByName(fs, 0, "enableDPEigenbackground", false);
-    enableDPTexture = cvReadIntByName(fs, 0, "enableDPTexture", false);
-
-    enableT2FGMM_UM = cvReadIntByName(fs, 0, "enableT2FGMM_UM", false);
-    enableT2FGMM_UV = cvReadIntByName(fs, 0, "enableT2FGMM_UV", false);
-    enableT2FMRF_UM = cvReadIntByName(fs, 0, "enableT2FMRF_UM", false);
-    enableT2FMRF_UV = cvReadIntByName(fs, 0, "enableT2FMRF_UV", false);
-    enableFuzzySugenoIntegral = cvReadIntByName(fs, 0, "enableFuzzySugenoIntegral", false);
-    enableFuzzyChoquetIntegral = cvReadIntByName(fs, 0, "enableFuzzyChoquetIntegral", false);
-
-    enableLBSimpleGaussian = cvReadIntByName(fs, 0, "enableLBSimpleGaussian", false);
-    enableLBFuzzyGaussian = cvReadIntByName(fs, 0, "enableLBFuzzyGaussian", false);
-    enableLBMixtureOfGaussians = cvReadIntByName(fs, 0, "enableLBMixtureOfGaussians", false);
-    enableLBAdaptiveSOM = cvReadIntByName(fs, 0, "enableLBAdaptiveSOM", false);
-    enableLBFuzzyAdaptiveSOM = cvReadIntByName(fs, 0, "enableLBFuzzyAdaptiveSOM", false);
-
-    enableLbpMrf = cvReadIntByName(fs, 0, "enableLbpMrf", false);
-
-#if CV_MAJOR_VERSION == 2
-    enableMultiLayer = cvReadIntByName(fs, 0, "enableMultiLayer", false);
-#endif
-    enablePBAS = cvReadIntByName(fs, 0, "enablePBAS", false);
-    enableVuMeter = cvReadIntByName(fs, 0, "enableVuMeter", false);
-    enableKDE = cvReadIntByName(fs, 0, "enableKDE", false);
-    enableIMBS = cvReadIntByName(fs, 0, "enableIMBS", false);
-    enableMultiCue = cvReadIntByName(fs, 0, "enableMultiCue", false);
-    enableSigmaDelta = cvReadIntByName(fs, 0, "enableSigmaDelta", false);
-    enableSuBSENSE = cvReadIntByName(fs, 0, "enableSuBSENSE", false);
-    enableLOBSTER = cvReadIntByName(fs, 0, "enableLOBSTER", false);
-
-    cvReleaseFileStorage(&fs);
-  }
-}
diff --git a/FrameProcessor.h b/FrameProcessor.h
deleted file mode 100644
index 228fa4c0e8a8b57f0d1a345f0d35700c25a60715..0000000000000000000000000000000000000000
--- a/FrameProcessor.h
+++ /dev/null
@@ -1,218 +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
-#pragma warning(disable : 4482)
-
-#include "IFrameProcessor.h"
-#include "PreProcessor.h"
-
-#include "package_bgs/IBGS.h"
-#include "package_bgs/bgslibrary.h"
-#include "package_analysis/ForegroundMaskAnalysis.h"
-
-namespace bgslibrary
-{
-  class FrameProcessor : public IFrameProcessor
-  {
-  private:
-    bool firstTime;
-    long frameNumber;
-    std::string processname;
-    double duration;
-    std::string tictoc;
-
-    cv::Mat img_preProcessor;
-    PreProcessor* preProcessor;
-    bool enablePreProcessor;
-
-    cv::Mat img_frameDifference;
-    FrameDifference* frameDifference;
-    bool enableFrameDifference;
-
-    cv::Mat img_staticFrameDifference;
-    StaticFrameDifference* staticFrameDifference;
-    bool enableStaticFrameDifference;
-
-    cv::Mat img_weightedMovingMean;
-    WeightedMovingMean* weightedMovingMean;
-    bool enableWeightedMovingMean;
-
-    cv::Mat img_weightedMovingVariance;
-    WeightedMovingVariance* weightedMovingVariance;
-    bool enableWeightedMovingVariance;
-
-#if CV_MAJOR_VERSION == 2
-    cv::Mat img_mixtureOfGaussianV1;
-    MixtureOfGaussianV1* mixtureOfGaussianV1;
-    bool enableMixtureOfGaussianV1;
-#endif
-
-    cv::Mat img_mixtureOfGaussianV2;
-    MixtureOfGaussianV2* mixtureOfGaussianV2;
-    bool enableMixtureOfGaussianV2;
-
-    cv::Mat img_adaptiveBackgroundLearning;
-    AdaptiveBackgroundLearning* adaptiveBackgroundLearning;
-    bool enableAdaptiveBackgroundLearning;
-
-#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
-    cv::Mat img_gmg;
-    GMG* gmg;
-    bool enableGMG;
-#endif
-
-    cv::Mat img_dpAdaptiveMedian;
-    DPAdaptiveMedian* dpAdaptiveMedian;
-    bool enableDPAdaptiveMedian;
-
-    cv::Mat img_dpGrimsonGMM;
-    DPGrimsonGMM* dpGrimsonGMM;
-    bool enableDPGrimsonGMM;
-
-    cv::Mat img_dpZivkovicAGMM;
-    DPZivkovicAGMM* dpZivkovicAGMM;
-    bool enableDPZivkovicAGMM;
-
-    cv::Mat img_dpTemporalMean;
-    DPMean* dpTemporalMean;
-    bool enableDPMean;
-
-    cv::Mat img_dpWrenGA;
-    DPWrenGA* dpWrenGA;
-    bool enableDPWrenGA;
-
-    cv::Mat img_dpPratiMediod;
-    DPPratiMediod* dpPratiMediod;
-    bool enableDPPratiMediod;
-
-    cv::Mat img_dpEigenBackground;
-    DPEigenbackground* dpEigenBackground;
-    bool enableDPEigenbackground;
-
-    cv::Mat img_dpTexture;
-    DPTexture* dpTexture;
-    bool enableDPTexture;
-
-    cv::Mat img_type2FuzzyGMM_UM;
-    T2FGMM_UM* type2FuzzyGMM_UM;
-    bool enableT2FGMM_UM;
-
-    cv::Mat img_type2FuzzyGMM_UV;
-    T2FGMM_UV* type2FuzzyGMM_UV;
-    bool enableT2FGMM_UV;
-
-    cv::Mat img_type2FuzzyMRF_UM;
-    T2FMRF_UM* type2FuzzyMRF_UM;
-    bool enableT2FMRF_UM;
-
-    cv::Mat img_type2FuzzyMRF_UV;
-    T2FMRF_UV* type2FuzzyMRF_UV;
-    bool enableT2FMRF_UV;
-
-    cv::Mat img_fuzzySugenoIntegral;
-    FuzzySugenoIntegral* fuzzySugenoIntegral;
-    bool enableFuzzySugenoIntegral;
-
-    cv::Mat img_fuzzyChoquetIntegral;
-    FuzzyChoquetIntegral* fuzzyChoquetIntegral;
-    bool enableFuzzyChoquetIntegral;
-
-    cv::Mat img_lbSimpleGaussian;
-    LBSimpleGaussian* lbSimpleGaussian;
-    bool enableLBSimpleGaussian;
-
-    cv::Mat img_lbFuzzyGaussian;
-    LBFuzzyGaussian* lbFuzzyGaussian;
-    bool enableLBFuzzyGaussian;
-
-    cv::Mat img_lbMixtureOfGaussians;
-    LBMixtureOfGaussians* lbMixtureOfGaussians;
-    bool enableLBMixtureOfGaussians;
-
-    cv::Mat img_lbAdaptiveSOM;
-    LBAdaptiveSOM* lbAdaptiveSOM;
-    bool enableLBAdaptiveSOM;
-
-    cv::Mat img_lbFuzzyAdaptiveSOM;
-    LBFuzzyAdaptiveSOM* lbFuzzyAdaptiveSOM;
-    bool enableLBFuzzyAdaptiveSOM;
-
-    cv::Mat img_lbpMrf;
-    LBP_MRF* lbpMrf;
-    bool enableLbpMrf;
-
-#if CV_MAJOR_VERSION == 2
-    cv::Mat img_multiLayer;
-    MultiLayer* multiLayer;
-    bool enableMultiLayer;
-#endif
-
-    cv::Mat img_pixelBasedAdaptiveSegmenter;
-    PixelBasedAdaptiveSegmenter* pixelBasedAdaptiveSegmenter;
-    bool enablePBAS;
-
-    cv::Mat img_vumeter;
-    VuMeter* vuMeter;
-    bool enableVuMeter;
-
-    cv::Mat img_kde;
-    KDE* kde;
-    bool enableKDE;
-
-    cv::Mat img_imbs;
-    IndependentMultimodal* imbs;
-    bool enableIMBS;
-
-    cv::Mat img_multiCue;
-    MultiCue* multiCue;
-    bool enableMultiCue;
-
-    cv::Mat img_sigmaDelta;
-    SigmaDelta* sigmaDelta;
-    bool enableSigmaDelta;
-
-    cv::Mat img_subSENSE;
-    SuBSENSE* subSENSE;
-    bool enableSuBSENSE;
-
-    cv::Mat img_lobster;
-    LOBSTER* lobster;
-    bool enableLOBSTER;
-
-    ForegroundMaskAnalysis* foregroundMaskAnalysis;
-    bool enableForegroundMaskAnalysis;
-
-  public:
-    FrameProcessor();
-    ~FrameProcessor();
-
-    long frameToStop;
-    std::string imgref;
-
-    void init();
-    void process(const cv::Mat &img_input);
-    void finish(void);
-
-  private:
-    void process(std::string name, IBGS *bgs, const cv::Mat &img_input, cv::Mat &img_bgs);
-    void tic(std::string value);
-    void toc();
-
-    void saveConfig();
-    void loadConfig();
-  };
-}
diff --git a/IFrameProcessor.h b/IFrameProcessor.h
deleted file mode 100644
index 61bdf3ad401dc1816e2b1b142f368ff0e3b1e619..0000000000000000000000000000000000000000
--- a/IFrameProcessor.h
+++ /dev/null
@@ -1,29 +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
-
-#include <opencv2/opencv.hpp>
-
-namespace bgslibrary
-{
-  class IFrameProcessor
-  {
-  public:
-    virtual void process(const cv::Mat &input) = 0;
-    virtual ~IFrameProcessor(){}
-  };
-}
diff --git a/LICENSE b/LICENSE
index ef7e7efc09c9d471c391f05b9567966928085840..f0f51ad65bb82c3c568d2b48af42eff1cb643cc9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,674 +1,22 @@
-GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    {one line to give the program's name and a brief idea of what it does.}
-    Copyright (C) {year}  {name of author}
-
-    This program 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.
-
-    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    {project}  Copyright (C) {year}  {fullname}
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+The MIT License
+
+Copyright (c) 2012-2019 Andrews Cordolino Sobral, 
+https://github.com/andrewssobral/bgslibrary/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/LICENSE.txt b/LICENSE.txt
index e2ce0d8b1060343138fcd323c66fc027c4308051..f0f51ad65bb82c3c568d2b48af42eff1cb643cc9 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,12 +1,22 @@
-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/>.
\ No newline at end of file
+The MIT License
+
+Copyright (c) 2012-2019 Andrews Cordolino Sobral, 
+https://github.com/andrewssobral/bgslibrary/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000000000000000000000000000000000000..edea572f1cfbb9767e74a1568bab922d741c3bbd
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,22 @@
+include *.txt
+prune src
+recursive-include src/algorithms *.*
+recursive-include src/tools *.*
+recursive-include src/utils *.*
+prune wrapper
+recursive-include wrapper/python *.*
+recursive-include modules *.*
+recursive-include pybgs *.*
+prune build
+prune dist
+prune tools
+prune test
+prune gui
+prune examples
+prune docs
+prune dataset
+prune config
+prune cmake-modules
+prune _dist
+prune _wiki
+prune _opencv_cmake
diff --git a/Main.cpp b/Main.cpp
deleted file mode 100644
index 7a406d9a859c56c6603c76f09d48cf08e326fc97..0000000000000000000000000000000000000000
--- a/Main.cpp
+++ /dev/null
@@ -1,85 +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 "Config.h"
-#include "VideoAnalysis.h"
-#include <iostream>
-
-namespace bgslibrary
-{
-  class Main
-  {
-  private:
-    Main();
-
-  public:
-    static void start(int argc, const char **argv)
-    {
-      std::cout << "-----------------------------------------" << std::endl;
-      std::cout << "Background Subtraction Library v2.0.0     " << std::endl;
-      std::cout << "http://code.google.com/p/bgslibrary       " << std::endl;
-      std::cout << "by:                                       " << std::endl;
-      std::cout << "Andrews Sobral (andrewssobral@gmail.com)  " << std::endl;
-      std::cout << "-----------------------------------------" << std::endl;
-      std::cout << "Using OpenCV version " << CV_VERSION << std::endl;
-
-      try
-      {
-        int key = KEY_ESC;
-
-        do
-        {
-          VideoAnalysis* videoAnalysis = new VideoAnalysis;
-
-          if (videoAnalysis->setup(argc, argv))
-          {
-            videoAnalysis->start();
-
-            std::cout << "Processing finished, enter:" << std::endl;
-            std::cout << "R - Repeat" << std::endl;
-            std::cout << "Q - Quit" << std::endl;
-
-            key = cv::waitKey();
-          }
-
-          cv::destroyAllWindows();
-          delete videoAnalysis;
-
-        } while (key == KEY_REPEAT);
-      }
-      catch (const std::exception& ex)
-      {
-        std::cout << "std::exception:" << ex.what() << std::endl;
-        return;
-      }
-      catch (...)
-      {
-        std::cout << "Unknow error" << std::endl;
-        return;
-      }
-
-#ifdef WIN32
-      //system("pause");
-#endif
-    }
-  };
-}
-
-int main(int argc, const char **argv)
-{
-  bgslibrary::Main::start(argc, argv);
-  return 0;
-}
diff --git a/PreProcessor.h b/PreProcessor.h
deleted file mode 100644
index 2e6e61c75ddd3d8e21362a83e800fe7ab846db48..0000000000000000000000000000000000000000
--- a/PreProcessor.h
+++ /dev/null
@@ -1,50 +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
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-
-namespace bgslibrary
-{
-  class PreProcessor
-  {
-  private:
-    bool firstTime;
-    bool equalizeHist;
-    bool gaussianBlur;
-    cv::Mat img_gray;
-    bool enableShow;
-
-  public:
-    PreProcessor();
-    ~PreProcessor();
-
-    void setEqualizeHist(bool value);
-    void setGaussianBlur(bool value);
-    cv::Mat getGrayScale();
-
-    void process(const cv::Mat &img_input, cv::Mat &img_output);
-
-    void rotate(const cv::Mat &img_input, cv::Mat &img_output, float angle);
-    void applyCanny(const cv::Mat &img_input, cv::Mat &img_output);
-
-  private:
-    void saveConfig();
-    void loadConfig();
-  };
-}
diff --git a/README.md b/README.md
index e5ec9a9ca9bd9bb757b7086e8ccaf7a4a53824a4..e7bc89746a57dfa0166fed34513d7107d841fbf2 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,15 @@
 ## BGSLibrary
-
-thomas fork of 
-
-for the records of 2018 and preprocessed records please use:
-tag v.0.9.9 alias: 415d967eccf7b8f541cb647c99a2f26be2f3ddc7
-
-i updated the version to include the lense correction in 2019
-
-
-
 A Background Subtraction Library
 
-[![bgslibrary](http://i.giphy.com/5A94AZahSIVOw.gif)](https://youtu.be/_UbERwuQ0OU)
+[![Release](https://img.shields.io/badge/Release-3.0.0-blue.svg)](https://github.com/andrewssobral/bgslibrary/wiki/Build-status) [![License: GPL v3](https://img.shields.io/badge/License-MIT-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) [![Platform: Windows, Linux, OS X](https://img.shields.io/badge/Platform-Windows%2C%20Linux%2C%20OS%20X-blue.svg)](https://github.com/andrewssobral/bgslibrary/wiki/Build-status) [![OpenCV](https://img.shields.io/badge/OpenCV-2.4.x%2C%203.x%2C%204.x-blue.svg)](https://github.com/andrewssobral/bgslibrary/wiki/Build-status) [![Wrapper: Python, MATLAB](https://img.shields.io/badge/Wrapper-Java%2C%20Python%2C%20MATLAB-orange.svg)](https://github.com/andrewssobral/bgslibrary/wiki/Build-status) [![Algorithms](https://img.shields.io/badge/Algorithms-43-red.svg)](https://github.com/andrewssobral/bgslibrary/wiki/List-of-available-algorithms)
 
-Last Page Update: **18/03/2017**
+[![bgslibrary](http://i.giphy.com/5A94AZahSIVOw.gif)](https://youtu.be/_UbERwuQ0OU)
 
-Latest Library Version: **2.0.0** (see [Release Notes](https://github.com/andrewssobral/bgslibrary/wiki/Release-notes) for more info)
+Last page update: **06/08/2019**
 
-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 **40** 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.
+Library Version: **3.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)
 
-***Note: The [opencv3](https://github.com/andrewssobral/bgslibrary/tree/opencv3) branch will be deprecated.***
+The **BGSLibrary** was developed early 2012 by [Andrews Sobral](http://andrewssobral.wixsite.com/home) to provide an easy-to-use C++ framework (wrappers for Python, Java and MATLAB are also available) for foreground-background separation in videos based on [OpenCV](http://www.opencv.org/). The bgslibrary is compatible with OpenCV 2.4.x, 3.x and 4.x, and compiles under Windows, Linux, and Mac OS X. Currently the library contains **43** algorithms. The source code is available under the [MIT license](https://opensource.org/licenses/MIT), 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)
@@ -28,14 +18,34 @@ The **BGSLibrary** was developed by [Andrews Sobral](http://andrewssobral.wixsit
 
 * Installation instructions
 
+You can either install BGSLibrary via [pre-built binary package](https://github.com/andrewssobral/bgslibrary/releases) or build it from source via:
+
+`git clone --recursive https://github.com/andrewssobral/bgslibrary.git`
+
 * * [Windows installation](https://github.com/andrewssobral/bgslibrary/wiki/Installation-instructions---Windows)
 
 * * [Ubuntu / OS X installation](https://github.com/andrewssobral/bgslibrary/wiki/Installation-instructions-Ubuntu-or-OSX)
 
+Supported Compilers are:
+
+    GCC 4.8 and above
+    Clang 3.4 and above
+    MSVC 2015, 2017, 2019
+
+Other compilers might work, but are not officially supported.
+The bgslibrary requires some features from the ISO C++ 2014 standard.
+
 * Graphical User Interface:
 
-*  * [C++ MFC (Microsoft Foundation Class)](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) ***(Official)***
+*  * [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)
+*  * [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)
@@ -44,6 +54,11 @@ The **BGSLibrary** was developed by [Andrews Sobral](http://andrewssobral.wixsit
 * [Release notes](https://github.com/andrewssobral/bgslibrary/wiki/Release-notes)
 
 
+## Stargazers over time
+
+[![Stargazers over time](https://starchart.cc/andrewssobral/bgslibrary.svg)](https://starchart.cc/andrewssobral/bgslibrary)
+
+
 Citation
 --------
 
diff --git a/VideoAnalysis.cpp b/VideoAnalysis.cpp
deleted file mode 100644
index 34c828af763e03c669dbdb3d7c6233e814b9739c..0000000000000000000000000000000000000000
--- a/VideoAnalysis.cpp
+++ /dev/null
@@ -1,169 +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 "VideoAnalysis.h"
-
-namespace bgslibrary
-{
-	VideoAnalysis::VideoAnalysis() :
-		use_file(false), use_camera(false), cameraIndex(0),
-		use_comp(false), frameToStop(0)
-	{
-		std::cout << "VideoAnalysis()" << std::endl;
-	}
-
-	VideoAnalysis::~VideoAnalysis()
-	{
-		std::cout << "~VideoAnalysis()" << std::endl;
-	}
-
-	bool VideoAnalysis::setup(int argc, const char **argv)
-	{
-		bool flag = false;
-
-#if CV_MAJOR_VERSION == 2
-		const char* keys =
-			"{hp|help|false|Print this message}"
-			"{uf|use_file|false|Use video file}"
-			"{fn|filename||Specify video file}"
-			"{uc|use_cam|false|Use camera}"
-			"{ca|camera|0|Specify camera index}"
-			"{co|use_comp|false|Use mask comparator}"
-			"{st|stopAt|0|Frame number to stop}"
-			"{im|imgref||Specify image file}"
-			;
-#elif CV_MAJOR_VERSION == 3
-		const std::string keys =
-			"{h help ?     |     | Print this message   }"
-			"{uf use_file  |false| Use a video file     }"
-			"{fn filename  |     | Specify a video file }"
-			"{uc use_cam   |false| Use a webcamera      }"
-			"{ca camera    | 0   | Specify camera index }"
-			"{co use_comp  |false| Use mask comparator  }"
-			"{st stopAt    | 0   | Frame number to stop }"
-			"{im imgref    |     | Specify a image file }"
-			;
-#endif
-
-		cv::CommandLineParser cmd(argc, argv, keys);
-
-#if CV_MAJOR_VERSION == 2
-		if (argc <= 1 || cmd.get<bool>("help") == true)
-		{
-			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
-			std::cout << "Available options:" << std::endl;
-			cmd.printParams();
-			return false;
-		}
-#elif CV_MAJOR_VERSION == 3
-		if (argc <= 1 || cmd.has("help"))
-		{
-			std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
-			std::cout << "Available options:" << std::endl;
-			cmd.printMessage();
-			return false;
-		}
-		if (!cmd.check())
-		{
-			cmd.printErrors();
-			return false;
-		}
-#endif
-
-		use_file = cmd.get<bool>("uf"); //use_file
-		filename = cmd.get<std::string>("fn"); //filename
-		use_camera = cmd.get<bool>("uc"); //use_cam
-		cameraIndex = cmd.get<int>("ca"); //camera
-		use_comp = cmd.get<bool>("co"); //use_comp
-		frameToStop = cmd.get<int>("st"); //stopAt
-		imgref = cmd.get<std::string>("im"); //imgref
-
-		std::cout << "use_file:    " << use_file << std::endl;
-		std::cout << "filename:    " << filename << std::endl;
-		std::cout << "use_camera:  " << use_camera << std::endl;
-		std::cout << "cameraIndex: " << cameraIndex << std::endl;
-		std::cout << "use_comp:    " << use_comp << std::endl;
-		std::cout << "frameToStop: " << frameToStop << std::endl;
-		std::cout << "imgref:      " << imgref << std::endl;
-		//return false;
-
-		if (use_file)
-		{
-			if (filename.empty())
-			{
-				std::cout << "Specify filename" << std::endl;
-				return false;
-			}
-
-			flag = true;
-		}
-
-		if (use_camera)
-			flag = true;
-
-		if (flag && use_comp)
-		{
-			if (imgref.empty())
-			{
-				std::cout << "Specify image reference" << std::endl;
-				return false;
-			}
-		}
-
-		return flag;
-	}
-
-	void VideoAnalysis::start()
-	{
-		//std::cout << "Press 'ESC' to stop..." << std::endl;
-
-		do
-		{
-			videoCapture = new VideoCapture;
-			frameProcessor = new FrameProcessor;
-
-			frameProcessor->init();
-			frameProcessor->frameToStop = frameToStop;
-			frameProcessor->imgref = imgref;
-
-			videoCapture->setFrameProcessor(frameProcessor);
-
-			if (use_file)
-				videoCapture->setVideo(filename);
-
-			if (use_camera)
-				videoCapture->setCamera(cameraIndex);
-
-			videoCapture->start();
-
-			if (use_file || use_camera)
-				break;
-
-			frameProcessor->finish();
-
-			int key = cvWaitKey(500);
-			if (key == KEY_ESC)
-				break;
-
-			delete frameProcessor;
-			delete videoCapture;
-
-		} while (1);
-
-		delete frameProcessor;
-		delete videoCapture;
-	}
-}
diff --git a/VideoAnalysis.h b/VideoAnalysis.h
deleted file mode 100644
index b48d93c4f0aa2674f8cf3f1b45129bdc8e4d396c..0000000000000000000000000000000000000000
--- a/VideoAnalysis.h
+++ /dev/null
@@ -1,47 +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
-
-#include <iostream> 
-#include <sstream>
-
-#include "VideoCapture.h"
-#include "FrameProcessor.h"
-
-namespace bgslibrary
-{
-  class VideoAnalysis
-  {
-  private:
-    VideoCapture* videoCapture;
-    FrameProcessor* frameProcessor;
-    bool use_file;
-    std::string filename;
-    bool use_camera;
-    int cameraIndex;
-    bool use_comp;
-    long frameToStop;
-    std::string imgref;
-
-  public:
-    VideoAnalysis();
-    ~VideoAnalysis();
-
-    bool setup(int argc, const char **argv);
-    void start();
-  };
-}
diff --git a/VideoCapture.h b/VideoCapture.h
deleted file mode 100644
index 0e88c87023b8fedbb4f089e0bf19dfc0222c3d28..0000000000000000000000000000000000000000
--- a/VideoCapture.h
+++ /dev/null
@@ -1,66 +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
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-#include <opencv2/imgproc/imgproc_c.h>
-#include <opencv2/imgproc/types_c.h>
-
-#include "Config.h"
-#include "IFrameProcessor.h"
-
-namespace bgslibrary
-{
-  class VideoCapture
-  {
-  private:
-    IFrameProcessor* frameProcessor;
-    cv::VideoCapture capture;
-    IplImage* frame;
-    int key;
-    int64 start_time;
-    int64 delta_time;
-    double freq;
-    double fps;
-    long frameNumber;
-    long stopAt;
-    bool useCamera;
-    int cameraIndex;
-    bool useVideo;
-    std::string videoFileName;
-    int input_resize_percent;
-    bool showOutput;
-    bool enableFlip;
-
-  public:
-    VideoCapture();
-    ~VideoCapture();
-
-    void setFrameProcessor(IFrameProcessor* frameProcessorPtr);
-    void setCamera(int cameraIndex);
-    void setVideo(std::string filename);
-    void start();
-
-  private:
-    void setUpCamera();
-    void setUpVideo();
-
-    void saveConfig();
-    void loadConfig();
-  };
-}
diff --git a/gui_mfc/outputs/background/.gitignore b/build/.gitignore
similarity index 100%
rename from gui_mfc/outputs/background/.gitignore
rename to build/.gitignore
diff --git a/config/FrameProcessor.xml b/config/FrameProcessor.xml
index 3cf398cc4f421bd0c42bf3a19631c425af5add42..fe71fa44d8115acf8fe56e2cb5642942f7666a4d 100644
--- a/config/FrameProcessor.xml
+++ b/config/FrameProcessor.xml
@@ -1,16 +1,17 @@
 <?xml version="1.0"?>
 <opencv_storage>
 <tictoc>""</tictoc>
-<enablePreProcessor>1</enablePreProcessor>
+<enablePreProcessor>0</enablePreProcessor>
 <enableForegroundMaskAnalysis>0</enableForegroundMaskAnalysis>
 <enableFrameDifference>1</enableFrameDifference>
 <enableStaticFrameDifference>0</enableStaticFrameDifference>
 <enableWeightedMovingMean>0</enableWeightedMovingMean>
 <enableWeightedMovingVariance>0</enableWeightedMovingVariance>
-<enableMixtureOfGaussianV1>0</enableMixtureOfGaussianV1>
-<enableMixtureOfGaussianV2>0</enableMixtureOfGaussianV2>
 <enableAdaptiveBackgroundLearning>0</enableAdaptiveBackgroundLearning>
-<enableGMG>0</enableGMG>
+<enableAdaptiveSelectiveBackgroundLearning>0</enableAdaptiveSelectiveBackgroundLearning>
+<enableMixtureOfGaussianV2>0</enableMixtureOfGaussianV2>
+<enableMixtureOfGaussianV1>0</enableMixtureOfGaussianV1>
+<enableKNN>0</enableKNN>
 <enableDPAdaptiveMedian>0</enableDPAdaptiveMedian>
 <enableDPGrimsonGMM>0</enableDPGrimsonGMM>
 <enableDPZivkovicAGMM>0</enableDPZivkovicAGMM>
@@ -40,4 +41,9 @@
 <enableSigmaDelta>0</enableSigmaDelta>
 <enableSuBSENSE>0</enableSuBSENSE>
 <enableLOBSTER>0</enableLOBSTER>
+<enablePAWCS>0</enablePAWCS>
+<enableTwoPoints>0</enableTwoPoints>
+<enableViBe>0</enableViBe>
+<enableCodeBook>0</enableCodeBook>
+<enableGMG>0</enableGMG>
 </opencv_storage>
diff --git a/config/VideoCapture.xml b/config/VideoCapture.xml
index 60dd9aa81010d78759f5986f0aa5a2876da25f63..bddc163b2ab83c3a9965a5e1c2730bc3a9c48b4b 100644
--- a/config/VideoCapture.xml
+++ b/config/VideoCapture.xml
@@ -9,5 +9,6 @@
 <roi_y0>0</roi_y0>
 <roi_x1>0</roi_x1>
 <roi_y1>0</roi_y1>
+<showFPS>1</showFPS>
 <showOutput>1</showOutput>
 </opencv_storage>
diff --git a/dataset/video.avi b/dataset/video.avi
index a29f00658be7d05b10344859e6bee9a501a7a2b1..828ec7ba863b23f7b0775d322c6b3d297035c4d5 100644
Binary files a/dataset/video.avi and b/dataset/video.avi differ
diff --git a/dataset/video02.avi b/dataset/video02.avi
new file mode 100644
index 0000000000000000000000000000000000000000..4c9299cfd75fafb25b7b75e72c1e97357269199a
Binary files /dev/null and b/dataset/video02.avi differ
diff --git a/dataset/video03.avi b/dataset/video03.avi
new file mode 100644
index 0000000000000000000000000000000000000000..c2873f201f5227dbd58f654421fefaf94d0bfcb5
Binary files /dev/null and b/dataset/video03.avi differ
diff --git a/demo.py b/demo.py
new file mode 100644
index 0000000000000000000000000000000000000000..c96da53790b759087511603b72725a5f7c2c72d2
--- /dev/null
+++ b/demo.py
@@ -0,0 +1,49 @@
+import numpy as np
+import cv2
+import pybgs as bgs
+
+algorithm = bgs.FrameDifference()
+video_file = "dataset/video.avi"
+
+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()
diff --git a/demo2.py b/demo2.py
new file mode 100644
index 0000000000000000000000000000000000000000..321896c3ae73853ccebfe2e9a32e91c95640166e
--- /dev/null
+++ b/demo2.py
@@ -0,0 +1,164 @@
+##############################################
+# Demo file
+# python demo2.py --- will use video
+# python demo2.py image --- will use images
+#############################################
+
+import numpy as np
+import cv2
+import pybgs as bgs
+import sys
+import glob
+
+print("OpenCV Version: {}".format(cv2.__version__))
+
+def is_cv2():
+  return check_opencv_version("2.")
+
+def is_cv3():
+  return check_opencv_version("3.")
+
+def is_cv4():
+  return check_opencv_version("4.")
+
+def check_opencv_version(major):
+  return cv2.__version__.startswith(major)
+
+## bgslibrary algorithms
+algorithms=[]
+algorithms.append(bgs.FrameDifference())
+algorithms.append(bgs.StaticFrameDifference())
+algorithms.append(bgs.WeightedMovingMean())
+algorithms.append(bgs.WeightedMovingVariance())
+algorithms.append(bgs.AdaptiveBackgroundLearning())
+algorithms.append(bgs.AdaptiveSelectiveBackgroundLearning())
+algorithms.append(bgs.MixtureOfGaussianV2())
+if is_cv2():
+  algorithms.append(bgs.MixtureOfGaussianV1()) # if opencv 2.x
+  algorithms.append(bgs.GMG()) # if opencv 2.x
+if is_cv3():
+  algorithms.append(bgs.KNN()) # if opencv 3.x
+if is_cv2() or is_cv3():
+  algorithms.append(bgs.DPAdaptiveMedian())
+  algorithms.append(bgs.DPGrimsonGMM())
+  algorithms.append(bgs.DPZivkovicAGMM())
+  algorithms.append(bgs.DPMean())
+  algorithms.append(bgs.DPWrenGA())
+  algorithms.append(bgs.DPPratiMediod())
+  algorithms.append(bgs.DPEigenbackground())
+  algorithms.append(bgs.DPTexture())
+  algorithms.append(bgs.T2FGMM_UM())
+  algorithms.append(bgs.T2FGMM_UV())
+  algorithms.append(bgs.T2FMRF_UM())
+  algorithms.append(bgs.T2FMRF_UV())
+  algorithms.append(bgs.FuzzySugenoIntegral())
+  algorithms.append(bgs.FuzzyChoquetIntegral())
+  algorithms.append(bgs.LBSimpleGaussian())
+  algorithms.append(bgs.LBFuzzyGaussian())
+  algorithms.append(bgs.LBMixtureOfGaussians())
+  algorithms.append(bgs.LBAdaptiveSOM())
+  algorithms.append(bgs.LBFuzzyAdaptiveSOM())
+  algorithms.append(bgs.LBP_MRF())
+  algorithms.append(bgs.MultiLayer())
+  algorithms.append(bgs.PixelBasedAdaptiveSegmenter())
+  algorithms.append(bgs.VuMeter())
+  algorithms.append(bgs.KDE())
+  algorithms.append(bgs.IndependentMultimodal())
+  algorithms.append(bgs.MultiCue())
+algorithms.append(bgs.SigmaDelta())
+algorithms.append(bgs.SuBSENSE())
+algorithms.append(bgs.LOBSTER())
+algorithms.append(bgs.PAWCS())
+algorithms.append(bgs.TwoPoints())
+algorithms.append(bgs.ViBe())
+algorithms.append(bgs.CodeBook())
+
+
+# check if we want to use the images
+image = False
+if (len(sys.argv) == 2):
+    if(sys.argv[1] == "image"):
+        image = True
+        img_folder = "dataset/frames"
+        img_array = sorted(glob.iglob(img_folder + '/*.png'))
+
+video_file = "dataset/video.avi"
+
+
+for algorithm in algorithms:
+  print("Running ", algorithm.__class__)
+
+  if(image):
+    # loop x times as files in our folder
+    for x in range(0, len(img_array)):
+
+        # we can loop now through our array of images
+        img_path = img_array[x]
+
+        # read file into open cv and apply to algorithm to generate background model
+        img = cv2.imread(img_path)
+        img_output = algorithm.apply(img)
+        img_bgmodel = algorithm.getBackgroundModel()
+
+        # show images in python imshow window
+        cv2.imshow('image', img)
+        cv2.imshow('img_output', img_output)
+        cv2.imshow('img_bgmodel', img_bgmodel)
+
+        # we need waitKey otherwise it wont display the image
+        if 0xFF & cv2.waitKey(10) == 27:
+          break
+
+        # Comment out to save images to bg and fg folder
+        #img_bg = img_path.replace(img_folder, "output/bg")
+        #img_fg = img_path.replace(img_folder, "output/fg")
+        #cv2.imwrite(img_bg, img_bgmodel)
+        #cv2.imwrite(img_fg, img_output)
+
+        print("Frames left: " + str(len(img_array)-x))
+
+  else:
+
+      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
+
+print("Finished")
+cv2.destroyAllWindows()
diff --git a/demos/linux_ubuntu/CMakeLists.txt b/demos/linux_ubuntu/CMakeLists.txt
deleted file mode 100644
index 8cc38e8852cd8facf728c49ca358e6a641feacd2..0000000000000000000000000000000000000000
--- a/demos/linux_ubuntu/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-project(FrameDifferenceTest)
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
-
-find_package(OpenCV REQUIRED)
-
-file(GLOB source FrameDifferenceTest.cpp)
-
-file(GLOB_RECURSE bgs_src ../../package_bgs/*.cpp ../../package_bgs/*.c ../../package_analysis/*.cpp)
-file(GLOB_RECURSE bgs_inc ../../package_bgs/*.h ../../package_analysis/*.h)
-
-include_directories(${CMAKE_SOURCE_DIR})
-
-add_library(bgs SHARED ${bgs_src})
-target_link_libraries(bgs ${OpenCV_LIBS})
-set_property(TARGET bgs PROPERTY PUBLIC_HEADER ${bgs_inc})
-
-add_executable(FrameDifferenceTest ${source})
-target_link_libraries(FrameDifferenceTest ${OpenCV_LIBS} bgs)
diff --git a/demos/linux_ubuntu/FrameDifferenceTest.cpp b/demos/linux_ubuntu/FrameDifferenceTest.cpp
deleted file mode 100644
index 7ebe8b1aa19ef3495d0cf57868340577a83f9134..0000000000000000000000000000000000000000
--- a/demos/linux_ubuntu/FrameDifferenceTest.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <iostream>
-#include <cv.h>
-#include <highgui.h>
-
-#include "../../package_bgs/FrameDifference.h"
-
-using namespace bgslibrary::algorithms;
-
-int main(int argc, char **argv)
-{
-  CvCapture *capture = 0;
-  capture = cvCaptureFromCAM(0);
-
-  if(!capture){
-    std::cerr << "Cannot initialize video!" << std::endl;
-    return -1;
-  }
-
-  IBGS *bgs;
-  bgs = new FrameDifference;
-
-  IplImage *frame;
-  while(1)
-  {
-    frame = cvQueryFrame(capture);
-    if(!frame) break;
-
-    cv::Mat img_input(frame);
-    cv::imshow("Input", img_input);
-
-    cv::Mat img_mask;
-    cv::Mat img_bkgmodel;
-
-    // by default, it shows automatically the foreground mask image
-    bgs->process(img_input, img_mask, img_bkgmodel);
-
-    //if(!img_mask.empty())
-    //  cv::imshow("Foreground", img_mask);
-    //  do something
-
-    if(cvWaitKey(33) >= 0)
-		  break;
-  }
-
-  delete bgs;
-
-  cvDestroyAllWindows();
-  cvReleaseCapture(&capture);
-
-  return 0;
-}
diff --git a/demos/linux_ubuntu/README.txt b/demos/linux_ubuntu/README.txt
deleted file mode 100644
index 5558b71484046423834c91f24e75c4bd36d5bcd6..0000000000000000000000000000000000000000
--- a/demos/linux_ubuntu/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# HOW TO COMPILE ON LINUX
-#
-# Requirements:
-# cmake >= 2.8
-# opencv >= 2.3.1
-
-cmake .
-make
diff --git a/demos/macosx/CMakeLists.txt b/demos/macosx/CMakeLists.txt
deleted file mode 100644
index a9775d850e56c7d5aa6669ae652980394f95a968..0000000000000000000000000000000000000000
--- a/demos/macosx/CMakeLists.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-project(FrameDifferenceTest)
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
-
-IF(UNIX)
-  # add some standard warnings
-  ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
-  
-  # -ansi does not compile with sjn module
-  #ADD_DEFINITIONS(-ansi)
-
-  # if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
-  #ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
-endif(UNIX)
-
-find_package(OpenCV REQUIRED)
-
-file(GLOB source FrameDifferenceTest.cpp)
-
-file(GLOB_RECURSE bgs_src ../../package_bgs/*.cpp ../../package_bgs/*.c ../../package_analysis/*.cpp)
-file(GLOB_RECURSE bgs_inc ../../package_bgs/*.h ../../package_analysis/*.h)
-
-include_directories(${CMAKE_SOURCE_DIR})
-
-add_library(bgs SHARED ${bgs_src})
-target_link_libraries(bgs ${OpenCV_LIBS})
-set_property(TARGET bgs PROPERTY PUBLIC_HEADER ${bgs_inc})
-
-add_executable(FrameDifferenceTest ${source})
-target_link_libraries(FrameDifferenceTest ${OpenCV_LIBS} bgs)
diff --git a/demos/macosx/FrameDifferenceTest.cpp b/demos/macosx/FrameDifferenceTest.cpp
deleted file mode 100644
index 7ebe8b1aa19ef3495d0cf57868340577a83f9134..0000000000000000000000000000000000000000
--- a/demos/macosx/FrameDifferenceTest.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <iostream>
-#include <cv.h>
-#include <highgui.h>
-
-#include "../../package_bgs/FrameDifference.h"
-
-using namespace bgslibrary::algorithms;
-
-int main(int argc, char **argv)
-{
-  CvCapture *capture = 0;
-  capture = cvCaptureFromCAM(0);
-
-  if(!capture){
-    std::cerr << "Cannot initialize video!" << std::endl;
-    return -1;
-  }
-
-  IBGS *bgs;
-  bgs = new FrameDifference;
-
-  IplImage *frame;
-  while(1)
-  {
-    frame = cvQueryFrame(capture);
-    if(!frame) break;
-
-    cv::Mat img_input(frame);
-    cv::imshow("Input", img_input);
-
-    cv::Mat img_mask;
-    cv::Mat img_bkgmodel;
-
-    // by default, it shows automatically the foreground mask image
-    bgs->process(img_input, img_mask, img_bkgmodel);
-
-    //if(!img_mask.empty())
-    //  cv::imshow("Foreground", img_mask);
-    //  do something
-
-    if(cvWaitKey(33) >= 0)
-		  break;
-  }
-
-  delete bgs;
-
-  cvDestroyAllWindows();
-  cvReleaseCapture(&capture);
-
-  return 0;
-}
diff --git a/demos/macosx/README.txt b/demos/macosx/README.txt
deleted file mode 100644
index 5558b71484046423834c91f24e75c4bd36d5bcd6..0000000000000000000000000000000000000000
--- a/demos/macosx/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# HOW TO COMPILE ON LINUX
-#
-# Requirements:
-# cmake >= 2.8
-# opencv >= 2.3.1
-
-cmake .
-make
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..03296d9d08ca4a14eb58df37cceb5d9af5ac15fc
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,144 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(bgslibrary-examples)
+
+set(CMAKE_CXX_STANDARD 14)
+
+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)
+
+# compilation mode setup
+set(CMAKE_BUILD_TYPE Release)
+#set(CMAKE_BUILD_TYPE Debug)
+
+if(WIN32)
+  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
+  set(BUILD_SHARED_LIBS TRUE)
+  #if(BGS_PYTHON_SUPPORT)
+    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
+    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
+  #else()
+  #  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+  #  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+  #endif()
+endif(WIN32)
+
+set(bgs_out_dir ".")
+# First for the generic no-config case (e.g. with mingw)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${bgs_out_dir})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${bgs_out_dir})
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${bgs_out_dir})
+# Second, for multi-config builds (e.g. msvc)
+foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
+  string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
+
+if(UNIX)
+  # add some standard warnings
+  ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
+
+  # -ansi does not compile with sjn module
+  #ADD_DEFINITIONS(-ansi)
+
+  # if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
+  #ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
+endif(UNIX)
+
+set(OpenCV_STATIC OFF)
+find_package(OpenCV REQUIRED)
+if(OpenCV_FOUND)
+  message(STATUS "")
+  message(STATUS "OpenCV library status:")
+  message(STATUS "    version: ${OpenCV_VERSION}")
+  message(STATUS "    libraries: ${OpenCV_LIBS}")
+  message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}\n")
+endif()
+
+# if(${OpenCV_VERSION} VERSION_EQUAL 3 OR ${OpenCV_VERSION} VERSION_GREATER 3)
+#   message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
+# endif()
+
+if(${OpenCV_VERSION} VERSION_LESS 2.3.1)
+  message(FATAL_ERROR "OpenCV version is not compatible: ${OpenCV_VERSION}")
+endif()
+
+file(GLOB demo Demo.cpp)
+file(GLOB demo2 Demo2.cpp)
+
+file(GLOB_RECURSE tools_src ../src/tools/*.cpp ../src/tools/*.c)
+file(GLOB_RECURSE tools_inc ../src/tools/*.h ../src/tools/*.hpp)
+
+file(GLOB_RECURSE utils_src ../src/utils/*.cpp ../src/utils/*.c)
+file(GLOB_RECURSE utils_inc ../src/utils/*.h ../src/utils/*.hpp)
+
+file(GLOB_RECURSE bgs_src ../src/algorithms/*.cpp ../src/algorithms/*.c)
+file(GLOB_RECURSE bgs_inc ../src/algorithms/*.h ../src/algorithms/*.hpp)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${OpenCV_INCLUDE_DIRS})
+
+# GMG is not available in older OpenCV versions
+if(${OpenCV_VERSION} VERSION_LESS 2.4.3)
+  file(GLOB gmg ../src/algorithms/GMG.cpp)
+  list(REMOVE_ITEM bgs_src ${gmg})
+endif()
+
+add_library(bgslibrary_core SHARED ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
+# generates the export header bgslibrary_core_EXPORTS.h automatically
+include(GenerateExportHeader)
+GENERATE_EXPORT_HEADER(bgslibrary_core
+    BASE_NAME bgslibrary_core
+    EXPORT_MACRO_NAME bgslibrary_core_EXPORTS
+    EXPORT_FILE_NAME bgslibrary_core_EXPORTS.h
+    STATIC_DEFINE BGSLIBRARY_CORE_EXPORTS_BUILT_AS_STATIC)
+target_link_libraries(bgslibrary_core ${OpenCV_LIBS})
+set_property(TARGET bgslibrary_core PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc})
+
+#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()
+
+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)
+
+if(UNIX)
+  # to avoid: error while loading shared libraries: libbgslibrary_core.so
+  message(STATUS "You might need to run:")
+  message(STATUS "$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib")
+  message(STATUS "$ export LD_LIBRARY_PATH")
+  message(STATUS "after 'make install' to avoid error while loading libbgslibrary_core\n")
+endif()
+
+if(WIN32)
+  message(STATUS "You might need to add ${CMAKE_CURRENT_BINARY_DIR} to your PATH to be able to run your applications.")
+  message(STATUS "> set PATH=%PATH%;${CMAKE_CURRENT_BINARY_DIR}\n")
+endif()
diff --git a/examples/Demo.cpp b/examples/Demo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2bfec63b297acb1f1ec796f5349a9137d0674512
--- /dev/null
+++ b/examples/Demo.cpp
@@ -0,0 +1,92 @@
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include <opencv2/opencv.hpp>
+
+#include "../src/algorithms/algorithms.h"
+
+#if CV_MAJOR_VERSION >= 4
+#define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES
+#define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT
+#endif
+
+int main(int argc, char **argv)
+{
+  std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
+
+  cv::VideoCapture capture;
+
+  if (argc > 1)
+  {
+    std::cout << "Openning: " << argv[1] << std::endl;
+    capture.open(argv[1]);
+  }
+  else
+    capture.open(0);
+
+  if (!capture.isOpened())
+  {
+    std::cerr << "Cannot initialize video!" << std::endl;
+    return -1;
+  }
+
+  /* Background Subtraction Methods */
+  auto algorithmsName = BGS_Factory::Instance()->GetRegisteredAlgorithmsName();
+  
+  std::cout << "List of available algorithms:" << std::endl;
+  std::copy(algorithmsName.begin(), algorithmsName.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
+  
+  for (const std::string& algorithmName : algorithmsName)
+  {
+    std::cout << "Running " << algorithmName << std::endl;
+    auto bgs = BGS_Factory::Instance()->Create(algorithmName);
+
+    cv::Mat img_input;
+    
+    capture.set(CV_CAP_PROP_POS_FRAMES, 0); // Set index to 0 (start frame)
+    auto frame_counter = 0;
+    std::cout << "Press 's' to stop:" << std::endl;
+    auto key = 0;
+    while (key != 's')
+    {
+      // Capture frame-by-frame
+      capture >> img_input;
+      frame_counter += 1;
+
+      if (img_input.empty()) break;
+
+      cv::resize(img_input, img_input, cv::Size(380, 240), 0, 0, CV_INTER_LINEAR);
+      cv::imshow("input", img_input);
+
+      cv::Mat img_mask;
+      cv::Mat img_bkgmodel;
+      try
+      {
+        bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
+
+        //if(!img_mask.empty())
+        //  cv::imshow("Foreground", img_mask);
+        //  do something
+      }
+      catch (std::exception& e)
+      {
+        std::cout << "Exception occurred" << std::endl;
+        std::cout << e.what() << std::endl;
+      }
+
+      key = cv::waitKey(33);
+    }
+
+    std::cout << "Press 'q' to exit, or anything else to move to the next algorithm:" << std::endl;
+    key = cv::waitKey(0);
+    if (key == 'q')
+      break;
+
+    cv::destroyAllWindows();
+  }
+
+  capture.release();
+
+  return 0;
+}
diff --git a/examples/Demo.cpp.bup b/examples/Demo.cpp.bup
new file mode 100644
index 0000000000000000000000000000000000000000..2bfec63b297acb1f1ec796f5349a9137d0674512
--- /dev/null
+++ b/examples/Demo.cpp.bup
@@ -0,0 +1,92 @@
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include <opencv2/opencv.hpp>
+
+#include "../src/algorithms/algorithms.h"
+
+#if CV_MAJOR_VERSION >= 4
+#define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES
+#define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT
+#endif
+
+int main(int argc, char **argv)
+{
+  std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
+
+  cv::VideoCapture capture;
+
+  if (argc > 1)
+  {
+    std::cout << "Openning: " << argv[1] << std::endl;
+    capture.open(argv[1]);
+  }
+  else
+    capture.open(0);
+
+  if (!capture.isOpened())
+  {
+    std::cerr << "Cannot initialize video!" << std::endl;
+    return -1;
+  }
+
+  /* Background Subtraction Methods */
+  auto algorithmsName = BGS_Factory::Instance()->GetRegisteredAlgorithmsName();
+  
+  std::cout << "List of available algorithms:" << std::endl;
+  std::copy(algorithmsName.begin(), algorithmsName.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
+  
+  for (const std::string& algorithmName : algorithmsName)
+  {
+    std::cout << "Running " << algorithmName << std::endl;
+    auto bgs = BGS_Factory::Instance()->Create(algorithmName);
+
+    cv::Mat img_input;
+    
+    capture.set(CV_CAP_PROP_POS_FRAMES, 0); // Set index to 0 (start frame)
+    auto frame_counter = 0;
+    std::cout << "Press 's' to stop:" << std::endl;
+    auto key = 0;
+    while (key != 's')
+    {
+      // Capture frame-by-frame
+      capture >> img_input;
+      frame_counter += 1;
+
+      if (img_input.empty()) break;
+
+      cv::resize(img_input, img_input, cv::Size(380, 240), 0, 0, CV_INTER_LINEAR);
+      cv::imshow("input", img_input);
+
+      cv::Mat img_mask;
+      cv::Mat img_bkgmodel;
+      try
+      {
+        bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
+
+        //if(!img_mask.empty())
+        //  cv::imshow("Foreground", img_mask);
+        //  do something
+      }
+      catch (std::exception& e)
+      {
+        std::cout << "Exception occurred" << std::endl;
+        std::cout << e.what() << std::endl;
+      }
+
+      key = cv::waitKey(33);
+    }
+
+    std::cout << "Press 'q' to exit, or anything else to move to the next algorithm:" << std::endl;
+    key = cv::waitKey(0);
+    if (key == 'q')
+      break;
+
+    cv::destroyAllWindows();
+  }
+
+  capture.release();
+
+  return 0;
+}
diff --git a/examples/Demo2.cpp b/examples/Demo2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8b4f69839d141345a01c423d1bd98d3d34b287bb
--- /dev/null
+++ b/examples/Demo2.cpp
@@ -0,0 +1,80 @@
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include <opencv2/opencv.hpp>
+
+#include "../src/algorithms/algorithms.h"
+
+#if CV_MAJOR_VERSION >= 4
+#define CV_LOAD_IMAGE_COLOR cv::IMREAD_COLOR
+#endif
+
+int main(int argc, char **argv)
+{
+  std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl;
+
+  std::string baseDir = "./dataset/frames";
+  if (argc > 1)
+    baseDir = argv[1];
+  std::cout << "Openning: " << baseDir << std::endl;
+
+  /* Background Subtraction Methods */
+  auto algorithmsName = BGS_Factory::Instance()->GetRegisteredAlgorithmsName();
+  
+  std::cout << "List of available algorithms:" << std::endl;
+  std::copy(algorithmsName.begin(), algorithmsName.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
+  
+  for (const std::string& algorithmName : algorithmsName)
+  {
+    std::cout << "Running " << algorithmName << std::endl;
+    auto bgs = BGS_Factory::Instance()->Create(algorithmName);
+
+    auto frame_counter = 0;
+    std::cout << "Press 's' to stop:" << std::endl;
+    auto key = 0;
+    while (key != 's')
+    {
+      // Capture frame-by-frame
+      frame_counter++;
+      std::stringstream ss;
+      ss << frame_counter;
+      auto fileName = baseDir + "/" + ss.str() + ".png";
+      std::cout << "reading " << fileName << std::endl;
+
+      auto img_input = cv::imread(fileName, CV_LOAD_IMAGE_COLOR);
+
+      if (img_input.empty())
+        break;
+
+      cv::imshow("input", img_input);
+
+      cv::Mat img_mask;
+      cv::Mat img_bkgmodel;
+      try
+      {
+        bgs->process(img_input, img_mask, img_bkgmodel); // by default, it shows automatically the foreground mask image
+
+        //if(!img_mask.empty())
+        //  cv::imshow("Foreground", img_mask);
+        //  do something
+      }
+      catch (std::exception& e)
+      {
+        std::cout << "Exception occurred" << std::endl;
+        std::cout << e.what() << std::endl;
+      }
+
+      key = cv::waitKey(33);
+    }
+
+    std::cout << "Press 'q' to exit, or anything else to move to the next algorithm:" << std::endl;
+    key = cv::waitKey(0);
+    if (key == 'q')
+      break;
+
+    cv::destroyAllWindows();
+  }
+
+  return 0;
+}
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f4486ec8029e0ba872ffb873e0848c22ebe52ba1
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,27 @@
+### BGS Library Examples
+
+#### CMake on Linux or MacOS
+```
+cd build
+cmake ..
+make
+cd ..
+```
+
+#### Running
+```
+chmod +x *.sh
+./run_demo.sh
+./run_demo2.sh
+```
+or
+```
+# using a web camera
+./build/bgs_demo
+
+# using a video file
+./build/bgs_demo ../dataset/video.avi
+
+# using a sequence of images
+./build/bgs_demo2 ../dataset/frames
+```
diff --git a/gui_mfc/outputs/foreground/.gitignore b/examples/build/.gitignore
similarity index 100%
rename from gui_mfc/outputs/foreground/.gitignore
rename to examples/build/.gitignore
diff --git a/gui_mfc/outputs/input/.gitignore b/examples/config/.gitignore
similarity index 100%
rename from gui_mfc/outputs/input/.gitignore
rename to examples/config/.gitignore
diff --git a/examples/run_demo.bat b/examples/run_demo.bat
new file mode 100644
index 0000000000000000000000000000000000000000..1b9c9d695c606078f14eefd261f3414d6834e307
--- /dev/null
+++ b/examples/run_demo.bat
@@ -0,0 +1,2 @@
+@echo off
+build\bgs_demo.exe ../dataset/video.avi
diff --git a/examples/run_demo.sh b/examples/run_demo.sh
new file mode 100755
index 0000000000000000000000000000000000000000..61373c73e4238907f333b3f912923787003632fa
--- /dev/null
+++ b/examples/run_demo.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+./build/bgs_demo ../dataset/video.avi
diff --git a/examples/run_demo2.bat b/examples/run_demo2.bat
new file mode 100644
index 0000000000000000000000000000000000000000..7a1347cac9ed0f911fd3a5dc7dfe7b47b245cc70
--- /dev/null
+++ b/examples/run_demo2.bat
@@ -0,0 +1,2 @@
+@echo off
+build\bgs_demo2.exe ../dataset/frames
diff --git a/examples/run_demo2.sh b/examples/run_demo2.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6fe32dacefa236989b95a931c801fc18e41a0879
--- /dev/null
+++ b/examples/run_demo2.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+./build/bgs_demo2 ../dataset/frames
diff --git a/gui/README.md b/gui/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..37f570ec89ed7c1daf694e4ef45c1f1764f4cb13
--- /dev/null
+++ b/gui/README.md
@@ -0,0 +1,5 @@
+* Graphical User Interface:
+
+*  * [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)***
diff --git a/gui_java/README.txt b/gui/java/README.txt
similarity index 100%
rename from gui_java/README.txt
rename to gui/java/README.txt
diff --git a/gui_java/bgslibrary_gui.jar b/gui/java/bgslibrary_gui.jar
similarity index 100%
rename from gui_java/bgslibrary_gui.jar
rename to gui/java/bgslibrary_gui.jar
diff --git a/gui_java/bgslibrary_gui.properties b/gui/java/bgslibrary_gui.properties
similarity index 100%
rename from gui_java/bgslibrary_gui.properties
rename to gui/java/bgslibrary_gui.properties
diff --git a/gui_java/build.xml b/gui/java/build.xml
similarity index 100%
rename from gui_java/build.xml
rename to gui/java/build.xml
diff --git a/gui_java/config/.gitignore b/gui/java/config/.gitignore
similarity index 100%
rename from gui_java/config/.gitignore
rename to gui/java/config/.gitignore
diff --git a/gui_java/config/FrameProcessor.xml b/gui/java/config/FrameProcessor.xml
similarity index 100%
rename from gui_java/config/FrameProcessor.xml
rename to gui/java/config/FrameProcessor.xml
diff --git a/gui_java/config/PreProcessor.xml b/gui/java/config/PreProcessor.xml
similarity index 100%
rename from gui_java/config/PreProcessor.xml
rename to gui/java/config/PreProcessor.xml
diff --git a/gui_java/config/VideoCapture.xml b/gui/java/config/VideoCapture.xml
similarity index 100%
rename from gui_java/config/VideoCapture.xml
rename to gui/java/config/VideoCapture.xml
diff --git a/gui_java/images/bgslibrary_gui_screen01.png b/gui/java/images/bgslibrary_gui_screen01.png
similarity index 100%
rename from gui_java/images/bgslibrary_gui_screen01.png
rename to gui/java/images/bgslibrary_gui_screen01.png
diff --git a/gui_java/images/bgslibrary_gui_screen02.png b/gui/java/images/bgslibrary_gui_screen02.png
similarity index 100%
rename from gui_java/images/bgslibrary_gui_screen02.png
rename to gui/java/images/bgslibrary_gui_screen02.png
diff --git a/gui_java/images/bgslibrary_gui_screen03.png b/gui/java/images/bgslibrary_gui_screen03.png
similarity index 100%
rename from gui_java/images/bgslibrary_gui_screen03.png
rename to gui/java/images/bgslibrary_gui_screen03.png
diff --git a/gui_java/images/bgslibrary_gui_screen04.png b/gui/java/images/bgslibrary_gui_screen04.png
similarity index 100%
rename from gui_java/images/bgslibrary_gui_screen04.png
rename to gui/java/images/bgslibrary_gui_screen04.png
diff --git a/gui_java/images/logo.jpg b/gui/java/images/logo.jpg
similarity index 100%
rename from gui_java/images/logo.jpg
rename to gui/java/images/logo.jpg
diff --git a/gui_java/lib/commons-configuration-1.8.jar b/gui/java/lib/commons-configuration-1.8.jar
similarity index 100%
rename from gui_java/lib/commons-configuration-1.8.jar
rename to gui/java/lib/commons-configuration-1.8.jar
diff --git a/gui_java/lib/commons-io-2.3.jar b/gui/java/lib/commons-io-2.3.jar
similarity index 100%
rename from gui_java/lib/commons-io-2.3.jar
rename to gui/java/lib/commons-io-2.3.jar
diff --git a/gui_java/lib/commons-lang-2.6.jar b/gui/java/lib/commons-lang-2.6.jar
similarity index 100%
rename from gui_java/lib/commons-lang-2.6.jar
rename to gui/java/lib/commons-lang-2.6.jar
diff --git a/gui_java/lib/commons-logging-1.1.1.jar b/gui/java/lib/commons-logging-1.1.1.jar
similarity index 100%
rename from gui_java/lib/commons-logging-1.1.1.jar
rename to gui/java/lib/commons-logging-1.1.1.jar
diff --git a/gui_java/lib/swingx-all-1.6.3.jar b/gui/java/lib/swingx-all-1.6.3.jar
similarity index 100%
rename from gui_java/lib/swingx-all-1.6.3.jar
rename to gui/java/lib/swingx-all-1.6.3.jar
diff --git a/gui_java/lib/swingx-beaninfo-1.6.3.jar b/gui/java/lib/swingx-beaninfo-1.6.3.jar
similarity index 100%
rename from gui_java/lib/swingx-beaninfo-1.6.3.jar
rename to gui/java/lib/swingx-beaninfo-1.6.3.jar
diff --git a/gui_java/manifest.mf b/gui/java/manifest.mf
similarity index 100%
rename from gui_java/manifest.mf
rename to gui/java/manifest.mf
diff --git a/gui_java/nbproject/build-impl.xml b/gui/java/nbproject/build-impl.xml
similarity index 100%
rename from gui_java/nbproject/build-impl.xml
rename to gui/java/nbproject/build-impl.xml
diff --git a/gui_java/nbproject/genfiles.properties b/gui/java/nbproject/genfiles.properties
similarity index 100%
rename from gui_java/nbproject/genfiles.properties
rename to gui/java/nbproject/genfiles.properties
diff --git a/gui_java/nbproject/private/config.properties b/gui/java/nbproject/private/config.properties
similarity index 100%
rename from gui_java/nbproject/private/config.properties
rename to gui/java/nbproject/private/config.properties
diff --git a/gui_java/nbproject/private/private.properties b/gui/java/nbproject/private/private.properties
similarity index 100%
rename from gui_java/nbproject/private/private.properties
rename to gui/java/nbproject/private/private.properties
diff --git a/gui_java/nbproject/private/private.xml b/gui/java/nbproject/private/private.xml
similarity index 100%
rename from gui_java/nbproject/private/private.xml
rename to gui/java/nbproject/private/private.xml
diff --git a/gui_java/nbproject/project.properties b/gui/java/nbproject/project.properties
similarity index 100%
rename from gui_java/nbproject/project.properties
rename to gui/java/nbproject/project.properties
diff --git a/gui_java/nbproject/project.xml b/gui/java/nbproject/project.xml
similarity index 100%
rename from gui_java/nbproject/project.xml
rename to gui/java/nbproject/project.xml
diff --git a/gui_java/run_camera.bat b/gui/java/run_camera.bat
similarity index 100%
rename from gui_java/run_camera.bat
rename to gui/java/run_camera.bat
diff --git a/gui_java/run_java_gui.bat b/gui/java/run_java_gui.bat
similarity index 100%
rename from gui_java/run_java_gui.bat
rename to gui/java/run_java_gui.bat
diff --git a/gui_java/run_java_gui_with_console.bat b/gui/java/run_java_gui_with_console.bat
similarity index 100%
rename from gui_java/run_java_gui_with_console.bat
rename to gui/java/run_java_gui_with_console.bat
diff --git a/gui_java/run_video.bat b/gui/java/run_video.bat
similarity index 100%
rename from gui_java/run_video.bat
rename to gui/java/run_video.bat
diff --git a/gui_java/src/br/com/bgslibrary/Main.java b/gui/java/src/br/com/bgslibrary/Main.java
similarity index 60%
rename from gui_java/src/br/com/bgslibrary/Main.java
rename to gui/java/src/br/com/bgslibrary/Main.java
index f986a21bee6833ecc9ece0ccd587bb4cad44543d..339fae62e1afa151acf6c5f5496d91e9bb25f2b5 100644
--- a/gui_java/src/br/com/bgslibrary/Main.java
+++ b/gui/java/src/br/com/bgslibrary/Main.java
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 package br.com.bgslibrary;
 
 import br.com.bgslibrary.gui.MainFrame;
diff --git a/gui_java/src/br/com/bgslibrary/entity/Command.java b/gui/java/src/br/com/bgslibrary/entity/Command.java
similarity index 83%
rename from gui_java/src/br/com/bgslibrary/entity/Command.java
rename to gui/java/src/br/com/bgslibrary/entity/Command.java
index 57abcf4bb9b8aacf6ad5c0a1cebbcf886c06b99b..452173b13817b4f7a5a19623d758f13a62272b14 100644
--- a/gui_java/src/br/com/bgslibrary/entity/Command.java
+++ b/gui/java/src/br/com/bgslibrary/entity/Command.java
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 package br.com.bgslibrary.entity;
 
 public class Command
diff --git a/gui_java/src/br/com/bgslibrary/entity/Configuration.java b/gui/java/src/br/com/bgslibrary/entity/Configuration.java
similarity index 78%
rename from gui_java/src/br/com/bgslibrary/entity/Configuration.java
rename to gui/java/src/br/com/bgslibrary/entity/Configuration.java
index caa07fda3c0cc2f2a7cd530036b5e803cb6b2ec4..d5abebda99c86b5d5e96273dbf323bfa0d5433ed 100644
--- a/gui_java/src/br/com/bgslibrary/entity/Configuration.java
+++ b/gui/java/src/br/com/bgslibrary/entity/Configuration.java
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 package br.com.bgslibrary.entity;
 
 public interface Configuration
diff --git a/gui_java/src/br/com/bgslibrary/gui/AboutDialog.form b/gui/java/src/br/com/bgslibrary/gui/AboutDialog.form
similarity index 100%
rename from gui_java/src/br/com/bgslibrary/gui/AboutDialog.form
rename to gui/java/src/br/com/bgslibrary/gui/AboutDialog.form
diff --git a/gui_java/src/br/com/bgslibrary/gui/AboutDialog.java b/gui/java/src/br/com/bgslibrary/gui/AboutDialog.java
similarity index 87%
rename from gui_java/src/br/com/bgslibrary/gui/AboutDialog.java
rename to gui/java/src/br/com/bgslibrary/gui/AboutDialog.java
index 2c8afc01d03d3402081a07657535b3f7ee872c61..836a5abc1bdbf932622456c48812433f17aa3843 100644
--- a/gui_java/src/br/com/bgslibrary/gui/AboutDialog.java
+++ b/gui/java/src/br/com/bgslibrary/gui/AboutDialog.java
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 package br.com.bgslibrary.gui;
 
 public class AboutDialog extends javax.swing.JDialog
diff --git a/gui_java/src/br/com/bgslibrary/gui/MainFrame.form b/gui/java/src/br/com/bgslibrary/gui/MainFrame.form
similarity index 100%
rename from gui_java/src/br/com/bgslibrary/gui/MainFrame.form
rename to gui/java/src/br/com/bgslibrary/gui/MainFrame.form
diff --git a/gui_java/src/br/com/bgslibrary/gui/MainFrame.java b/gui/java/src/br/com/bgslibrary/gui/MainFrame.java
similarity index 99%
rename from gui_java/src/br/com/bgslibrary/gui/MainFrame.java
rename to gui/java/src/br/com/bgslibrary/gui/MainFrame.java
index 4938426f86529e1a6abf60ae8f40aa4a04490cad..538e1898c426ebf8a70dbc651d6e38ba598e5de7 100644
--- a/gui_java/src/br/com/bgslibrary/gui/MainFrame.java
+++ b/gui/java/src/br/com/bgslibrary/gui/MainFrame.java
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 package br.com.bgslibrary.gui;
 
 import br.com.bgslibrary.entity.Command;
diff --git a/gui_java/src/br/com/bgslibrary/resources/logo.jpg b/gui/java/src/br/com/bgslibrary/resources/logo.jpg
similarity index 100%
rename from gui_java/src/br/com/bgslibrary/resources/logo.jpg
rename to gui/java/src/br/com/bgslibrary/resources/logo.jpg
diff --git a/gui_mfc/.gitignore b/gui/mfc/.gitignore
similarity index 100%
rename from gui_mfc/.gitignore
rename to gui/mfc/.gitignore
diff --git a/gui_mfc/ReadMe.txt b/gui/mfc/ReadMe.txt
similarity index 100%
rename from gui_mfc/ReadMe.txt
rename to gui/mfc/ReadMe.txt
diff --git a/gui_mfc/config/AdaptiveBackgroundLearning.xml b/gui/mfc/config/AdaptiveBackgroundLearning.xml
similarity index 100%
rename from gui_mfc/config/AdaptiveBackgroundLearning.xml
rename to gui/mfc/config/AdaptiveBackgroundLearning.xml
diff --git a/gui_mfc/config/AdaptiveSelectiveBackgroundLearning.xml b/gui/mfc/config/AdaptiveSelectiveBackgroundLearning.xml
similarity index 100%
rename from gui_mfc/config/AdaptiveSelectiveBackgroundLearning.xml
rename to gui/mfc/config/AdaptiveSelectiveBackgroundLearning.xml
diff --git a/gui_mfc/config/DPAdaptiveMedianBGS.xml b/gui/mfc/config/DPAdaptiveMedianBGS.xml
similarity index 100%
rename from gui_mfc/config/DPAdaptiveMedianBGS.xml
rename to gui/mfc/config/DPAdaptiveMedianBGS.xml
diff --git a/gui_mfc/config/DPEigenbackgroundBGS.xml b/gui/mfc/config/DPEigenbackgroundBGS.xml
similarity index 100%
rename from gui_mfc/config/DPEigenbackgroundBGS.xml
rename to gui/mfc/config/DPEigenbackgroundBGS.xml
diff --git a/gui_mfc/config/DPGrimsonGMMBGS.xml b/gui/mfc/config/DPGrimsonGMMBGS.xml
similarity index 100%
rename from gui_mfc/config/DPGrimsonGMMBGS.xml
rename to gui/mfc/config/DPGrimsonGMMBGS.xml
diff --git a/gui_mfc/config/DPMeanBGS.xml b/gui/mfc/config/DPMeanBGS.xml
similarity index 100%
rename from gui_mfc/config/DPMeanBGS.xml
rename to gui/mfc/config/DPMeanBGS.xml
diff --git a/gui_mfc/config/DPPratiMediodBGS.xml b/gui/mfc/config/DPPratiMediodBGS.xml
similarity index 100%
rename from gui_mfc/config/DPPratiMediodBGS.xml
rename to gui/mfc/config/DPPratiMediodBGS.xml
diff --git a/gui_mfc/config/DPTextureBGS.xml b/gui/mfc/config/DPTextureBGS.xml
similarity index 100%
rename from gui_mfc/config/DPTextureBGS.xml
rename to gui/mfc/config/DPTextureBGS.xml
diff --git a/gui_mfc/config/DPWrenGABGS.xml b/gui/mfc/config/DPWrenGABGS.xml
similarity index 100%
rename from gui_mfc/config/DPWrenGABGS.xml
rename to gui/mfc/config/DPWrenGABGS.xml
diff --git a/gui_mfc/config/DPZivkovicAGMMBGS.xml b/gui/mfc/config/DPZivkovicAGMMBGS.xml
similarity index 100%
rename from gui_mfc/config/DPZivkovicAGMMBGS.xml
rename to gui/mfc/config/DPZivkovicAGMMBGS.xml
diff --git a/gui_mfc/config/FrameDifferenceBGS.xml b/gui/mfc/config/FrameDifferenceBGS.xml
similarity index 100%
rename from gui_mfc/config/FrameDifferenceBGS.xml
rename to gui/mfc/config/FrameDifferenceBGS.xml
diff --git a/gui_mfc/config/FuzzyChoquetIntegral.xml b/gui/mfc/config/FuzzyChoquetIntegral.xml
similarity index 100%
rename from gui_mfc/config/FuzzyChoquetIntegral.xml
rename to gui/mfc/config/FuzzyChoquetIntegral.xml
diff --git a/gui_mfc/config/FuzzySugenoIntegral.xml b/gui/mfc/config/FuzzySugenoIntegral.xml
similarity index 100%
rename from gui_mfc/config/FuzzySugenoIntegral.xml
rename to gui/mfc/config/FuzzySugenoIntegral.xml
diff --git a/gui_mfc/config/GMG.xml b/gui/mfc/config/GMG.xml
similarity index 100%
rename from gui_mfc/config/GMG.xml
rename to gui/mfc/config/GMG.xml
diff --git a/gui_mfc/config/IndependentMultimodalBGS.xml b/gui/mfc/config/IndependentMultimodalBGS.xml
similarity index 100%
rename from gui_mfc/config/IndependentMultimodalBGS.xml
rename to gui/mfc/config/IndependentMultimodalBGS.xml
diff --git a/gui_mfc/config/KDE.xml b/gui/mfc/config/KDE.xml
similarity index 100%
rename from gui_mfc/config/KDE.xml
rename to gui/mfc/config/KDE.xml
diff --git a/gui_mfc/config/LBAdaptiveSOM.xml b/gui/mfc/config/LBAdaptiveSOM.xml
similarity index 100%
rename from gui_mfc/config/LBAdaptiveSOM.xml
rename to gui/mfc/config/LBAdaptiveSOM.xml
diff --git a/gui_mfc/config/LBFuzzyAdaptiveSOM.xml b/gui/mfc/config/LBFuzzyAdaptiveSOM.xml
similarity index 100%
rename from gui_mfc/config/LBFuzzyAdaptiveSOM.xml
rename to gui/mfc/config/LBFuzzyAdaptiveSOM.xml
diff --git a/gui_mfc/config/LBFuzzyGaussian.xml b/gui/mfc/config/LBFuzzyGaussian.xml
similarity index 100%
rename from gui_mfc/config/LBFuzzyGaussian.xml
rename to gui/mfc/config/LBFuzzyGaussian.xml
diff --git a/gui_mfc/config/LBMixtureOfGaussians.xml b/gui/mfc/config/LBMixtureOfGaussians.xml
similarity index 100%
rename from gui_mfc/config/LBMixtureOfGaussians.xml
rename to gui/mfc/config/LBMixtureOfGaussians.xml
diff --git a/gui_mfc/config/LBSimpleGaussian.xml b/gui/mfc/config/LBSimpleGaussian.xml
similarity index 100%
rename from gui_mfc/config/LBSimpleGaussian.xml
rename to gui/mfc/config/LBSimpleGaussian.xml
diff --git a/gui_mfc/config/LOBSTERBGS.xml b/gui/mfc/config/LOBSTERBGS.xml
similarity index 100%
rename from gui_mfc/config/LOBSTERBGS.xml
rename to gui/mfc/config/LOBSTERBGS.xml
diff --git a/gui_mfc/config/MixtureOfGaussianV1BGS.xml b/gui/mfc/config/MixtureOfGaussianV1BGS.xml
similarity index 100%
rename from gui_mfc/config/MixtureOfGaussianV1BGS.xml
rename to gui/mfc/config/MixtureOfGaussianV1BGS.xml
diff --git a/gui_mfc/config/MixtureOfGaussianV2BGS.xml b/gui/mfc/config/MixtureOfGaussianV2BGS.xml
similarity index 100%
rename from gui_mfc/config/MixtureOfGaussianV2BGS.xml
rename to gui/mfc/config/MixtureOfGaussianV2BGS.xml
diff --git a/gui_mfc/config/MultiCueBGS.xml b/gui/mfc/config/MultiCueBGS.xml
similarity index 100%
rename from gui_mfc/config/MultiCueBGS.xml
rename to gui/mfc/config/MultiCueBGS.xml
diff --git a/gui_mfc/config/MultiLayerBGS.xml b/gui/mfc/config/MultiLayerBGS.xml
similarity index 100%
rename from gui_mfc/config/MultiLayerBGS.xml
rename to gui/mfc/config/MultiLayerBGS.xml
diff --git a/gui_mfc/config/SigmaDeltaBGS.xml b/gui/mfc/config/SigmaDeltaBGS.xml
similarity index 100%
rename from gui_mfc/config/SigmaDeltaBGS.xml
rename to gui/mfc/config/SigmaDeltaBGS.xml
diff --git a/gui_mfc/config/StaticFrameDifferenceBGS.xml b/gui/mfc/config/StaticFrameDifferenceBGS.xml
similarity index 100%
rename from gui_mfc/config/StaticFrameDifferenceBGS.xml
rename to gui/mfc/config/StaticFrameDifferenceBGS.xml
diff --git a/gui_mfc/config/SuBSENSEBGS.xml b/gui/mfc/config/SuBSENSEBGS.xml
similarity index 100%
rename from gui_mfc/config/SuBSENSEBGS.xml
rename to gui/mfc/config/SuBSENSEBGS.xml
diff --git a/gui_mfc/config/T2FGMM_UM.xml b/gui/mfc/config/T2FGMM_UM.xml
similarity index 100%
rename from gui_mfc/config/T2FGMM_UM.xml
rename to gui/mfc/config/T2FGMM_UM.xml
diff --git a/gui_mfc/config/T2FGMM_UV.xml b/gui/mfc/config/T2FGMM_UV.xml
similarity index 100%
rename from gui_mfc/config/T2FGMM_UV.xml
rename to gui/mfc/config/T2FGMM_UV.xml
diff --git a/gui_mfc/config/T2FMRF_UM.xml b/gui/mfc/config/T2FMRF_UM.xml
similarity index 100%
rename from gui_mfc/config/T2FMRF_UM.xml
rename to gui/mfc/config/T2FMRF_UM.xml
diff --git a/gui_mfc/config/T2FMRF_UV.xml b/gui/mfc/config/T2FMRF_UV.xml
similarity index 100%
rename from gui_mfc/config/T2FMRF_UV.xml
rename to gui/mfc/config/T2FMRF_UV.xml
diff --git a/gui_mfc/config/VuMeter.xml b/gui/mfc/config/VuMeter.xml
similarity index 100%
rename from gui_mfc/config/VuMeter.xml
rename to gui/mfc/config/VuMeter.xml
diff --git a/gui_mfc/config/WeightedMovingMeanBGS.xml b/gui/mfc/config/WeightedMovingMeanBGS.xml
similarity index 100%
rename from gui_mfc/config/WeightedMovingMeanBGS.xml
rename to gui/mfc/config/WeightedMovingMeanBGS.xml
diff --git a/gui_mfc/config/WeightedMovingVarianceBGS.xml b/gui/mfc/config/WeightedMovingVarianceBGS.xml
similarity index 100%
rename from gui_mfc/config/WeightedMovingVarianceBGS.xml
rename to gui/mfc/config/WeightedMovingVarianceBGS.xml
diff --git a/gui_mfc/dataset/video.avi b/gui/mfc/dataset/video.avi
similarity index 100%
rename from gui_mfc/dataset/video.avi
rename to gui/mfc/dataset/video.avi
diff --git a/gui_qt/build/.gitignore b/gui/mfc/outputs/background/.gitignore
similarity index 100%
rename from gui_qt/build/.gitignore
rename to gui/mfc/outputs/background/.gitignore
diff --git a/wrapper_matlab/config/.gitignore b/gui/mfc/outputs/foreground/.gitignore
similarity index 100%
rename from wrapper_matlab/config/.gitignore
rename to gui/mfc/outputs/foreground/.gitignore
diff --git a/demos/linux_ubuntu/config/.gitignore b/gui/mfc/outputs/input/.gitignore
similarity index 83%
rename from demos/linux_ubuntu/config/.gitignore
rename to gui/mfc/outputs/input/.gitignore
index 8ee04a01eb210a035d02f190538c5235aebc7277..4e2a98bb114355ae964e78a929c12d44f75815de 100644
--- a/demos/linux_ubuntu/config/.gitignore
+++ b/gui/mfc/outputs/input/.gitignore
@@ -1,4 +1,4 @@
 # Ignore everything in this directory
 *
 # Except these files
-!.gitignore
\ No newline at end of file
+!.gitignore
diff --git a/gui_mfc/src/.gitignore b/gui/mfc/src/.gitignore
similarity index 100%
rename from gui_mfc/src/.gitignore
rename to gui/mfc/src/.gitignore
diff --git a/gui_mfc/src/App.cpp b/gui/mfc/src/App.cpp
similarity index 100%
rename from gui_mfc/src/App.cpp
rename to gui/mfc/src/App.cpp
diff --git a/gui_mfc/src/App.h b/gui/mfc/src/App.h
similarity index 100%
rename from gui_mfc/src/App.h
rename to gui/mfc/src/App.h
diff --git a/gui_mfc/src/Dlg.cpp b/gui/mfc/src/Dlg.cpp
similarity index 100%
rename from gui_mfc/src/Dlg.cpp
rename to gui/mfc/src/Dlg.cpp
diff --git a/gui_mfc/src/Dlg.h b/gui/mfc/src/Dlg.h
similarity index 100%
rename from gui_mfc/src/Dlg.h
rename to gui/mfc/src/Dlg.h
diff --git a/gui_mfc/src/ReadMe.txt b/gui/mfc/src/ReadMe.txt
similarity index 100%
rename from gui_mfc/src/ReadMe.txt
rename to gui/mfc/src/ReadMe.txt
diff --git a/gui_mfc/src/bgslibrary_vs2013_mfc.rc b/gui/mfc/src/bgslibrary_vs2013_mfc.rc
similarity index 100%
rename from gui_mfc/src/bgslibrary_vs2013_mfc.rc
rename to gui/mfc/src/bgslibrary_vs2013_mfc.rc
diff --git a/gui_mfc/src/bgslibrary_vs2013_mfc.sln b/gui/mfc/src/bgslibrary_vs2013_mfc.sln
similarity index 100%
rename from gui_mfc/src/bgslibrary_vs2013_mfc.sln
rename to gui/mfc/src/bgslibrary_vs2013_mfc.sln
diff --git a/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj b/gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj
similarity index 100%
rename from gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj
rename to gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj
diff --git a/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters b/gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters
similarity index 100%
rename from gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters
rename to gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters
diff --git a/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.user b/gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj.user
similarity index 100%
rename from gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.user
rename to gui/mfc/src/bgslibrary_vs2013_mfc.vcxproj.user
diff --git a/gui_mfc/src/res/bgslibrary_vs2013_mfc.ico b/gui/mfc/src/res/bgslibrary_vs2013_mfc.ico
similarity index 100%
rename from gui_mfc/src/res/bgslibrary_vs2013_mfc.ico
rename to gui/mfc/src/res/bgslibrary_vs2013_mfc.ico
diff --git a/gui_mfc/src/res/bgslibrary_vs2013_mfc.rc2 b/gui/mfc/src/res/bgslibrary_vs2013_mfc.rc2
similarity index 100%
rename from gui_mfc/src/res/bgslibrary_vs2013_mfc.rc2
rename to gui/mfc/src/res/bgslibrary_vs2013_mfc.rc2
diff --git a/gui_mfc/src/resource.h b/gui/mfc/src/resource.h
similarity index 100%
rename from gui_mfc/src/resource.h
rename to gui/mfc/src/resource.h
diff --git a/gui_mfc/src/stdafx.cpp b/gui/mfc/src/stdafx.cpp
similarity index 100%
rename from gui_mfc/src/stdafx.cpp
rename to gui/mfc/src/stdafx.cpp
diff --git a/gui_mfc/src/stdafx.h b/gui/mfc/src/stdafx.h
similarity index 100%
rename from gui_mfc/src/stdafx.h
rename to gui/mfc/src/stdafx.h
diff --git a/gui_mfc/src/targetver.h b/gui/mfc/src/targetver.h
similarity index 100%
rename from gui_mfc/src/targetver.h
rename to gui/mfc/src/targetver.h
diff --git a/gui_qt/.gitignore b/gui/qt/.gitignore
similarity index 86%
rename from gui_qt/.gitignore
rename to gui/qt/.gitignore
index 9c28032b4c6631a5f27072a12901a0fecd324309..e3317f8f13699242452b3916cc1a2bacff78a91c 100644
--- a/gui_qt/.gitignore
+++ b/gui/qt/.gitignore
@@ -7,3 +7,4 @@ binaries*/
 Makefile*
 *.exe
 *.dll
+*.pro.user
diff --git a/gui/qt/CMakeLists.txt b/gui/qt/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7f008f6e32d9e131273e00b1a79bf8aef9ba5f22
--- /dev/null
+++ b/gui/qt/CMakeLists.txt
@@ -0,0 +1,84 @@
+cmake_minimum_required(VERSION 2.8.11)
+
+project(bgslibrary_gui)
+
+if(UNIX)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
+  set(CMAKE_MACOSX_RPATH 1)
+
+  # add some standard warnings
+  ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
+
+  # -ansi does not compile with sjn module
+  #ADD_DEFINITIONS(-ansi)
+
+  # if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
+  #ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
+endif(UNIX)
+
+# Find includes in corresponding build directories
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+if(POLICY CMP0071)
+  cmake_policy(SET CMP0071 NEW)
+endif()
+
+# Instruct CMake to run moc automatically when needed.
+set(CMAKE_AUTOMOC ON)
+
+# Handle the Qt uic code generator automatically
+set(CMAKE_AUTOUIC ON)
+
+# Find the Qt5Widgets library
+find_package(Qt5Widgets)
+# To fix the issue: https://stackoverflow.com/questions/38557755/cmake-cant-seem-to-find-needed-qt-cmake-files-even-though-ive-set-cmake-prefix
+#find_package(Qt5Widgets CONFIG PATHS C:/Qt/5.11.1/msvc2017_64/lib/cmake NO_DEFAULT_PATH)
+if(Qt5Widgets_FOUND)
+  message(STATUS "Qt5Widgets status:")
+  message(STATUS "    version: ${Qt5Widgets_VERSION}")
+  message(STATUS "    libraries: ${Qt5Widgets_LIBRARIES}")
+  message(STATUS "    include path: ${Qt5Widgets_INCLUDE_DIRS}")
+endif()
+
+SET(app_RESOURCES application.qrc)
+QT5_ADD_RESOURCES(app_RESOURCES_RCC ${app_RESOURCES})
+
+# Find the OpenCV library
+set(OpenCV_STATIC OFF)
+find_package(OpenCV REQUIRED)
+if(OpenCV_FOUND)
+  message(STATUS "OpenCV library status:")
+  message(STATUS "    version: ${OpenCV_VERSION}")
+  message(STATUS "    libraries: ${OpenCV_LIBS}")
+  message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
+endif()
+
+file(GLOB main_src *.cpp *.c)
+file(GLOB main_inc *.h *.hpp)
+
+file(GLOB_RECURSE tools_src ../../src/tools/*.cpp ../../src/tools/*.c)
+file(GLOB_RECURSE tools_inc ../../src/tools/*.h ../../src/tools/*.hpp)
+
+file(GLOB_RECURSE utils_src ../../src/utils/*.cpp ../../src/utils/*.c)
+file(GLOB_RECURSE utils_inc ../../src/utils/*.h ../../src/utils/*.hpp)
+
+file(GLOB_RECURSE bgs_src ../../src/algorithms/*.cpp ../../src/algorithms/*.c)
+file(GLOB_RECURSE bgs_inc ../../src/algorithms/*.h)
+
+include_directories(${CMAKE_SOURCE_DIR} ${OpenCV_INCLUDE_DIRS})
+
+add_library(libbgs STATIC ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
+target_link_libraries(libbgs ${OpenCV_LIBS})
+set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc})
+
+if(WIN32)
+  # set_property(TARGET libbgs PROPERTY SUFFIX ".lib")
+else()
+  set_property(TARGET libbgs PROPERTY OUTPUT_NAME "bgs")
+endif()
+
+# Tell CMake to create the bgslibrary_gui executable
+add_executable(bgslibrary_gui ${main_src} ${main_inc} ${app_RESOURCES_RCC})
+
+# Use the Widgets module from Qt 5.
+target_link_libraries(bgslibrary_gui Qt5::Widgets ${OpenCV_LIBS} libbgs)
diff --git a/gui/qt/README.md b/gui/qt/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..29f41ea2145af30e8bfd0bd149161302671da24d
--- /dev/null
+++ b/gui/qt/README.md
@@ -0,0 +1,118 @@
+## BGSLibrary v2.0.0 with QT GUI 
+
+* Download binaries for Windows (x86/x64):
+
+* * Download [bgslibrary2_qtgui_opencv320_x64.zip](https://github.com/andrewssobral/bgslibrary/releases/download/bgslib_qtgui_2.0.0/bgslibrary2_qtgui_opencv320_x64.zip)
+
+* * More info: https://github.com/andrewssobral/bgslibrary/releases/tag/bgslib_qtgui_2.0.0
+
+![BGSLibrary QT GUI](https://sites.google.com/site/andrewssobral/bgslibrary_qt_gui.png "BGSLibrary QT GUI")
+
+## Building QT GUI from scratch
+
+* Dependencies:
+
+* * OpenCV 2.x or 3.x (Tested with OpenCV 3.2.0)
+
+* * Qt 5 library (Tested with Qt 5.6.2)
+
+### On Windows (with CMAKE and Visual Studio 2015 x64)
+
+1) Click on 'Qt 5.6 64-bit for Desktop (MSVC 2015)'
+
+2) Go to **bgslibrary/gui_qt/build** folder.
+
+3) Set your OpenCV PATH:
+```
+set OpenCV_DIR=C:\OpenCV3.2.0\build
+```
+
+4) Launch CMAKE:
+```
+cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 14 Win64" ..
+```
+
+5) Include OpenCV binaries in the system path:
+```
+set PATH=%PATH%;%OpenCV_DIR%\x64\vc14\bin
+```
+
+6) Open the **bgslibrary_gui.sln** file in your Visual Studio and switch to **'RELEASE'** mode 
+
+7) Click on **'ALL_BUILD'** project and build!
+
+8) Go to **bgslibrary/gui_qt/build/Release** and copy **bgslibrary_gui.exe** to **bgslibrary/**.
+
+9) Run **bgslibrary_gui.exe** and enjoy! ;-)
+
+### On Linux or Mac OS X 
+
+* Installing dependencies on Mac OS X:
+```
+brew install opencv3 --with-ffmpeg --with-qt5 --HEAD
+brew link --overwrite --dry-run opencv3
+```
+
+* Step-by-step Instructions
+```
+git clone --recursive https://github.com/andrewssobral/bgslibrary.git
+
+cd bgslibrary/gui_qt/build
+cmake ..
+make
+
+cp bgslibrary_gui ../../ 
+
+./bgslibrary_gui 
+```
+
+
+![BGSLibrary QT GUI](https://sites.google.com/site/andrewssobral/bgslibrary2_qt_gui_osx.png "BGSLibrary QT GUI")
+
+### (Video) Build & Execute BGSLibrary QT GUI on MacOSX using CMake
+
+<p align="center"><a href=https://youtu.be/vl0c-mXWQEo>https://youtu.be/vl0c-mXWQEo</a></p>
+<p align="center">
+<a href="https://youtu.be/vl0c-mXWQEo" target="_blank">
+<img src="https://sites.google.com/site/andrewssobral/bgslib_qtgui_macosx.png?width=600" border="0" />
+</a>
+</p>
+
+
+
+
+* Possible issues:
+
+If you have something like this:
+```
+CMake Warning at CMakeLists.txt:33 (find_package):
+  By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project
+  has asked CMake to find a package configuration file provided by
+  "Qt5Widgets", but CMake did not find one.
+
+  Could not find a package configuration file provided by "Qt5Widgets" with
+  any of the following names:
+
+    Qt5WidgetsConfig.cmake
+    qt5widgets-config.cmake
+
+  Add the installation prefix of "Qt5Widgets" to CMAKE_PREFIX_PATH or set
+  "Qt5Widgets_DIR" to a directory containing one of the above files.  If
+  "Qt5Widgets" provides a separate development package or SDK, be sure it has
+  been installed.
+
+
+CMake Error at CMakeLists.txt:44 (QT5_ADD_RESOURCES):
+  Unknown CMake command "QT5_ADD_RESOURCES".
+
+
+-- Configuring incomplete, errors occurred!
+```
+
+You just need to specify the PATH of your QT installation, for example:
+
+On Linux:
+`cmake .. -DCMAKE_PREFIX_PATH=$HOME/Qt/5.12.1/gcc_64`
+
+On MacOS:
+`cmake .. -DCMAKE_PREFIX_PATH=$HOME/Qt/5.13.0/clang_64`
diff --git a/gui_qt/application.qrc b/gui/qt/application.qrc
similarity index 100%
rename from gui_qt/application.qrc
rename to gui/qt/application.qrc
diff --git a/gui/qt/bgslibrary_gui.cpp b/gui/qt/bgslibrary_gui.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..832c618c8210074299ff9bb28b8a9cbded7a4bc3
--- /dev/null
+++ b/gui/qt/bgslibrary_gui.cpp
@@ -0,0 +1,22 @@
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+  std::cout << "--------------------------------------------" << std::endl;
+  std::cout << "Background Subtraction Library v3.0.0       " << std::endl;
+  std::cout << "https://github.com/andrewssobral/bgslibrary " << std::endl;
+  std::cout << "by:                                         " << std::endl;
+  std::cout << "Andrews Sobral (andrewssobral@gmail.com)    " << std::endl;
+  std::cout << "--------------------------------------------" << std::endl;
+  std::cout << "Using OpenCV version " << CV_VERSION << std::endl;
+
+  QApplication a(argc, argv);
+
+  QCoreApplication::setApplicationName("BGSLibrary");
+  QCoreApplication::setApplicationVersion("3.0.0");
+
+  MainWindow w;
+  w.show();
+
+  return a.exec();
+}
diff --git a/gui/qt/bgslibrary_gui.pro b/gui/qt/bgslibrary_gui.pro
new file mode 100644
index 0000000000000000000000000000000000000000..fd8d7b84a952a9043817b9910fa2be453ae51e6c
--- /dev/null
+++ b/gui/qt/bgslibrary_gui.pro
@@ -0,0 +1,98 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator
+#
+#-------------------------------------------------
+
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = bgslibrary_gui
+TEMPLATE = app
+
+message(Qt version: $$[QT_VERSION])
+message(Qt is installed in $$[QT_INSTALL_PREFIX])
+message(Qt resources can be found in the following locations:)
+message(Documentation: $$[QT_INSTALL_DOCS])
+message(Header files: $$[QT_INSTALL_HEADERS])
+message(Libraries: $$[QT_INSTALL_LIBS])
+message(Binary files (executables): $$[QT_INSTALL_BINS])
+message(Plugins: $$[QT_INSTALL_PLUGINS])
+message(Data files: $$[QT_INSTALL_DATA])
+message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
+message(Settings: $$[QT_INSTALL_SETTINGS])
+message(Examples: $$[QT_INSTALL_EXAMPLES])
+message(Demonstrations: $$[QT_INSTALL_DEMOS])
+
+# https://doc.qt.io/qt-5/qmake-variable-reference.html#config
+CONFIG += c++14
+#CONFIG += no_keywords # Python redefines some qt keywords
+#CONFIG += console
+CONFIG -= app_bundle
+CONFIG += sdk_no_version_check # supress OS warning for 10.14
+#CONFIG += staticlib
+
+# For Windows x64 + Visual Studio 2015 + OpenCV 4.1.1
+win32 {
+  message("Building for Windows")
+  INCLUDEPATH += E:/OpenCV/opencv-4.1.1/build/include
+  release {
+    LIBS += -LE:/OpenCV/opencv-4.1.1/build/x64/vc14/lib -lopencv_world411
+  }
+  debug {
+    LIBS += -LE:/OpenCV/opencv-4.1.1/build/x64/vc14/lib -lopencv_world411d
+  }
+}
+
+# For Linux or MacOS
+unix {
+  macx {
+    message("Building for MacOS")
+    QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
+  } else {
+    message("Building for Linux")
+    #CONFIG += link_pkgconfig
+    #PKGCONFIG += opencv
+  }
+  #pkg-config --cflags --libs opencv
+  INCLUDEPATH += /usr/local/include
+  #INCLUDEPATH += /usr/local/include/opencv
+  INCLUDEPATH += /usr/local/include/opencv2
+  #INCLUDEPATH += /usr/local/include/opencv4
+  LIBS += -L/usr/local/lib
+  #LIBS += -L/usr/local/Cellar/ffmpeg/3.3.3/lib
+  LIBS += -lopencv_core
+  LIBS += -lopencv_imgproc
+  LIBS += -lopencv_imgcodecs
+  LIBS += -lopencv_video
+  LIBS += -lopencv_videoio
+  LIBS += -lopencv_highgui
+  LIBS += -lopencv_features2d
+}
+
+RESOURCES = application.qrc
+
+SOURCES += bgslibrary_gui.cpp\
+    mainwindow.cpp \
+    qt_utils.cpp \
+    texteditor.cpp
+SOURCES += $$files("../../src/algorithms/*.cpp", true)
+SOURCES += $$files("../../src/tools/*.cpp", true)
+SOURCES += $$files("../../src/utils/*.cpp", true)
+
+HEADERS  += mainwindow.h \
+    qt_utils.h \
+    texteditor.h
+HEADERS += $$files("../../src/algorithms/*.h", true)
+HEADERS += $$files("../../src/tools/*.h", true)
+HEADERS += $$files("../../src/utils/*.h", true)
+
+FORMS    += mainwindow.ui
+
+DISTFILES += \
+    ../../src/algorithms/LBSP/LBSP_16bits_dbcross_1ch.i \
+    ../../src/algorithms/LBSP/LBSP_16bits_dbcross_3ch1t.i \
+    ../../src/algorithms/LBSP/LBSP_16bits_dbcross_3ch3t.i \
+    ../../src/algorithms/LBSP/LBSP_16bits_dbcross_s3ch.i \
+    ../../src/algorithms/ViBe/LICENSE
diff --git a/demos/macosx/config/.gitignore b/gui/qt/build/.gitignore
similarity index 83%
rename from demos/macosx/config/.gitignore
rename to gui/qt/build/.gitignore
index 8ee04a01eb210a035d02f190538c5235aebc7277..4e2a98bb114355ae964e78a929c12d44f75815de 100644
--- a/demos/macosx/config/.gitignore
+++ b/gui/qt/build/.gitignore
@@ -1,4 +1,4 @@
 # Ignore everything in this directory
 *
 # Except these files
-!.gitignore
\ No newline at end of file
+!.gitignore
diff --git a/gui_qt/figs/copy.png b/gui/qt/figs/copy.png
similarity index 100%
rename from gui_qt/figs/copy.png
rename to gui/qt/figs/copy.png
diff --git a/gui_qt/figs/cut.png b/gui/qt/figs/cut.png
similarity index 100%
rename from gui_qt/figs/cut.png
rename to gui/qt/figs/cut.png
diff --git a/gui_qt/figs/new.png b/gui/qt/figs/new.png
similarity index 100%
rename from gui_qt/figs/new.png
rename to gui/qt/figs/new.png
diff --git a/gui_qt/figs/open.png b/gui/qt/figs/open.png
similarity index 100%
rename from gui_qt/figs/open.png
rename to gui/qt/figs/open.png
diff --git a/gui_qt/figs/paste.png b/gui/qt/figs/paste.png
similarity index 100%
rename from gui_qt/figs/paste.png
rename to gui/qt/figs/paste.png
diff --git a/gui_qt/figs/save.png b/gui/qt/figs/save.png
similarity index 100%
rename from gui_qt/figs/save.png
rename to gui/qt/figs/save.png
diff --git a/gui_qt/mainwindow.cpp b/gui/qt/mainwindow.cpp
similarity index 92%
rename from gui_qt/mainwindow.cpp
rename to gui/qt/mainwindow.cpp
index bb7eac8c0acbab9f27cfa9ffa59bd3649f0a76a8..c2b7eeeac33798b6b0c0394e17b9e7b2ca2a45e3 100644
--- a/gui_qt/mainwindow.cpp
+++ b/gui/qt/mainwindow.cpp
@@ -1,19 +1,3 @@
-/*
-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 "mainwindow.h"
 #include "ui_mainwindow.h"
 
@@ -37,9 +21,10 @@ namespace bgslibrary
 #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
     map["GMG"] = &createInstance<GMG>; // only for OpenCV >= 2.4.3
 #endif
-#if CV_MAJOR_VERSION == 3
+#if CV_MAJOR_VERSION >= 3
     map["KNN"] = &createInstance<KNN>; // only on OpenCV 3.x
 #endif
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
     map["DPAdaptiveMedian"] = &createInstance<DPAdaptiveMedian>;
     map["DPGrimsonGMM"] = &createInstance<DPGrimsonGMM>;
     map["DPZivkovicAGMM"] = &createInstance<DPZivkovicAGMM>;
@@ -66,12 +51,14 @@ namespace bgslibrary
     map["KDE"] = &createInstance<KDE>;
     map["IndependentMultimodal"] = &createInstance<IndependentMultimodal>;
     map["MultiCue"] = &createInstance<MultiCue>;
+#endif
     map["SigmaDelta"] = &createInstance<SigmaDelta>;
     map["SuBSENSE"] = &createInstance<SuBSENSE>;
     map["LOBSTER"] = &createInstance<LOBSTER>;
     map["PAWCS"] = &createInstance<PAWCS>;
     map["TwoPoints"] = &createInstance<TwoPoints>;
     map["ViBe"] = &createInstance<ViBe>;
+    map["CodeBook"] = &createInstance<CodeBook>;
 
     return map[alg_name]();
   }
@@ -92,9 +79,10 @@ namespace bgslibrary
 #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
     stringList.append("GMG"); // only for OpenCV >= 2.4.3
 #endif
-#if CV_MAJOR_VERSION == 3
+#if CV_MAJOR_VERSION >= 3
     stringList.append("KNN"); // only on OpenCV 3.x
 #endif
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
     stringList.append("DPAdaptiveMedian");
     stringList.append("DPGrimsonGMM");
     stringList.append("DPZivkovicAGMM");
@@ -121,12 +109,14 @@ namespace bgslibrary
     stringList.append("KDE");
     stringList.append("IndependentMultimodal");
     stringList.append("MultiCue");
+#endif
     stringList.append("SigmaDelta");
     stringList.append("SuBSENSE");
     stringList.append("LOBSTER");
     stringList.append("PAWCS");
     stringList.append("TwoPoints");
     stringList.append("ViBe");
+    stringList.append("CodeBook");
     return stringList;
   }
 }
@@ -142,11 +132,13 @@ MainWindow::MainWindow(QWidget *parent) :
   ui->lineEdit_inputdata->setText(fileName);
   //fileName = ui->lineEdit_inputdata->text();
   timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(startCapture()));
-  QStringListModel* listModel = new QStringListModel(bgslibrary::get_algs_name(), NULL);
+  QStringListModel* listModel = new QStringListModel(bgslibrary::get_algs_name(), nullptr);
   listModel->sort(0);
   ui->listView_algorithms->setModel(listModel);
   QModelIndex index = listModel->index(0);
   ui->listView_algorithms->selectionModel()->select(index, QItemSelectionModel::Select);
+  //std::cout << "QDir::currentPath(): " + QDir::currentPath().toStdString() << std::endl;
+  //std::cout << "QCoreApplication::applicationDirPath(): " + QCoreApplication::applicationDirPath().toStdString() << std::endl;
 }
 
 MainWindow::~MainWindow()
@@ -299,7 +291,7 @@ void MainWindow::setFrameNumber(long long _frameNumber)
 {
   //std::cout << "setFrameNumber()" << std::endl;
   frameNumber = _frameNumber;
-  QString txt_frameNumber = QString::fromStdString(its(frameNumber));
+  QString txt_frameNumber = QString::fromStdString(to_string<long long>(frameNumber));
   ui->label_framenumber_txt->setText(txt_frameNumber);
 }
 
@@ -323,12 +315,12 @@ bool MainWindow::setUpCapture()
   }
 
   if (useCamera || useVideo) {
-    int capture_fps = capture.get(CV_CAP_PROP_FPS);
+    int capture_fps = static_cast<int>(capture.get(CV_CAP_PROP_FPS));
     std::cout << "capture_fps: " << capture_fps << std::endl;
   }
 
   if (useVideo) {
-    capture_length = capture.get(CV_CAP_PROP_FRAME_COUNT);
+    capture_length = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_COUNT));
     std::cout << "capture_length: " << capture_length << std::endl;
   }
 
@@ -347,7 +339,7 @@ void MainWindow::startCapture()
 
   if (useSequence && (frameNumber - 1) < entryList.length())
   {
-    QString file = entryList.at(frameNumber - 1);
+    QString file = entryList.at(static_cast<int>(frameNumber - 1));
     QString filePath = QDir(fileName).filePath(file);
 
     std::cout << "Processing: " << filePath.toStdString() << std::endl;
@@ -365,15 +357,15 @@ void MainWindow::startCapture()
   {
     int frame_width = cv_frame.size().width;
     int frame_height = cv_frame.size().height;
-    ui->label_frameresw_txt->setText(QString::fromStdString(its(frame_width)));
-    ui->label_frameresh_txt->setText(QString::fromStdString(its(frame_height)));
+    ui->label_frameresw_txt->setText(QString::fromStdString(to_string<int>(frame_width)));
+    ui->label_frameresh_txt->setText(QString::fromStdString(to_string<int>(frame_height)));
   }
 
   if (useVideo && capture_length > 0)
   {
     double perc = (double(frameNumber) / double(capture_length)) * 100.0;
     //std::cout << "perc: " << perc << std::endl;
-    ui->progressBar->setValue(perc);
+    ui->progressBar->setValue(static_cast<int>(perc));
   }
 
   int startAt = ui->spinBox_startat->value();
@@ -416,7 +408,7 @@ void MainWindow::processFrame(const cv::Mat &cv_frame)
   tic();
   bgs->process(cv_frame, cv_fg, cv_bg);
   toc();
-  ui->label_fps_txt->setText(QString::fromStdString(its(fps())));
+  ui->label_fps_txt->setText(QString::fromStdString(to_string(fps())));
 
   cv::Mat cv_fg_small;
   cv::resize(cv_fg, cv_fg_small, cv::Size(250, 250));
@@ -486,7 +478,8 @@ bool MainWindow::setUpCamera()
 
 bool MainWindow::setUpVideo()
 {
-  std::string videoFileName = fileName.toStdString();
+  //std::string videoFileName = fileName.toStdString();
+  std::string videoFileName = ui->lineEdit_inputdata->text().toStdString();
   std::cout << "Openning: " << videoFileName << std::endl;
   capture.open(videoFileName.c_str());
   return capture.isOpened();
@@ -565,7 +558,7 @@ void MainWindow::on_listView_algorithms_doubleClicked(const QModelIndex &index)
   }
   else
   {
-    QMessageBox::warning(this, "Warning", "XML configuration file not found!\nPlease run the algorithm first!");
+    QMessageBox::warning(this, "Warning", "XML configuration file not found!\nPlease run the algorithm first or create a config folder relative to the executable path.");
     return;
   }
 }
diff --git a/gui_qt/mainwindow.h b/gui/qt/mainwindow.h
similarity index 71%
rename from gui_qt/mainwindow.h
rename to gui/qt/mainwindow.h
index a834882b7bc73683e53f6d0960f26209f82e9961..521a7796dc1782a3cb8e1c244f0b0d949341462b 100644
--- a/gui_qt/mainwindow.h
+++ b/gui/qt/mainwindow.h
@@ -1,19 +1,3 @@
-/*
-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
 
 #include <QApplication>
@@ -31,10 +15,19 @@ along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
 #include <QCollator>
 
 #include <opencv2/opencv.hpp>
+//#include <opencv2/imgproc/types_c.h>
+//#include <opencv2/imgproc/imgproc_c.h>
+//#include <opencv2/highgui/highgui_c.h>
+
+#if  CV_MAJOR_VERSION >= 4
+#define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES
+#define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT
+#define CV_CAP_PROP_FPS cv::CAP_PROP_FPS
+#endif
 
 #include "qt_utils.h"
 #include "texteditor.h"
-#include "../package_bgs/bgslibrary.h"
+#include "../../src/algorithms/algorithms.h"
 
 namespace bgslibrary
 {
@@ -54,7 +47,7 @@ class MainWindow : public QMainWindow
   Q_OBJECT
 
 public:
-  explicit MainWindow(QWidget *parent = 0);
+  explicit MainWindow(QWidget *parent = nullptr);
   ~MainWindow();
 
   private slots:
diff --git a/gui_qt/mainwindow.ui b/gui/qt/mainwindow.ui
similarity index 95%
rename from gui_qt/mainwindow.ui
rename to gui/qt/mainwindow.ui
index 75e9e61a8081a9417d138d40149e10b6f2e5ea00..5f1db75aa2bcb3b6af86cb107863bd61ff5836b6 100644
--- a/gui_qt/mainwindow.ui
+++ b/gui/qt/mainwindow.ui
@@ -82,7 +82,7 @@
    <widget class="QCheckBox" name="checkBox_webcamera">
     <property name="geometry">
      <rect>
-      <x>280</x>
+      <x>590</x>
       <y>60</y>
       <width>131</width>
       <height>20</height>
@@ -95,7 +95,7 @@
    <widget class="QSpinBox" name="spinBox_webcamera">
     <property name="geometry">
      <rect>
-      <x>410</x>
+      <x>720</x>
       <y>60</y>
       <width>42</width>
       <height>20</height>
@@ -105,7 +105,7 @@
    <widget class="QCheckBox" name="checkBox_imageseq">
     <property name="geometry">
      <rect>
-      <x>470</x>
+      <x>770</x>
       <y>60</y>
       <width>151</width>
       <height>20</height>
@@ -600,6 +600,32 @@
      <bool>true</bool>
     </property>
    </widget>
+   <widget class="QLabel" name="label_config">
+    <property name="geometry">
+     <rect>
+      <x>280</x>
+      <y>60</y>
+      <width>91</width>
+      <height>23</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>Config folder</string>
+    </property>
+   </widget>
+   <widget class="QLineEdit" name="lineEdit_config">
+    <property name="geometry">
+     <rect>
+      <x>280</x>
+      <y>90</y>
+      <width>641</width>
+      <height>22</height>
+     </rect>
+    </property>
+    <property name="text">
+     <string>./config</string>
+    </property>
+   </widget>
   </widget>
   <widget class="QMenuBar" name="menuBar">
    <property name="geometry">
@@ -607,7 +633,7 @@
      <x>0</x>
      <y>0</y>
      <width>1070</width>
-     <height>26</height>
+     <height>22</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuBGSLibrary">
diff --git a/gui_qt/qt_utils.cpp b/gui/qt/qt_utils.cpp
similarity index 55%
rename from gui_qt/qt_utils.cpp
rename to gui/qt/qt_utils.cpp
index 2464d7896aa7bc9d72a47cff3971b925feab6f3b..4f9ef4b2042629bc31afba3e5182f0171d4637d7 100644
--- a/gui_qt/qt_utils.cpp
+++ b/gui/qt/qt_utils.cpp
@@ -1,38 +1,23 @@
-/*
-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 "qt_utils.h"
 
 QImage GrayMat2QImage(cv::Mat const& src) {
   cv::Mat temp;
   src.copyTo(temp);
-  QImage dest((const uchar *)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_Indexed8);
+  QImage dest((const uchar *)temp.data, temp.cols, temp.rows, static_cast<int>(temp.step), QImage::Format_Indexed8);
   dest.bits();
   return dest;
 }
+
 QImage Mat2QImage(cv::Mat const& src) {
   cv::Mat temp;
   cvtColor(src, temp, CV_BGR2RGB);
-  QImage dest((const uchar *)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
+  QImage dest((const uchar *)temp.data, temp.cols, temp.rows, static_cast<int>(temp.step), QImage::Format_RGB888);
   dest.bits();
   return dest;
 }
+
 cv::Mat QImage2Mat(QImage const& src) {
-  cv::Mat tmp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
+  cv::Mat tmp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), static_cast<size_t>(src.bytesPerLine()));
   cv::Mat result;
   cvtColor(tmp, result, CV_RGB2BGR);
   return result;
@@ -43,29 +28,38 @@ QString base64_encode(const QString string) {
   ba.append(string);
   return ba.toBase64();
 }
+
 QString base64_decode(const QString string) {
   QByteArray ba;
   ba.append(string);
   return QByteArray::fromBase64(ba);
 }
+
 QString md5_encode(const QString string) {
   QByteArray ba;
   ba.append(string);
   return QString(QCryptographicHash::hash((ba), QCryptographicHash::Md5).toHex());
 }
 
-int sti(const std::string &s) {
+int str2int(const std::string &s) {
   int i;
   std::stringstream ss;
   ss << s;
   ss >> i;
   return i;
 }
-std::string its(int i) {
+
+template<typename T>
+std::string to_string(T t) {
   std::stringstream ss;
-  ss << i;
+  ss << t;
   return ss.str();
 }
+template std::string to_string<double>(double);
+template std::string to_string<int>(int);
+template std::string to_string<size_t>(size_t);
+template std::string to_string<long>(long);
+template std::string to_string<long long>(long long);
 
 bool fileExists(QString path) {
   QFileInfo check_file(path);
diff --git a/gui_qt/qt_utils.h b/gui/qt/qt_utils.h
similarity index 77%
rename from gui_qt/qt_utils.h
rename to gui/qt/qt_utils.h
index 84128c5676e8b969e76c749d85bf750bbd7a2dbf..e690143a867365081fddf30c5287d5c86d265393 100644
--- a/gui_qt/qt_utils.h
+++ b/gui/qt/qt_utils.h
@@ -1,28 +1,15 @@
-/*
-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
 
 #include <sstream>
 #include <string>
+
 #include <QByteArray>
 #include <QImage>
 #include <QCryptographicHash>
 #include <QFileInfo>
+
 #include <opencv2/opencv.hpp>
+#include <opencv2/imgproc/types_c.h>
 
 QImage GrayMat2QImage(cv::Mat const& src);
 QImage Mat2QImage(cv::Mat const& src);
@@ -32,8 +19,10 @@ QString base64_encode(const QString string);
 QString base64_decode(const QString string);
 QString md5_encode(const QString);
 
-int sti(const std::string &s);
-std::string its(int i);
+int str2int(const std::string &s);
+
+template<typename T>
+std::string to_string(T t);
 
 bool fileExists(QString path);
 
diff --git a/gui_qt/texteditor.cpp b/gui/qt/texteditor.cpp
similarity index 93%
rename from gui_qt/texteditor.cpp
rename to gui/qt/texteditor.cpp
index 80f45e118ed842cb231898dbc3128c11ec7f4f8f..57d3b33a55b024965e5402c8cf352e831a0f6e02 100644
--- a/gui_qt/texteditor.cpp
+++ b/gui/qt/texteditor.cpp
@@ -1,20 +1,3 @@
-/*
-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 <QtWidgets>
 
 #include "texteditor.h"
diff --git a/gui_qt/texteditor.h b/gui/qt/texteditor.h
similarity index 57%
rename from gui_qt/texteditor.h
rename to gui/qt/texteditor.h
index c0d5d8f60d1d8a4ed859207f52349cd597a49c9a..c039ab3649e76f8ee494d9f12275dc877a52481f 100644
--- a/gui_qt/texteditor.h
+++ b/gui/qt/texteditor.h
@@ -1,19 +1,3 @@
-/*
-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/>.
-*/
 #ifndef TEXTEDITOR_H
 #define TEXTEDITOR_H
 
diff --git a/gui_qt/ui_mainwindow.h b/gui/qt/ui_mainwindow.h
similarity index 100%
rename from gui_qt/ui_mainwindow.h
rename to gui/qt/ui_mainwindow.h
diff --git a/gui_java/_COPY_bgslibrary.exe_HERE_ b/gui_java/_COPY_bgslibrary.exe_HERE_
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/gui_qt/CMakeLists.txt b/gui_qt/CMakeLists.txt
deleted file mode 100644
index 83c89202c63b6a0c15300ddaa017ef6e10606410..0000000000000000000000000000000000000000
--- a/gui_qt/CMakeLists.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-cmake_minimum_required(VERSION 2.8.11)
-
-project(bgslibrary_gui)
-
-# Find includes in corresponding build directories
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-# Instruct CMake to run moc automatically when needed.
-set(CMAKE_AUTOMOC ON)
-
-# Handle the Qt uic code generator automatically
-set(CMAKE_AUTOUIC ON)
-
-# Find the Qt5Widgets library
-find_package(Qt5Widgets)
-
-SET(app_RESOURCES application.qrc)
-QT5_ADD_RESOURCES(app_RESOURCES_RCC ${app_RESOURCES})
-
-# Find the OpenCV library
-set(OpenCV_STATIC OFF)
-find_package(OpenCV REQUIRED)
-
-message(STATUS "OpenCV library status:")
-message(STATUS "    version: ${OpenCV_VERSION}")
-message(STATUS "    libraries: ${OpenCV_LIBS}")
-message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
-
-file(GLOB main bgslibrary_gui.cpp mainwindow.cpp qt_utils.cpp texteditor.cpp)
-
-file(GLOB_RECURSE analysis_src ../package_analysis/*.cpp)
-file(GLOB_RECURSE analysis_inc ../package_analysis/*.h)
-file(GLOB_RECURSE bgs_src ../package_bgs/*.cpp ../package_bgs/*.c)
-file(GLOB_RECURSE bgs_inc ../package_bgs/*.h)
-
-include_directories(${CMAKE_SOURCE_DIR} ${OpenCV_INCLUDE_DIRS})
-
-add_library(libbgs STATIC ${bgs_src} ${analysis_src})
-target_link_libraries(libbgs ${OpenCV_LIBS})
-set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_inc} ${analysis_inc})
-
-if(WIN32)
-	# set_property(TARGET libbgs PROPERTY SUFFIX ".lib")
-else()
-	set_property(TARGET libbgs PROPERTY OUTPUT_NAME "bgs")
-endif()
-
-# Tell CMake to create the bgslibrary_gui executable
-add_executable(bgslibrary_gui ${main} ${app_RESOURCES_RCC})
-
-# Use the Widgets module from Qt 5.
-target_link_libraries(bgslibrary_gui Qt5::Widgets ${OpenCV_LIBS} libbgs)
diff --git a/gui_qt/README.txt b/gui_qt/README.txt
deleted file mode 100644
index 41a4cd2b1548b7ee189911927559afa2aa58d922..0000000000000000000000000000000000000000
--- a/gui_qt/README.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-#-------------------------------------------------
-#
-# Project created with Qt 5.6.2
-#
-# Compiling BGSLibrary QT GUI with CMAKE
-#
-#-------------------------------------------------
-# Qt 5.x 64-bit for Desktop (MSVC 2015)
-#-------------------------------------------------
-
-mkdir build
-
-cd build
-
-set OpenCV_DIR=C:\OpenCV3.2.0\build
-
-cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 14 Win64" ..
diff --git a/gui_qt/bgslibrary_gui.cpp b/gui_qt/bgslibrary_gui.cpp
deleted file mode 100644
index e886262427295abddf30fd063ed4861a4bd9b16b..0000000000000000000000000000000000000000
--- a/gui_qt/bgslibrary_gui.cpp
+++ /dev/null
@@ -1,38 +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 "mainwindow.h"
-
-int main(int argc, char *argv[])
-{
-  std::cout << "--------------------------------------------" << std::endl;
-  std::cout << "Background Subtraction Library v2.0.0       " << std::endl;
-  std::cout << "https://github.com/andrewssobral/bgslibrary " << std::endl;
-  std::cout << "by:                                         " << std::endl;
-  std::cout << "Andrews Sobral (andrewssobral@gmail.com)    " << std::endl;
-  std::cout << "--------------------------------------------" << std::endl;
-  std::cout << "Using OpenCV version " << CV_VERSION << std::endl;
-
-  QApplication a(argc, argv);
-
-  QCoreApplication::setApplicationName("BGSLibrary");
-  QCoreApplication::setApplicationVersion("2.0.0");
-
-  MainWindow w;
-  w.show();
-
-  return a.exec();
-}
diff --git a/gui_qt/bgslibrary_gui.pro b/gui_qt/bgslibrary_gui.pro
deleted file mode 100644
index feedbf6a8601455aaad465d68842e76928c92a3a..0000000000000000000000000000000000000000
--- a/gui_qt/bgslibrary_gui.pro
+++ /dev/null
@@ -1,248 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator
-#
-#-------------------------------------------------
-
-QT       += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-TARGET = bgslibrary_gui
-TEMPLATE = app
-
-# For Windows x64 + Visual Studio 2015 + OpenCV 3.1.0
-#INCLUDEPATH += C:/OpenCV3.1.0/build/include
-#LIBS += -LC:/OpenCV3.1.0/build/x64/vc14/lib -lopencv_world310
-
-# For Windows x64 + Visual Studio 2015 + OpenCV 3.2.0
-INCLUDEPATH += C:/OpenCV3.2.0/build/include
-LIBS += -LC:/OpenCV3.2.0/build/x64/vc14/lib -lopencv_world320
-
-# For Linux
-# INCLUDEPATH += /usr/local/include/opencv
-# LIBS += -L/usr/local/lib
-
-RESOURCES = application.qrc
-
-SOURCES += bgslibrary_gui.cpp\
-    mainwindow.cpp \
-    qt_utils.cpp \
-    texteditor.cpp \
-    ../package_analysis/ForegroundMaskAnalysis.cpp \
-    ../package_analysis/PerformanceUtils.cpp \
-    ../package_analysis/PixelUtils.cpp \
-    ../package_bgs/_template_/Amber.cpp \
-    ../package_bgs/_template_/MyBGS.cpp \
-    ../package_bgs/dp/AdaptiveMedianBGS.cpp \
-    ../package_bgs/dp/Eigenbackground.cpp \
-    ../package_bgs/dp/Error.cpp \
-    ../package_bgs/dp/GrimsonGMM.cpp \
-    ../package_bgs/dp/Image.cpp \
-    ../package_bgs/dp/MeanBGS.cpp \
-    ../package_bgs/dp/PratiMediodBGS.cpp \
-    ../package_bgs/dp/TextureBGS.cpp \
-    ../package_bgs/dp/WrenGA.cpp \
-    ../package_bgs/dp/ZivkovicAGMM.cpp \
-    ../package_bgs/IMBS/IMBS.cpp \
-    ../package_bgs/KDE/KernelTable.cpp \
-    ../package_bgs/KDE/NPBGmodel.cpp \
-    ../package_bgs/KDE/NPBGSubtractor.cpp \
-    ../package_bgs/lb/BGModel.cpp \
-    ../package_bgs/lb/BGModelFuzzyGauss.cpp \
-    ../package_bgs/lb/BGModelFuzzySom.cpp \
-    ../package_bgs/lb/BGModelGauss.cpp \
-    ../package_bgs/lb/BGModelMog.cpp \
-    ../package_bgs/lb/BGModelSom.cpp \
-    ../package_bgs/LBP_MRF/graph.cpp \
-    ../package_bgs/LBP_MRF/maxflow.cpp \
-    ../package_bgs/LBP_MRF/MEDefs.cpp \
-    ../package_bgs/LBP_MRF/MEHistogram.cpp \
-    ../package_bgs/LBP_MRF/MEImage.cpp \
-    ../package_bgs/LBP_MRF/MotionDetection.cpp \
-    ../package_bgs/LBSP/BackgroundSubtractorLBSP.cpp \
-    ../package_bgs/LBSP/BackgroundSubtractorLBSP_.cpp \
-    ../package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp \
-    ../package_bgs/LBSP/BackgroundSubtractorPAWCS.cpp \
-    ../package_bgs/LBSP/BackgroundSubtractorSuBSENSE.cpp \
-    ../package_bgs/LBSP/LBSP.cpp \
-    ../package_bgs/LBSP/LBSP_.cpp \
-    ../package_bgs/MultiLayer/blob.cpp \
-    ../package_bgs/MultiLayer/BlobExtraction.cpp \
-    ../package_bgs/MultiLayer/BlobResult.cpp \
-    ../package_bgs/MultiLayer/CMultiLayerBGS.cpp \
-    ../package_bgs/MultiLayer/LocalBinaryPattern.cpp \
-    ../package_bgs/PBAS/PBAS.cpp \
-    ../package_bgs/SigmaDelta/sdLaMa091.cpp \
-    ../package_bgs/T2F/FuzzyUtils.cpp \
-    ../package_bgs/T2F/MRF.cpp \
-    ../package_bgs/T2F/T2FGMM.cpp \
-    ../package_bgs/T2F/T2FMRF.cpp \
-    ../package_bgs/TwoPoints/two_points.cpp \
-    ../package_bgs/ViBe/vibe-background-sequential.cpp \
-    ../package_bgs/VuMeter/TBackground.cpp \
-    ../package_bgs/VuMeter/TBackgroundVuMeter.cpp \
-    ../package_bgs/AdaptiveBackgroundLearning.cpp \
-    ../package_bgs/AdaptiveSelectiveBackgroundLearning.cpp \
-    ../package_bgs/DPAdaptiveMedian.cpp \
-    ../package_bgs/DPEigenbackground.cpp \
-    ../package_bgs/DPGrimsonGMM.cpp \
-    ../package_bgs/DPMean.cpp \
-    ../package_bgs/DPPratiMediod.cpp \
-    ../package_bgs/DPTexture.cpp \
-    ../package_bgs/DPWrenGA.cpp \
-    ../package_bgs/DPZivkovicAGMM.cpp \
-    ../package_bgs/FrameDifference.cpp \
-    ../package_bgs/FuzzyChoquetIntegral.cpp \
-    ../package_bgs/FuzzySugenoIntegral.cpp \
-    ../package_bgs/GMG.cpp \
-    ../package_bgs/IndependentMultimodal.cpp \
-    ../package_bgs/KDE.cpp \
-    ../package_bgs/KNN.cpp \
-    ../package_bgs/LBAdaptiveSOM.cpp \
-    ../package_bgs/LBFuzzyAdaptiveSOM.cpp \
-    ../package_bgs/LBFuzzyGaussian.cpp \
-    ../package_bgs/LBMixtureOfGaussians.cpp \
-    ../package_bgs/LBP_MRF.cpp \
-    ../package_bgs/LBSimpleGaussian.cpp \
-    ../package_bgs/LOBSTER.cpp \
-    ../package_bgs/MixtureOfGaussianV1.cpp \
-    ../package_bgs/MixtureOfGaussianV2.cpp \
-    ../package_bgs/MultiCue.cpp \
-    ../package_bgs/MultiLayer.cpp \
-    ../package_bgs/PAWCS.cpp \
-    ../package_bgs/PixelBasedAdaptiveSegmenter.cpp \
-    ../package_bgs/SigmaDelta.cpp \
-    ../package_bgs/StaticFrameDifference.cpp \
-    ../package_bgs/SuBSENSE.cpp \
-    ../package_bgs/T2FGMM_UM.cpp \
-    ../package_bgs/T2FGMM_UV.cpp \
-    ../package_bgs/T2FMRF_UM.cpp \
-    ../package_bgs/T2FMRF_UV.cpp \
-    ../package_bgs/TwoPoints.cpp \
-    ../package_bgs/ViBe.cpp \
-    ../package_bgs/VuMeter.cpp \
-    ../package_bgs/WeightedMovingMean.cpp \
-    ../package_bgs/WeightedMovingVariance.cpp \
-    ../package_bgs/_template_/amber/amber.c
-
-HEADERS  += mainwindow.h \
-    qt_utils.h \
-    texteditor.h \
-    ../package_analysis/ForegroundMaskAnalysis.h \
-    ../package_analysis/PerformanceUtils.h \
-    ../package_analysis/PixelUtils.h \
-    ../package_bgs/_template_/amber/amber.h \
-    ../package_bgs/_template_/Amber.h \
-    ../package_bgs/_template_/MyBGS.h \
-    ../package_bgs/dp/AdaptiveMedianBGS.h \
-    ../package_bgs/dp/Bgs.h \
-    ../package_bgs/dp/BgsParams.h \
-    ../package_bgs/dp/Eigenbackground.h \
-    ../package_bgs/dp/Error.h \
-    ../package_bgs/dp/GrimsonGMM.h \
-    ../package_bgs/dp/Image.h \
-    ../package_bgs/dp/MeanBGS.h \
-    ../package_bgs/dp/PratiMediodBGS.h \
-    ../package_bgs/dp/TextureBGS.h \
-    ../package_bgs/dp/WrenGA.h \
-    ../package_bgs/dp/ZivkovicAGMM.h \
-    ../package_bgs/IMBS/IMBS.hpp \
-    ../package_bgs/KDE/KernelTable.h \
-    ../package_bgs/KDE/NPBGmodel.h \
-    ../package_bgs/KDE/NPBGSubtractor.h \
-    ../package_bgs/lb/BGModel.h \
-    ../package_bgs/lb/BGModelFuzzyGauss.h \
-    ../package_bgs/lb/BGModelFuzzySom.h \
-    ../package_bgs/lb/BGModelGauss.h \
-    ../package_bgs/lb/BGModelMog.h \
-    ../package_bgs/lb/BGModelSom.h \
-    ../package_bgs/lb/Types.h \
-    ../package_bgs/LBP_MRF/block.h \
-    ../package_bgs/LBP_MRF/graph.h \
-    ../package_bgs/LBP_MRF/MEDefs.hpp \
-    ../package_bgs/LBP_MRF/MEHistogram.hpp \
-    ../package_bgs/LBP_MRF/MEImage.hpp \
-    ../package_bgs/LBP_MRF/MotionDetection.hpp \
-    ../package_bgs/LBSP/BackgroundSubtractorLBSP.h \
-    ../package_bgs/LBSP/BackgroundSubtractorLBSP_.h \
-    ../package_bgs/LBSP/BackgroundSubtractorLOBSTER.h \
-    ../package_bgs/LBSP/BackgroundSubtractorPAWCS.h \
-    ../package_bgs/LBSP/BackgroundSubtractorSuBSENSE.h \
-    ../package_bgs/LBSP/DistanceUtils.h \
-    ../package_bgs/LBSP/LBSP.h \
-    ../package_bgs/LBSP/LBSP_.h \
-    ../package_bgs/LBSP/RandUtils.h \
-    ../package_bgs/MultiLayer/BackgroundSubtractionAPI.h \
-    ../package_bgs/MultiLayer/BGS.h \
-    ../package_bgs/MultiLayer/blob.h \
-    ../package_bgs/MultiLayer/BlobExtraction.h \
-    ../package_bgs/MultiLayer/BlobLibraryConfiguration.h \
-    ../package_bgs/MultiLayer/BlobResult.h \
-    ../package_bgs/MultiLayer/CMultiLayerBGS.h \
-    ../package_bgs/MultiLayer/LocalBinaryPattern.h \
-    ../package_bgs/MultiLayer/OpenCvDataConversion.h \
-    ../package_bgs/MultiLayer/OpenCvLegacyIncludes.h \
-    ../package_bgs/PBAS/PBAS.h \
-    ../package_bgs/SigmaDelta/sdLaMa091.h \
-    ../package_bgs/T2F/FuzzyUtils.h \
-    ../package_bgs/T2F/MRF.h \
-    ../package_bgs/T2F/T2FGMM.h \
-    ../package_bgs/T2F/T2FMRF.h \
-    ../package_bgs/TwoPoints/two_points.h \
-    ../package_bgs/ViBe/vibe-background-sequential.h \
-    ../package_bgs/VuMeter/TBackground.h \
-    ../package_bgs/VuMeter/TBackgroundVuMeter.h \
-    ../package_bgs/AdaptiveBackgroundLearning.h \
-    ../package_bgs/AdaptiveSelectiveBackgroundLearning.h \
-    ../package_bgs/bgslibrary.h \
-    ../package_bgs/DPAdaptiveMedian.h \
-    ../package_bgs/DPEigenbackground.h \
-    ../package_bgs/DPGrimsonGMM.h \
-    ../package_bgs/DPMean.h \
-    ../package_bgs/DPPratiMediod.h \
-    ../package_bgs/DPTexture.h \
-    ../package_bgs/DPWrenGA.h \
-    ../package_bgs/DPZivkovicAGMM.h \
-    ../package_bgs/FrameDifference.h \
-    ../package_bgs/FuzzyChoquetIntegral.h \
-    ../package_bgs/FuzzySugenoIntegral.h \
-    ../package_bgs/GMG.h \
-    ../package_bgs/IBGS.h \
-    ../package_bgs/IndependentMultimodal.h \
-    ../package_bgs/KDE.h \
-    ../package_bgs/KNN.h \
-    ../package_bgs/LBAdaptiveSOM.h \
-    ../package_bgs/LBFuzzyAdaptiveSOM.h \
-    ../package_bgs/LBFuzzyGaussian.h \
-    ../package_bgs/LBMixtureOfGaussians.h \
-    ../package_bgs/LBP_MRF.h \
-    ../package_bgs/LBSimpleGaussian.h \
-    ../package_bgs/LOBSTER.h \
-    ../package_bgs/MixtureOfGaussianV1.h \
-    ../package_bgs/MixtureOfGaussianV2.h \
-    ../package_bgs/MultiCue.h \
-    ../package_bgs/MultiLayer.h \
-    ../package_bgs/PAWCS.h \
-    ../package_bgs/PixelBasedAdaptiveSegmenter.h \
-    ../package_bgs/SigmaDelta.h \
-    ../package_bgs/StaticFrameDifference.h \
-    ../package_bgs/SuBSENSE.h \
-    ../package_bgs/T2FGMM_UM.h \
-    ../package_bgs/T2FGMM_UV.h \
-    ../package_bgs/T2FMRF_UM.h \
-    ../package_bgs/T2FMRF_UV.h \
-    ../package_bgs/TwoPoints.h \
-    ../package_bgs/ViBe.h \
-    ../package_bgs/VuMeter.h \
-    ../package_bgs/WeightedMovingMean.h \
-    ../package_bgs/WeightedMovingVariance.h
-
-FORMS    += mainwindow.ui
-
-DISTFILES += \
-    ../package_bgs/LBSP/LBSP_16bits_dbcross_1ch.i \
-    ../package_bgs/LBSP/LBSP_16bits_dbcross_3ch1t.i \
-    ../package_bgs/LBSP/LBSP_16bits_dbcross_3ch3t.i \
-    ../package_bgs/LBSP/LBSP_16bits_dbcross_s3ch.i \
-    ../package_bgs/ViBe/LICENSE
diff --git a/modules/pybind11 b/modules/pybind11
new file mode 160000
index 0000000000000000000000000000000000000000..c9d32a81f40ad540015814edf13b29980c63e39c
--- /dev/null
+++ b/modules/pybind11
@@ -0,0 +1 @@
+Subproject commit c9d32a81f40ad540015814edf13b29980c63e39c
diff --git a/notes b/notes
new file mode 100644
index 0000000000000000000000000000000000000000..07f2a440e74231b8d44966a3fa92679c88b3a6ba
--- /dev/null
+++ b/notes
@@ -0,0 +1,21 @@
+libopencv-core-dev/focal 4.2.0+dfsg-5 amd64
+  development files for libopencv-core4.2
+
+libopencv-core4.2/focal 4.2.0+dfsg-5 amd64
+  computer vision core library
+
+
+
+signal(SIGUSR1, my_handler);
+
+usage:
+bgs_demo -i inputTarFile -a amountOfJpgFiles -c exactCenterConfFile.xml -o outPutPath -p camparameterFile.xml
+
+
+/usr/lib/x86_64-linux-gnu/libopencv_core.so.4.2.0
+
+
+
+
+##################################################################################
+ai libopencv-dev
diff --git a/package_analysis/ForegroundMaskAnalysis.cpp b/package_analysis/ForegroundMaskAnalysis.cpp
deleted file mode 100644
index eddc9088d9e6e62f9f193793f389ed3ab60b236d..0000000000000000000000000000000000000000
--- a/package_analysis/ForegroundMaskAnalysis.cpp
+++ /dev/null
@@ -1,104 +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 "ForegroundMaskAnalysis.h"
-
-namespace bgslibrary
-{
-  ForegroundMaskAnalysis::ForegroundMaskAnalysis() : firstTime(true), showOutput(true), stopAt(0), img_ref_path("")
-  {
-    std::cout << "ForegroundMaskAnalysis()" << std::endl;
-  }
-
-  ForegroundMaskAnalysis::~ForegroundMaskAnalysis()
-  {
-    std::cout << "~ForegroundMaskAnalysis()" << std::endl;
-  }
-
-  void ForegroundMaskAnalysis::process(const long &frameNumber, const std::string &name, const cv::Mat &img_input)
-  {
-    if (img_input.empty())
-      return;
-
-    if (stopAt == 0)
-    {
-      loadConfig();
-
-      if (firstTime)
-        saveConfig();
-    }
-
-    if (stopAt == frameNumber && img_ref_path.empty() == false)
-    {
-      cv::Mat img_ref = cv::imread(img_ref_path, 0);
-
-      if (showOutput)
-        cv::imshow("ForegroundMaskAnalysis", img_ref);
-
-      int rn = cv::countNonZero(img_ref);
-      cv::Mat i;
-      cv::Mat u;
-
-      if (rn > 0)
-      {
-        i = img_input & img_ref;
-        u = img_input | img_ref;
-      }
-      else
-      {
-        i = (~img_input) & (~img_ref);
-        u = (~img_input) | (~img_ref);
-      }
-
-      int in = cv::countNonZero(i);
-      int un = cv::countNonZero(u);
-
-      double s = (((double)in) / ((double)un));
-
-      if (showOutput)
-      {
-        cv::imshow("A^B", i);
-        cv::imshow("AvB", u);
-      }
-
-      std::cout << name << " - Similarity Measure: " << s << " press ENTER to continue" << std::endl;
-
-      cv::waitKey(0);
-    }
-
-    firstTime = false;
-  }
-
-  void ForegroundMaskAnalysis::saveConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/ForegroundMaskAnalysis.xml", 0, CV_STORAGE_WRITE);
-
-    cvWriteInt(fs, "stopAt", stopAt);
-    cvWriteString(fs, "img_ref_path", img_ref_path.c_str());
-
-    cvReleaseFileStorage(&fs);
-  }
-
-  void ForegroundMaskAnalysis::loadConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/ForegroundMaskAnalysis.xml", 0, CV_STORAGE_READ);
-
-    stopAt = cvReadIntByName(fs, 0, "stopAt", 0);
-    img_ref_path = cvReadStringByName(fs, 0, "img_ref_path", "");
-
-    cvReleaseFileStorage(&fs);
-  }
-}
diff --git a/package_analysis/ForegroundMaskAnalysis.h b/package_analysis/ForegroundMaskAnalysis.h
deleted file mode 100644
index a0797d76b8fc4a6fe915fa9457f57ab1e97f880c..0000000000000000000000000000000000000000
--- a/package_analysis/ForegroundMaskAnalysis.h
+++ /dev/null
@@ -1,45 +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
-
-#include <iostream>
-#include <string>
-#include <opencv2/opencv.hpp>
-
-
-namespace bgslibrary
-{
-  class ForegroundMaskAnalysis
-  {
-  private:
-    bool firstTime;
-    bool showOutput;
-
-  public:
-    ForegroundMaskAnalysis();
-    ~ForegroundMaskAnalysis();
-
-    long stopAt;
-    std::string img_ref_path;
-
-    void process(const long &frameNumber, const std::string &name, const cv::Mat &img_input);
-
-  private:
-    void saveConfig();
-    void loadConfig();
-  };
-}
diff --git a/package_analysis/PerformanceUtils.h b/package_analysis/PerformanceUtils.h
deleted file mode 100644
index 4be392f53a1b40fc1096d448809ff7a7919097a8..0000000000000000000000000000000000000000
--- a/package_analysis/PerformanceUtils.h
+++ /dev/null
@@ -1,42 +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
-
-#include <stdio.h>
-#include <fstream>
-#include <opencv2/opencv.hpp>
-
-#include "PixelUtils.h"
-
-class PerformanceUtils
-{
-public:
-  PerformanceUtils(void);
-  ~PerformanceUtils(void);
-
-  float NrPixels(IplImage *image);
-  float NrAllDetectedPixNotNULL(IplImage *image, IplImage *ground_truth);
-  float NrTruePositives(IplImage *image, IplImage *ground_truth, bool debug = false);
-  float NrTrueNegatives(IplImage *image, IplImage *ground_truth, bool debug = false);
-  float NrFalsePositives(IplImage *image, IplImage *ground_truth, bool debug = false);
-  float NrFalseNegatives(IplImage *image, IplImage *ground_truth, bool debug = false);
-  float SimilarityMeasure(IplImage *image, IplImage *ground_truth, bool debug = false);
-
-  void ImageROC(IplImage *image, IplImage* ground_truth, bool saveResults = false, std::string filename = "");
-  void PerformanceEvaluation(IplImage *image, IplImage *ground_truth, bool saveResults = false, std::string filename = "", bool debug = false);
-};
-
diff --git a/package_analysis/PixelUtils.h b/package_analysis/PixelUtils.h
deleted file mode 100644
index 0e35c4055421c76d5bdb0af91fee4c6008b98253..0000000000000000000000000000000000000000
--- a/package_analysis/PixelUtils.h
+++ /dev/null
@@ -1,49 +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
-
-#include <stdio.h>
-#include <opencv2/opencv.hpp>
-
-class PixelUtils
-{
-public:
-  PixelUtils(void);
-  ~PixelUtils(void);
-
-  void ColorConversion(IplImage* RGBImage, IplImage* ConvertedImage, int color_space);
-  void cvttoOTHA(IplImage* RGBImage, IplImage* OthaImage);
-
-  void PostProcessing(IplImage *InputImage);
-
-  void GetPixel(IplImage *image, int m, int n, unsigned char *pixelcourant);
-  void GetGrayPixel(IplImage *image, int m, int n, unsigned char *pixelcourant);
-
-  void PutPixel(IplImage *image, int p, int q, unsigned char *pixelcourant);
-  void PutGrayPixel(IplImage *image, int p, int q, unsigned char pixelcourant);
-
-  void GetPixel(IplImage *image, int m, int n, float *pixelcourant);
-  void GetGrayPixel(IplImage *image, int m, int n, float *pixelcourant);
-
-  void PutPixel(IplImage *image, int p, int q, float *pixelcourant);
-  void PutGrayPixel(IplImage *image, int p, int q, float pixelcourant);
-
-  void getNeighberhoodGrayPixel(IplImage* InputImage, int x, int y, float* neighberPixel);
-  void ForegroundMaximum(IplImage *Foreground, float *Maximum, int n);
-  void ForegroundMinimum(IplImage *Foreground, float *Minimum, int n);
-  void ComplementaryAlphaImageCreation(IplImage *AlphaImage, IplImage *ComplementaryAlphaImage, int n);
-};
diff --git a/package_bgs/AdaptiveBackgroundLearning.cpp b/package_bgs/AdaptiveBackgroundLearning.cpp
deleted file mode 100644
index d2cb8a0ac5fee164454b10b18d2886706987c90c..0000000000000000000000000000000000000000
--- a/package_bgs/AdaptiveBackgroundLearning.cpp
+++ /dev/null
@@ -1,109 +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 "AdaptiveBackgroundLearning.h"
-
-using namespace bgslibrary::algorithms;
-
-AdaptiveBackgroundLearning::AdaptiveBackgroundLearning() :
-  alpha(0.05), limit(-1), counter(0), minVal(0.0), maxVal(1.0),
-  enableThreshold(true), threshold(15)
-{
-  std::cout << "AdaptiveBackgroundLearning()" << std::endl;
-  setup("./config/AdaptiveBackgroundLearning.xml");
-}
-
-AdaptiveBackgroundLearning::~AdaptiveBackgroundLearning()
-{
-  std::cout << "~AdaptiveBackgroundLearning()" << std::endl;
-}
-
-void AdaptiveBackgroundLearning::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_background.empty())
-    img_input.copyTo(img_background);
-
-  cv::Mat img_input_f(img_input.size(), CV_32F);
-  img_input.convertTo(img_input_f, CV_32F, 1. / 255.);
-
-  cv::Mat img_background_f(img_background.size(), CV_32F);
-  img_background.convertTo(img_background_f, CV_32F, 1. / 255.);
-
-  cv::Mat img_diff_f(img_input.size(), CV_32F);
-  cv::absdiff(img_input_f, img_background_f, img_diff_f);
-
-  if ((limit > 0 && limit < counter) || limit == -1)
-  {
-    img_background_f = alpha*img_input_f + (1 - alpha)*img_background_f;
-
-    cv::Mat img_new_background(img_input.size(), CV_8U);
-    img_background_f.convertTo(img_new_background, CV_8U, 255.0 / (maxVal - minVal), -minVal);
-    img_new_background.copyTo(img_background);
-
-    if (limit > 0 && limit < counter)
-      counter++;
-  }
-
-  //cv::Mat img_foreground(img_input.size(), CV_8U);
-  img_diff_f.convertTo(img_foreground, CV_8UC1, 255.0 / (maxVal - minVal), -minVal);
-
-  if (img_foreground.channels() == 3)
-    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
-
-  if (enableThreshold)
-    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("A-Learning FG", img_foreground);
-    cv::imshow("A-Learning BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void AdaptiveBackgroundLearning::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), 0, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "limit", limit);
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void AdaptiveBackgroundLearning::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.05);
-  limit = cvReadIntByName(fs, nullptr, "limit", -1);
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/AdaptiveBackgroundLearning.h b/package_bgs/AdaptiveBackgroundLearning.h
deleted file mode 100644
index 3cfc686296ecdda4f582cbf5e1795032273d23fc..0000000000000000000000000000000000000000
--- a/package_bgs/AdaptiveBackgroundLearning.h
+++ /dev/null
@@ -1,47 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class AdaptiveBackgroundLearning : public IBGS
-    {
-    private:
-      double alpha;
-      long limit;
-      long counter;
-      double minVal;
-      double maxVal;
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      AdaptiveBackgroundLearning();
-      ~AdaptiveBackgroundLearning();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/AdaptiveSelectiveBackgroundLearning.cpp b/package_bgs/AdaptiveSelectiveBackgroundLearning.cpp
deleted file mode 100644
index 2f6f9fe89ba9adf4b595c05cc05a3b5fb3c51985..0000000000000000000000000000000000000000
--- a/package_bgs/AdaptiveSelectiveBackgroundLearning.cpp
+++ /dev/null
@@ -1,130 +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 "AdaptiveSelectiveBackgroundLearning.h"
-
-using namespace bgslibrary::algorithms;
-
-AdaptiveSelectiveBackgroundLearning::AdaptiveSelectiveBackgroundLearning() :
-  alphaLearn(0.05), alphaDetection(0.05), learningFrames(-1), counter(0), minVal(0.0), maxVal(1.0),
-  threshold(15)
-{
-  std::cout << "AdaptiveSelectiveBackgroundLearning()" << std::endl;
-  setup("./config/AdaptiveSelectiveBackgroundLearning.xml");
-}
-
-AdaptiveSelectiveBackgroundLearning::~AdaptiveSelectiveBackgroundLearning()
-{
-  std::cout << "~AdaptiveSelectiveBackgroundLearning()" << std::endl;
-}
-
-void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input_, img_output, img_bgmodel);
-
-  cv::Mat img_input;
-  if (img_input_.channels() == 3)
-    cv::cvtColor(img_input_, img_input, CV_BGR2GRAY);
-  else
-    img_input_.copyTo(img_input);
-
-  if (img_background.empty())
-    img_input.copyTo(img_background);
-
-  cv::Mat img_input_f(img_input.size(), CV_32F);
-  img_input.convertTo(img_input_f, CV_32F, 1. / 255.);
-
-  cv::Mat img_background_f(img_background.size(), CV_32F);
-  img_background.convertTo(img_background_f, CV_32F, 1. / 255.);
-
-  cv::Mat img_diff_f(img_input.size(), CV_32F);
-  cv::absdiff(img_input_f, img_background_f, img_diff_f);
-
-  //cv::Mat img_foreground(img_input.size(), CV_8U);
-  img_diff_f.convertTo(img_foreground, CV_8U, 255.0 / (maxVal - minVal), -minVal);
-
-  cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
-  cv::medianBlur(img_foreground, img_foreground, 3);
-
-  if (learningFrames > 0 && counter <= learningFrames)
-  {
-    //std::cout << "Adaptive update..." << std::endl;
-    // Only Adaptive update of the background model
-    img_background_f = alphaLearn * img_input_f + (1 - alphaLearn) * img_background_f;
-    counter++;
-  }
-  else
-  {
-    //std::cout << "Adaptive and Selective update..." << std::endl;
-    int rows = img_input.rows;
-    int cols = img_input.cols;
-
-    for (int i = 0; i < rows; i++)
-    {
-      for (int j = 0; j < cols; j++)
-      {
-        // Adaptive and Selective update of the background model
-        if (img_foreground.at<uchar>(i, j) == 0)
-        {
-          img_background_f.at<float>(i, j) = alphaDetection * img_input_f.at<float>(i, j) + (1 - alphaDetection) * img_background_f.at<float>(i, j);
-        }
-      }
-    }
-  }
-
-  //cv::Mat img_new_background(img_input.size(), CV_8U);
-  img_background_f.convertTo(img_background, CV_8UC1, 255.0 / (maxVal - minVal), -minVal);
-  //img_new_background.copyTo(img_background);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("AS-Learning FG", img_foreground);
-    cv::imshow("AS-Learning BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void AdaptiveSelectiveBackgroundLearning::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "learningFrames", learningFrames);
-  cvWriteReal(fs, "alphaLearn", alphaLearn);
-  cvWriteReal(fs, "alphaDetection", alphaDetection);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void AdaptiveSelectiveBackgroundLearning::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), 0, CV_STORAGE_READ);
-
-  learningFrames = cvReadIntByName(fs, nullptr, "learningFrames", 90);
-  alphaLearn = cvReadRealByName(fs, nullptr, "alphaLearn", 0.05);
-  alphaDetection = cvReadRealByName(fs, nullptr, "alphaDetection", 0.05);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 25);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/AdaptiveSelectiveBackgroundLearning.h b/package_bgs/AdaptiveSelectiveBackgroundLearning.h
deleted file mode 100644
index 24da44c7e025c848d5761f84eb9a95c6c96e23f5..0000000000000000000000000000000000000000
--- a/package_bgs/AdaptiveSelectiveBackgroundLearning.h
+++ /dev/null
@@ -1,47 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class AdaptiveSelectiveBackgroundLearning : public IBGS
-    {
-    private:
-      double alphaLearn;
-      double alphaDetection;
-      long learningFrames;
-      long counter;
-      double minVal;
-      double maxVal;
-      int threshold;
-
-    public:
-      AdaptiveSelectiveBackgroundLearning();
-      ~AdaptiveSelectiveBackgroundLearning();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPAdaptiveMedian.cpp b/package_bgs/DPAdaptiveMedian.cpp
deleted file mode 100644
index 0885580a9ce809d5d03eb978236722a4ab451bd5..0000000000000000000000000000000000000000
--- a/package_bgs/DPAdaptiveMedian.cpp
+++ /dev/null
@@ -1,110 +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 "DPAdaptiveMedian.h"
-
-using namespace bgslibrary::algorithms;
-
-DPAdaptiveMedian::DPAdaptiveMedian() :
-  frameNumber(0), threshold(40), samplingRate(7), learningFrames(30)
-{
-  std::cout << "DPAdaptiveMedian()" << std::endl;
-  setup("./config/DPAdaptiveMedian.xml");
-}
-
-DPAdaptiveMedian::~DPAdaptiveMedian()
-{
-  std::cout << "~DPAdaptiveMedian()" << std::endl;
-}
-
-void DPAdaptiveMedian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    params.SamplingRate() = samplingRate;
-    params.LearningFrames() = learningFrames;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  //bitwise_not(img_foreground, img_foreground);
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("Adaptive Median FG (McFarlane&Schofield)", img_foreground);
-    cv::imshow("Adaptive Median BG (McFarlane&Schofield)", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPAdaptiveMedian::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "samplingRate", samplingRate);
-  cvWriteInt(fs, "learningFrames", learningFrames);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPAdaptiveMedian::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 40);
-  samplingRate = cvReadIntByName(fs, nullptr, "samplingRate", 7);
-  learningFrames = cvReadIntByName(fs, nullptr, "learningFrames", 30);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPAdaptiveMedian.h b/package_bgs/DPAdaptiveMedian.h
deleted file mode 100644
index 7d2b7fa88bb173e2dc08413660c74a507bf7e0bd..0000000000000000000000000000000000000000
--- a/package_bgs/DPAdaptiveMedian.h
+++ /dev/null
@@ -1,53 +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
-
-#include "IBGS.h"
-#include "dp/AdaptiveMedianBGS.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPAdaptiveMedian : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-      AdaptiveMedianParams params;
-      AdaptiveMedianBGS bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-      int threshold;
-      int samplingRate;
-      int learningFrames;
-
-    public:
-      DPAdaptiveMedian();
-      ~DPAdaptiveMedian();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPEigenbackground.cpp b/package_bgs/DPEigenbackground.cpp
deleted file mode 100644
index 75763cec252faa1ef6a28fa202d201ed93213c65..0000000000000000000000000000000000000000
--- a/package_bgs/DPEigenbackground.cpp
+++ /dev/null
@@ -1,109 +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 "DPEigenbackground.h"
-
-using namespace bgslibrary::algorithms;
-
-DPEigenbackground::DPEigenbackground() :
-  frameNumber(0), threshold(225), historySize(20), embeddedDim(10)
-{
-  std::cout << "DPEigenbackground()" << std::endl;
-  setup("./config/DPEigenbackground.xml");
-}
-
-DPEigenbackground::~DPEigenbackground()
-{
-  std::cout << "~DPEigenbackground()" << std::endl;
-}
-
-void DPEigenbackground::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold; //15*15;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    //params.HistorySize() = 100;
-    params.HistorySize() = historySize;
-    //params.EmbeddedDim() = 20;
-    params.EmbeddedDim() = embeddedDim;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Eigenbackground (Oliver)", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPEigenbackground::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "historySize", historySize);
-  cvWriteInt(fs, "embeddedDim", embeddedDim);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPEigenbackground::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 225);
-  historySize = cvReadIntByName(fs, nullptr, "historySize", 20);
-  embeddedDim = cvReadIntByName(fs, nullptr, "embeddedDim", 10);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPEigenbackground.h b/package_bgs/DPEigenbackground.h
deleted file mode 100644
index f84fee765028a7d1c12e55e44dd1239843b5f159..0000000000000000000000000000000000000000
--- a/package_bgs/DPEigenbackground.h
+++ /dev/null
@@ -1,55 +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
-
-#include "IBGS.h"
-#include "dp/Eigenbackground.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPEigenbackground : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      EigenbackgroundParams params;
-      Eigenbackground bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      int threshold;
-      int historySize;
-      int embeddedDim;
-
-    public:
-      DPEigenbackground();
-      ~DPEigenbackground();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPGrimsonGMM.cpp b/package_bgs/DPGrimsonGMM.cpp
deleted file mode 100644
index c72b4d218303bf796340d5a3b6f5131c4c595860..0000000000000000000000000000000000000000
--- a/package_bgs/DPGrimsonGMM.cpp
+++ /dev/null
@@ -1,108 +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 "DPGrimsonGMM.h"
-
-using namespace bgslibrary::algorithms;
-
-DPGrimsonGMM::DPGrimsonGMM() :
-  frameNumber(0), threshold(9.0), alpha(0.01), gaussians(3)
-{
-  std::cout << "DPGrimsonGMM()" << std::endl;
-  setup("./config/DPGrimsonGMM.xml");
-}
-
-DPGrimsonGMM::~DPGrimsonGMM()
-{
-  std::cout << "~DPGrimsonGMM()" << std::endl;
-}
-
-void DPGrimsonGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold; //3.0f*3.0f;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    //params.Alpha() = 0.001f;
-    params.Alpha() = alpha; //0.01f;
-    params.MaxModes() = gaussians; //3;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("GMM (Grimson)", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPGrimsonGMM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPGrimsonGMM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 9.0);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.01);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPGrimsonGMM.h b/package_bgs/DPGrimsonGMM.h
deleted file mode 100644
index dcc05eb1b3b79c46f207898b0668508670eb6d3d..0000000000000000000000000000000000000000
--- a/package_bgs/DPGrimsonGMM.h
+++ /dev/null
@@ -1,55 +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
-
-#include "IBGS.h"
-#include "dp/GrimsonGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPGrimsonGMM : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      GrimsonParams params;
-      GrimsonGMM bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      int gaussians;
-
-    public:
-      DPGrimsonGMM();
-      ~DPGrimsonGMM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPMean.cpp b/package_bgs/DPMean.cpp
deleted file mode 100644
index 3af1fb644ead27c5597c3bfdbe047c5f6270537e..0000000000000000000000000000000000000000
--- a/package_bgs/DPMean.cpp
+++ /dev/null
@@ -1,108 +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 "DPMean.h"
-
-using namespace bgslibrary::algorithms;
-
-DPMean::DPMean() :
-  frameNumber(0), threshold(2700), alpha(1e-6f), learningFrames(30)
-{
-  std::cout << "DPMean()" << std::endl;
-  setup("./config/DPMean.xml");
-}
-
-DPMean::~DPMean()
-{
-  std::cout << "~DPMean()" << std::endl;
-}
-
-void DPMean::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold; //3*30*30; // 2700
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    //params.Alpha() = 1e-6f;
-    params.Alpha() = alpha;
-    params.LearningFrames() = learningFrames;//30;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Temporal Mean (Donovan Parks)", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPMean::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "learningFrames", learningFrames);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPMean::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 2700);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 1e-6f);
-  learningFrames = cvReadIntByName(fs, nullptr, "learningFrames", 30);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPMean.h b/package_bgs/DPMean.h
deleted file mode 100644
index 60299680675ba0c711055109e2ed59eebde018c5..0000000000000000000000000000000000000000
--- a/package_bgs/DPMean.h
+++ /dev/null
@@ -1,55 +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
-
-#include "IBGS.h"
-#include "dp/MeanBGS.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPMean : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      MeanParams params;
-      MeanBGS bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      int threshold;
-      double alpha;
-      int learningFrames;
-
-    public:
-      DPMean();
-      ~DPMean();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPPratiMediod.cpp b/package_bgs/DPPratiMediod.cpp
deleted file mode 100644
index d1942c53ce2f4fe758ced5f5631239e4f6dff925..0000000000000000000000000000000000000000
--- a/package_bgs/DPPratiMediod.cpp
+++ /dev/null
@@ -1,112 +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 "DPPratiMediod.h"
-
-using namespace bgslibrary::algorithms;
-
-DPPratiMediod::DPPratiMediod() :
-  frameNumber(0), threshold(30), samplingRate(5), historySize(16), weight(5)
-{
-  std::cout << "DPPratiMediod()" << std::endl;
-  setup("./config/DPPratiMediod.xml");
-}
-
-DPPratiMediod::~DPPratiMediod()
-{
-  std::cout << "~DPPratiMediod()" << std::endl;
-}
-
-void DPPratiMediod::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    params.SamplingRate() = samplingRate;
-    params.HistorySize() = historySize;
-    params.Weight() = weight;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("Temporal Median FG (Cucchiara&Calderara)", img_foreground);
-    cv::imshow("Temporal Median BG (Cucchiara&Calderara)", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPPratiMediod::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "samplingRate", samplingRate);
-  cvWriteInt(fs, "historySize", historySize);
-  cvWriteInt(fs, "weight", weight);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPPratiMediod::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 30);
-  samplingRate = cvReadIntByName(fs, nullptr, "samplingRate", 5);
-  historySize = cvReadIntByName(fs, nullptr, "historySize", 16);
-  weight = cvReadIntByName(fs, nullptr, "weight", 5);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPPratiMediod.h b/package_bgs/DPPratiMediod.h
deleted file mode 100644
index d37a77abd018547f519dcd244b96e970a590bdc1..0000000000000000000000000000000000000000
--- a/package_bgs/DPPratiMediod.h
+++ /dev/null
@@ -1,56 +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
-
-#include "IBGS.h"
-#include "dp/PratiMediodBGS.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPPratiMediod : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      PratiParams params;
-      PratiMediodBGS bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      int threshold;
-      int samplingRate;
-      int historySize;
-      int weight;
-
-    public:
-      DPPratiMediod();
-      ~DPPratiMediod();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPTexture.h b/package_bgs/DPTexture.h
deleted file mode 100644
index 3cfdcea4c0bb499c323f4ef6b0cb0e218eaf3fdf..0000000000000000000000000000000000000000
--- a/package_bgs/DPTexture.h
+++ /dev/null
@@ -1,59 +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
-
-#include "IBGS.h"
-#include "dp/TextureBGS.h"
-//#include "ConnectedComponents.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPTexture : public IBGS
-    {
-    private:
-      int width;
-      int height;
-      int size;
-      TextureBGS bgs;
-      IplImage* frame;
-      RgbImage image;
-      BwImage fgMask;
-      BwImage tempMask;
-      TextureArray* bgModel;
-      RgbImage texture;
-      unsigned char* modeArray;
-      TextureHistogram* curTextureHist;
-      //ConnectedComponents cc;
-      //CBlobResult largeBlobs;
-      //IplConvKernel* dilateElement;
-      //IplConvKernel* erodeElement;
-      //bool enableFiltering;
-
-    public:
-      DPTexture();
-      ~DPTexture();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPWrenGA.cpp b/package_bgs/DPWrenGA.cpp
deleted file mode 100644
index 7fc331379d1ef27ea223e43dea6384308aafd503..0000000000000000000000000000000000000000
--- a/package_bgs/DPWrenGA.cpp
+++ /dev/null
@@ -1,107 +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 "DPWrenGA.h"
-
-using namespace bgslibrary::algorithms;
-
-DPWrenGA::DPWrenGA() :
-  frameNumber(0), threshold(12.25f), alpha(0.005f), learningFrames(30)
-{
-  std::cout << "DPWrenGA()" << std::endl;
-  setup("./config/DPWrenGA.xml");
-}
-
-DPWrenGA::~DPWrenGA()
-{
-  std::cout << "~DPWrenGA()" << std::endl;
-}
-
-void DPWrenGA::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold; //3.5f*3.5f;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    params.Alpha() = alpha; //0.005f;
-    params.LearningFrames() = learningFrames; //30;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Gaussian Average (Wren)", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPWrenGA::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "learningFrames", learningFrames);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPWrenGA::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 12.25f);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.005f);
-  learningFrames = cvReadIntByName(fs, nullptr, "learningFrames", 30);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPWrenGA.h b/package_bgs/DPWrenGA.h
deleted file mode 100644
index e4b0b5fffbb22de9dbc1edcbc8d24929576b69fc..0000000000000000000000000000000000000000
--- a/package_bgs/DPWrenGA.h
+++ /dev/null
@@ -1,55 +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
-
-#include "IBGS.h"
-#include "dp/WrenGA.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPWrenGA : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      WrenParams params;
-      WrenGA bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      int learningFrames;
-
-    public:
-      DPWrenGA();
-      ~DPWrenGA();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/DPZivkovicAGMM.cpp b/package_bgs/DPZivkovicAGMM.cpp
deleted file mode 100644
index a5a973514783fdb7791cfdc571c8f0c9630df322..0000000000000000000000000000000000000000
--- a/package_bgs/DPZivkovicAGMM.cpp
+++ /dev/null
@@ -1,107 +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 "DPZivkovicAGMM.h"
-
-using namespace bgslibrary::algorithms;
-
-DPZivkovicAGMM::DPZivkovicAGMM() :
-  frameNumber(0), threshold(25.0f), alpha(0.001f), gaussians(3)
-{
-  std::cout << "DPZivkovicAGMM()" << std::endl;
-  setup("./config/DPZivkovicAGMM.xml");
-}
-
-DPZivkovicAGMM::~DPZivkovicAGMM()
-{
-  std::cout << "~DPZivkovicAGMM()" << std::endl;
-}
-
-void DPZivkovicAGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold; //5.0f*5.0f;
-    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
-    params.Alpha() = alpha; //0.001f;
-    params.MaxModes() = gaussians; //3;
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Gaussian Mixture Model (Zivkovic)", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void DPZivkovicAGMM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void DPZivkovicAGMM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 25.0f);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.001f);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/DPZivkovicAGMM.h b/package_bgs/DPZivkovicAGMM.h
deleted file mode 100644
index f35504bff012f395bfa86ad5b304442fcb2fc08b..0000000000000000000000000000000000000000
--- a/package_bgs/DPZivkovicAGMM.h
+++ /dev/null
@@ -1,55 +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
-
-#include "IBGS.h"
-#include "dp/ZivkovicAGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class DPZivkovicAGMM : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      ZivkovicParams params;
-      ZivkovicAGMM bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      int gaussians;
-
-    public:
-      DPZivkovicAGMM();
-      ~DPZivkovicAGMM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/FrameDifference.cpp b/package_bgs/FrameDifference.cpp
deleted file mode 100644
index 4d5c076ce380ad410f115c678d4b71a0a2ca354a..0000000000000000000000000000000000000000
--- a/package_bgs/FrameDifference.cpp
+++ /dev/null
@@ -1,84 +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 "FrameDifference.h"
-
-using namespace bgslibrary::algorithms;
-
-FrameDifference::FrameDifference() :
-  enableThreshold(true), threshold(15)
-{
-  std::cout << "FrameDifference()" << std::endl;
-  setup("./config/FrameDifference.xml");
-}
-
-FrameDifference::~FrameDifference()
-{
-  std::cout << "~FrameDifference()" << std::endl;
-}
-
-void FrameDifference::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_background.empty())
-  {
-    img_input.copyTo(img_background);
-    return;
-  }
-
-  cv::absdiff(img_background, img_input, img_foreground);
-
-  if (img_foreground.channels() == 3)
-    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
-
-  if (enableThreshold)
-    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Frame Difference", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-
-  img_input.copyTo(img_background);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void FrameDifference::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void FrameDifference::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/FrameDifference.h b/package_bgs/FrameDifference.h
deleted file mode 100644
index 07bed8ed5e36fa42a53e81b95ea9624349f820a6..0000000000000000000000000000000000000000
--- a/package_bgs/FrameDifference.h
+++ /dev/null
@@ -1,43 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class FrameDifference : public IBGS
-    {
-    private:
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      FrameDifference();
-      ~FrameDifference();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
-
diff --git a/package_bgs/FuzzyChoquetIntegral.h b/package_bgs/FuzzyChoquetIntegral.h
deleted file mode 100644
index 25681b0c49f4e86efbd35440410b06ba90c25e81..0000000000000000000000000000000000000000
--- a/package_bgs/FuzzyChoquetIntegral.h
+++ /dev/null
@@ -1,53 +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
-
-#include "IBGS.h"
-#include "T2F/FuzzyUtils.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class FuzzyChoquetIntegral : public IBGS
-    {
-    private:
-      long frameNumber;
-
-      int framesToLearn;
-      double alphaLearn;
-      double alphaUpdate;
-      int colorSpace;
-      int option;
-      bool smooth;
-      double threshold;
-
-      FuzzyUtils fu;
-      cv::Mat img_background_f3;
-
-    public:
-      FuzzyChoquetIntegral();
-      ~FuzzyChoquetIntegral();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/FuzzySugenoIntegral.h b/package_bgs/FuzzySugenoIntegral.h
deleted file mode 100644
index 70bde1591ea4338b1955edf81e72d4089e1d7342..0000000000000000000000000000000000000000
--- a/package_bgs/FuzzySugenoIntegral.h
+++ /dev/null
@@ -1,53 +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
-
-#include "IBGS.h"
-#include "T2F/FuzzyUtils.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class FuzzySugenoIntegral : public IBGS
-    {
-    private:
-      long long frameNumber;
-
-      int framesToLearn;
-      double alphaLearn;
-      double alphaUpdate;
-      int colorSpace;
-      int option;
-      bool smooth;
-      double threshold;
-
-      FuzzyUtils fu;
-      cv::Mat img_background_f3;
-
-    public:
-      FuzzySugenoIntegral();
-      ~FuzzySugenoIntegral();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/GMG.cpp b/package_bgs/GMG.cpp
deleted file mode 100644
index 19bd8abbbf858a3c9d893e03f7a34dc7f557ebb0..0000000000000000000000000000000000000000
--- a/package_bgs/GMG.cpp
+++ /dev/null
@@ -1,98 +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 "GMG.h"
-
-#if CV_MAJOR_VERSION == 2
-
-using namespace bgslibrary::algorithms;
-
-GMG::GMG() : initializationFrames(20), decisionThreshold(0.7)
-{
-  std::cout << "GMG()" << std::endl;
-  setup("./config/GMG.xml");
-
-  cv::initModule_video();
-  cv::setUseOptimized(true);
-  cv::setNumThreads(8);
-
-  fgbg = cv::Algorithm::create<cv::BackgroundSubtractorGMG>("BackgroundSubtractor.GMG");
-}
-
-GMG::~GMG()
-{
-  std::cout << "~GMG()" << std::endl;
-}
-
-void GMG::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    fgbg->set("initializationFrames", initializationFrames);
-    fgbg->set("decisionThreshold", decisionThreshold);
-  }
-
-  if (fgbg.empty())
-  {
-    std::cerr << "Failed to create BackgroundSubtractor.GMG Algorithm." << std::endl;
-    return;
-  }
-
-  (*fgbg)(img_input, img_foreground);
-  (*fgbg).getBackgroundImage(img_background);
-
-  img_input.copyTo(img_segmentation);
-  cv::add(img_input, cv::Scalar(100, 100, 0), img_segmentation, img_foreground);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("GMG FG (Godbehere-Matsukawa-Goldberg)", img_foreground);
-    cv::imshow("GMG BG (Godbehere-Matsukawa-Goldberg)", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void GMG::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "initializationFrames", initializationFrames);
-  cvWriteReal(fs, "decisionThreshold", decisionThreshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void GMG::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  initializationFrames = cvReadIntByName(fs, nullptr, "initializationFrames", 20);
-  decisionThreshold = cvReadRealByName(fs, nullptr, "decisionThreshold", 0.7);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
-
-#endif
diff --git a/package_bgs/GMG.h b/package_bgs/GMG.h
deleted file mode 100644
index 1b4af30b234f954ee80d5fa8554b0e945ba21976..0000000000000000000000000000000000000000
--- a/package_bgs/GMG.h
+++ /dev/null
@@ -1,49 +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
-
-#include "opencv2/core/version.hpp"
-#if CV_MAJOR_VERSION == 2
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class GMG : public IBGS
-    {
-    private:
-      cv::Ptr<cv::BackgroundSubtractorGMG> fgbg;
-      int initializationFrames;
-      double decisionThreshold;
-      cv::Mat img_segmentation;
-
-    public:
-      GMG();
-      ~GMG();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
-
-#endif
diff --git a/package_bgs/IBGS.h b/package_bgs/IBGS.h
deleted file mode 100644
index 718bf51ed20d35865d420c46aaa867cd446dcb2d..0000000000000000000000000000000000000000
--- a/package_bgs/IBGS.h
+++ /dev/null
@@ -1,74 +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
-
-#include <iostream>
-#include <fstream>
-#include <opencv2/opencv.hpp>
-
-namespace bgslibrary
-{
-	namespace algorithms
-	{
-		class IBGS
-		{
-		public:
-			void setShowOutput(const bool _showOutput) {
-				showOutput = _showOutput;
-			}
-			cv::Mat apply(const cv::Mat &img_input) {
-				setShowOutput(false);
-				cv::Mat _img_foreground;
-				cv::Mat _img_background;
-				process(img_input, _img_foreground, _img_background);
-        _img_background.copyTo(img_background);
-				return _img_foreground;
-			}
-			cv::Mat getBackgroundModel() {
-				return img_background;
-			}
-			virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground, cv::Mat &img_background) = 0;
-			virtual ~IBGS() {}
-
-		protected:
-			bool firstTime = true;
-			bool showOutput = true;
-			cv::Mat img_background;
-			cv::Mat img_foreground;
-			std::string config_xml;
-			void setup(const std::string _config_xml) {
-				config_xml = _config_xml;
-				if (!config_xml.empty()) {
-					if (!std::ifstream(config_xml))
-						saveConfig();
-					loadConfig();
-				}
-			}
-			void init(const cv::Mat &img_input, cv::Mat &img_outfg, cv::Mat &img_outbg) {
-				assert(img_input.empty() == false);
-				//img_outfg = cv::Mat::zeros(img_input.size(), img_input.type());
-				//img_outbg = cv::Mat::zeros(img_input.size(), img_input.type());
-				img_outfg = cv::Mat::zeros(img_input.size(), CV_8UC1);
-				img_outbg = cv::Mat::zeros(img_input.size(), CV_8UC3);
-			}
-
-		private:
-			virtual void saveConfig() = 0;
-			virtual void loadConfig() = 0;
-		};
-	}
-}
diff --git a/package_bgs/IMBS/IMBS.hpp b/package_bgs/IMBS/IMBS.hpp
deleted file mode 100644
index 383e0ae27bdfc4b3a15dc703331b943f06d4c47f..0000000000000000000000000000000000000000
--- a/package_bgs/IMBS/IMBS.hpp
+++ /dev/null
@@ -1,190 +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/>.
-*/
-/*
-*  IMBS Background Subtraction Library
-*
-*  This file imbs.hpp contains the C++ OpenCV based implementation for
-*  IMBS algorithm described in
-*  D. D. Bloisi and L. Iocchi
-*  "Independent Multimodal Background Subtraction"
-*  In Proc. of the Third Int. Conf. on Computational Modeling of Objects
-*  Presented in Images: Fundamentals, Methods and Applications, pp. 39-44, 2012.
-*  Please, cite the above paper if you use IMBS.
-*
-*  This software is provided without any warranty about its usability.
-*  It is for educational purposes and should be regarded as such.
-*
-*  Written by Domenico D. Bloisi
-*
-*  Please, report suggestions/comments/bugs to
-*  domenico.bloisi@gmail.com
-*
-*/
-#pragma once
-
-//OPENCV
-#include <opencv2/core/core.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/features2d/features2d.hpp>
-//C++
-#include <iostream>
-#include <vector>
-
-using namespace cv;
-using namespace std;
-
-class BackgroundSubtractorIMBS
-{
-public:
-  //! the default constructor
-  BackgroundSubtractorIMBS();
-  //! the full constructor
-  BackgroundSubtractorIMBS(double fps,
-    unsigned int fgThreshold = 15,
-    unsigned int associationThreshold = 5,
-    double samplingPeriod = 500.,
-    unsigned int minBinHeight = 2,
-    unsigned int numSamples = 30,
-    double alpha = 0.65,
-    double beta = 1.15,
-    double tau_s = 60.,
-    double tau_h = 40.,
-    double minArea = 30.,
-    double persistencePeriod = 10000.,
-    bool morphologicalFiltering = false
-  );
-  //! the destructor
-  ~BackgroundSubtractorIMBS();
-  //! the update operator
-  void apply(InputArray image, OutputArray fgmask, double learningRate = -1.);
-
-  //! computes a background image which shows only the highest bin for each pixel
-  void getBackgroundImage(OutputArray backgroundImage) const;
-
-  //! re-initiaization method
-  void initialize(Size frameSize, int frameType);
-
-private:
-  //method for creating the background model
-  void createBg(unsigned int bg_sample_number);
-  //method for updating the background model
-  void updateBg();
-  //method for computing the foreground mask
-  void getFg();
-  //method for suppressing shadows and highlights
-  void hsvSuppression();
-  //method for refining foreground mask
-  void filterFg();
-  //method for filtering out blobs smaller than a given area
-  void areaThresholding();
-  //method for getting the current time
-  double getTimestamp();
-  //method for converting from RGB to HSV
-  Mat convertImageRGBtoHSV(const Mat& imageRGB);
-  //method for changing the bg in case of sudden changes
-  void changeBg();
-
-  //current input RGB frame
-  Mat frame;
-  vector<Mat> frameBGR;
-  //frame size
-  Size frameSize;
-  //frame type
-  int frameType;
-  //total number of pixels in frame
-  unsigned int numPixels;
-  //current background sample
-  Mat bgSample;
-  vector<Mat> bgSampleBGR;
-  //current background image which shows only the highest bin for each pixel
-  //(just for displaying purposes)
-  Mat bgImage;
-  //current foreground mask
-  Mat fgmask;
-
-  Mat fgfiltered;
-
-  //number of fps
-  double fps;
-  //time stamp in milliseconds (ms)
-  double timestamp;
-  //previous time stamp in milliseconds (ms)
-  double prev_timestamp;
-  double initial_tick_count;
-  //initial message to be shown until the first bg model is ready
-  Mat initialMsgGray;
-  Mat initialMsgRGB;
-
-  //struct for modeling the background values for a single pixel
-  typedef struct {
-    Vec3b* binValues;
-    uchar* binHeights;
-    bool* isFg;
-  } Bins;
-
-  Bins* bgBins;
-public:
-  //struct for modeling the background values for the entire frame
-  typedef struct {
-    Vec3b* values;
-    bool* isValid;
-    bool* isFg;
-    uchar* counter;
-  } BgModel;
-private:
-  BgModel* bgModel;
-
-  //SHADOW SUPPRESSION PARAMETERS
-  float alpha;
-  float beta;
-  uchar tau_s;
-  uchar tau_h;
-
-  unsigned int minBinHeight;
-  unsigned int numSamples;
-  unsigned int samplingPeriod;
-  unsigned long prev_bg_frame_time;
-  unsigned int bg_frame_counter;
-  unsigned int associationThreshold;
-  unsigned int maxBgBins;
-  unsigned int nframes;
-
-  double minArea;
-  bool bg_reset;
-  unsigned int persistencePeriod;
-  bool prev_area;
-  bool sudden_change;
-  unsigned int fgThreshold;
-  uchar SHADOW_LABEL;
-  uchar PERSISTENCE_LABEL;
-  uchar FOREGROUND_LABEL;
-  //persistence map
-  unsigned int* persistenceMap;
-  Mat persistenceImage;
-
-  bool morphologicalFiltering;
-
-public:
-  unsigned int getMaxBgBins() {
-    return maxBgBins;
-  }
-  unsigned int getFgThreshold() {
-    return fgThreshold;
-  }
-  void getBgModel(BgModel bgModel_copy[], int size);
-};
diff --git a/package_bgs/IndependentMultimodal.cpp b/package_bgs/IndependentMultimodal.cpp
deleted file mode 100644
index 7b4de4cc06f06b84a7d8d72050cbccf497b0ca9a..0000000000000000000000000000000000000000
--- a/package_bgs/IndependentMultimodal.cpp
+++ /dev/null
@@ -1,74 +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 "IndependentMultimodal.h"
-
-using namespace bgslibrary::algorithms;
-
-IndependentMultimodal::IndependentMultimodal() : fps(10)
-{
-  std::cout << "IndependentMultimodal()" << std::endl;
-  pIMBS = new BackgroundSubtractorIMBS(fps);
-  setup("./config/IndependentMultimodal.xml");
-}
-
-IndependentMultimodal::~IndependentMultimodal()
-{
-  std::cout << "~IndependentMultimodal()" << std::endl;
-  delete pIMBS;
-}
-
-void IndependentMultimodal::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  //get the fgmask and update the background model
-  pIMBS->apply(img_input, img_foreground);
-
-  //get background image
-  pIMBS->getBackgroundImage(img_background);
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("IMBS FG", img_foreground);
-    cv::imshow("IMBS BG", img_background);
-  }
-#endif
-
-  firstTime = false;
-}
-
-void IndependentMultimodal::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void IndependentMultimodal::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/IndependentMultimodal.h b/package_bgs/IndependentMultimodal.h
deleted file mode 100644
index 4e2e3a38e4e71bf65e729e91f3c27717e07e48eb..0000000000000000000000000000000000000000
--- a/package_bgs/IndependentMultimodal.h
+++ /dev/null
@@ -1,43 +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
-
-#include "IBGS.h"
-#include "IMBS/IMBS.hpp"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class IndependentMultimodal : public IBGS
-    {
-    private:
-      BackgroundSubtractorIMBS* pIMBS;
-      int fps;
-
-    public:
-      IndependentMultimodal();
-      ~IndependentMultimodal();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/KDE.cpp b/package_bgs/KDE.cpp
deleted file mode 100644
index 28564a0c4be11c2d76c89082e2198f6ca2bedeca..0000000000000000000000000000000000000000
--- a/package_bgs/KDE.cpp
+++ /dev/null
@@ -1,133 +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 "KDE.h"
-
-using namespace bgslibrary::algorithms;
-
-KDE::KDE() :
-  SequenceLength(50), TimeWindowSize(100), SDEstimationFlag(1), lUseColorRatiosFlag(1),
-  th(10e-8), alpha(0.3), framesToLearn(10), frameNumber(0)
-{
-  p = new NPBGSubtractor;
-  std::cout << "KDE()" << std::endl;
-  setup("./config/KDE.xml");
-}
-
-KDE::~KDE()
-{
-  delete FGImage;
-  delete p;
-  std::cout << "~KDE()" << std::endl;
-}
-
-void KDE::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    rows = img_input.size().height;
-    cols = img_input.size().width;
-    color_channels = img_input.channels();
-
-    // SequenceLength: number of samples for each pixel.
-    // TimeWindowSize: Time window for sampling. for example in the call above, the bg will sample 50 points out of 100 frames.
-    // this rate will affect how fast the model adapt.
-    // SDEstimationFlag: True means to estimate suitable kernel bandwidth to each pixel, False uses a default value.
-    // lUseColorRatiosFlag: True means use normalized RGB for color (recommended.)
-    p->Intialize(rows, cols, color_channels, SequenceLength, TimeWindowSize, SDEstimationFlag, lUseColorRatiosFlag);
-    // th: 0-1 is the probability threshold for a pixel to be a foregroud. typically make it small as 10e-8. the smaller the value the less false positive and more false negative.
-    // alpha: 0-1, for color. typically set to 0.3. this affect shadow suppression.
-    p->SetThresholds(th, alpha);
-
-    FGImage = new unsigned char[rows*cols];
-    //FilteredFGImage = new unsigned char[rows*cols];
-    FilteredFGImage = 0;
-    DisplayBuffers = 0;
-
-    img_foreground = cv::Mat::zeros(img_input.size(), CV_8UC1);
-    img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-    frameNumber = 0;
-    firstTime = false;
-  }
-
-  // Stores the first N frames to build the background model
-  if (frameNumber < framesToLearn)
-  {
-    p->AddFrame(img_input.data);
-    frameNumber++;
-  }
-  else
-  {
-    // Build the background model with first 10 frames
-    if (frameNumber == framesToLearn)
-    {
-      p->Estimation();
-      frameNumber++;
-    }
-
-    // Now, we can subtract the background
-    ((NPBGSubtractor*)p)->NBBGSubtraction(img_input.data, FGImage, FilteredFGImage, DisplayBuffers);
-
-    // At each frame also you can call the update function to adapt the bg
-    // here you pass a mask where pixels with true value will be masked out of the update.
-    ((NPBGSubtractor*)p)->Update(FGImage);
-
-    img_foreground.data = FGImage;
-  }
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("KDE", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-}
-
-void KDE::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "framesToLearn", framesToLearn);
-  cvWriteInt(fs, "SequenceLength", SequenceLength);
-  cvWriteInt(fs, "TimeWindowSize", TimeWindowSize);
-  cvWriteInt(fs, "SDEstimationFlag", SDEstimationFlag);
-  cvWriteInt(fs, "lUseColorRatiosFlag", lUseColorRatiosFlag);
-  cvWriteReal(fs, "th", th);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void KDE::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  framesToLearn = cvReadIntByName(fs, nullptr, "framesToLearn", 10);
-  SequenceLength = cvReadIntByName(fs, nullptr, "SequenceLength", 50);
-  TimeWindowSize = cvReadIntByName(fs, nullptr, "TimeWindowSize", 100);
-  SDEstimationFlag = cvReadIntByName(fs, nullptr, "SDEstimationFlag", 1);
-  lUseColorRatiosFlag = cvReadIntByName(fs, nullptr, "lUseColorRatiosFlag", 1);
-  th = cvReadRealByName(fs, nullptr, "th", 10e-8);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/KDE.h b/package_bgs/KDE.h
deleted file mode 100644
index e77996fd485456e1fce78df60697bf6254cacd3b..0000000000000000000000000000000000000000
--- a/package_bgs/KDE.h
+++ /dev/null
@@ -1,57 +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
-
-#include "IBGS.h"
-#include "KDE/NPBGSubtractor.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class KDE : public IBGS
-    {
-    private:
-      NPBGSubtractor *p;
-      int rows;
-      int cols;
-      int color_channels;
-      int SequenceLength;
-      int TimeWindowSize;
-      int SDEstimationFlag;
-      int lUseColorRatiosFlag;
-      double th;
-      double alpha;
-      int framesToLearn;
-      int frameNumber;
-
-      unsigned char *FGImage;
-      unsigned char *FilteredFGImage;
-      unsigned char **DisplayBuffers;
-
-    public:
-      KDE();
-      ~KDE();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/KDE/KernelTable.cpp b/package_bgs/KDE/KernelTable.cpp
deleted file mode 100644
index bd9c3685c0cf1aa6866eebb6cfcd9f0e5fa0df99..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/KernelTable.cpp
+++ /dev/null
@@ -1,116 +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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-
-#include "KernelTable.h"
-#include <math.h>
-
-#define PI 3.14159
-
-KernelLUTable::KernelLUTable()
-{
-  std::cout << "KernelLUTable()" << std::endl;
-}
-
-KernelLUTable::~KernelLUTable()
-{
-  delete kerneltable;
-  delete kernelsums;
-  std::cout << "~KernelLUTable()" << std::endl;
-}
-
-KernelLUTable::KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmamax, int Segmabins)
-{
-  std::cout << "KernelLUTable()" << std::endl;
-
-  double C1, C2, v, segma, sum;
-  int bin, b;
-
-  minsegma = Segmamin;
-  maxsegma = Segmamax;
-  segmabins = Segmabins;
-  tablehalfwidth = KernelHalfWidth;
-
-  // Generate the Kernel
-
-  // allocate memory for the Kernal Table
-  kerneltable = new double[segmabins*(2 * KernelHalfWidth + 1)];
-  kernelsums = new double[segmabins];
-
-  double segmastep = (maxsegma - minsegma) / segmabins;
-  double y;
-
-  for (segma = minsegma, bin = 0; bin < segmabins; segma += segmastep, bin++)
-  {
-    C1 = 1 / (sqrt(2 * PI)*segma);
-    C2 = -1 / (2 * segma*segma);
-
-    b = (2 * KernelHalfWidth + 1)*bin;
-    sum = 0;
-
-    for (int x = 0; x <= KernelHalfWidth; x++)
-    {
-      y = x / 1.0;
-      v = C1*exp(C2*y*y);
-      kerneltable[b + KernelHalfWidth + x] = v;
-      kerneltable[b + KernelHalfWidth - x] = v;
-      sum += 2 * v;
-    }
-
-    sum -= C1;
-
-    kernelsums[bin] = sum;
-
-    // Normailization
-    for (int x = 0; x <= KernelHalfWidth; x++)
-    {
-      v = kerneltable[b + KernelHalfWidth + x] / sum;
-      kerneltable[b + KernelHalfWidth + x] = v;
-      kerneltable[b + KernelHalfWidth - x] = v;
-    }
-  }
-}
diff --git a/package_bgs/KDE/KernelTable.h b/package_bgs/KDE/KernelTable.h
deleted file mode 100644
index 63a20dcdcf257f133abd4403e2fb1dc81618facc..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/KernelTable.h
+++ /dev/null
@@ -1,67 +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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-#pragma once
-
-#include <iostream>
-
-class KernelLUTable
-{
-public:
-  double minsegma;
-  double maxsegma;
-  int segmabins;
-  int tablehalfwidth;
-  double *kerneltable;
-  double *kernelsums;
-
-public:
-  KernelLUTable();
-  ~KernelLUTable();
-
-  KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmamax, int Segmabins);
-};
diff --git a/package_bgs/KDE/NPBGSubtractor.cpp b/package_bgs/KDE/NPBGSubtractor.cpp
deleted file mode 100644
index 5f004b9f1f2cb77fc80b6f3bade41f026ff17cad..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/NPBGSubtractor.cpp
+++ /dev/null
@@ -1,1160 +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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-
-// NPBGSubtractor.cpp: implementation of the NPBGSubtractor class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#include "NPBGSubtractor.h"
-#include <assert.h>
-#include <math.h>
-#include <string.h>
-
-//#ifdef _DEBUG
-//#undef THIS_FILE
-//static char THIS_FILE[]=__FILE__;
-//#define new DEBUG_NEW
-//#endif
-
-void BGR2SnGnRn(unsigned char * in_image,
-  unsigned char * out_image,
-  unsigned int rows,
-  unsigned int cols)
-{
-  unsigned int i;
-  unsigned int r2, r3;
-  unsigned int r, g, b;
-  double s;
-
-  for (i = 0; i < rows*cols * 3; i += 3)
-  {
-    b = in_image[i];
-    g = in_image[i + 1];
-    r = in_image[i + 2];
-
-    // calculate color ratios
-    s = (double)255 / (double)(b + g + r + 30);
-
-    r2 = (unsigned int)((g + 10) * s);
-    r3 = (unsigned int)((r + 10) * s);
-
-    out_image[i] = (unsigned char)(((unsigned int)b + g + r) / 3);
-    out_image[i + 1] = (unsigned char)(r2 > 255 ? 255 : r2);
-    out_image[i + 2] = (unsigned char)(r3 > 255 ? 255 : r3);
-  }
-}
-
-void UpdateDiffHist(unsigned char * image1, unsigned char * image2, DynamicMedianHistogram * pHist)
-{
-  unsigned int j;
-  int bin, diff;
-
-  unsigned int  imagesize = pHist->imagesize;
-  unsigned char histbins = pHist->histbins;
-  unsigned char *pAbsDiffHist = pHist->Hist;
-
-  int histbins_1 = histbins - 1;
-
-  for (j = 0; j < imagesize; j++)
-  {
-    diff = (int)image1[j] - (int)image2[j];
-    diff = abs(diff);
-    // update histogram
-    bin = (diff < histbins ? diff : histbins_1);
-    pAbsDiffHist[j*histbins + bin]++;
-  }
-}
-
-void FindHistMedians(DynamicMedianHistogram * pAbsDiffHist)
-{
-  unsigned char * Hist = pAbsDiffHist->Hist;
-  unsigned char * MedianBins = pAbsDiffHist->MedianBins;
-  unsigned char * AccSum = pAbsDiffHist->AccSum;
-  unsigned char histsum = pAbsDiffHist->histsum;
-  unsigned char histbins = pAbsDiffHist->histbins;
-  unsigned int imagesize = pAbsDiffHist->imagesize;
-
-  int sum;
-  int bin;
-  unsigned int histindex;
-  unsigned char medianCount = histsum / 2;
-  unsigned int j;
-
-  // find medians
-  for (j = 0; j < imagesize; j++)
-  {
-    // find the median
-    bin = 0;
-    sum = 0;
-
-    histindex = j*histbins;
-
-    while (sum < medianCount)
-    {
-      sum += Hist[histindex + bin];
-      bin++;
-    }
-
-    bin--;
-
-    MedianBins[j] = bin;
-    AccSum[j] = sum;
-  }
-}
-
-DynamicMedianHistogram BuildAbsDiffHist(unsigned char * pSequence,
-  unsigned int rows,
-  unsigned int cols,
-  unsigned int color_channels,
-  unsigned int SequenceLength,
-  unsigned int histbins)
-{
-
-  unsigned int imagesize = rows*cols*color_channels;
-  unsigned int i;
-
-  DynamicMedianHistogram Hist;
-
-  unsigned char *pAbsDiffHist = new unsigned char[rows*cols*color_channels*histbins];
-  unsigned char *pMedianBins = new unsigned char[rows*cols*color_channels];
-  unsigned char *pMedianFreq = new unsigned char[rows*cols*color_channels];
-  unsigned char *pAccSum = new unsigned char[rows*cols*color_channels];
-
-  memset(pAbsDiffHist, 0, rows*cols*color_channels*histbins);
-
-  Hist.Hist = pAbsDiffHist;
-  Hist.MedianBins = pMedianBins;
-  Hist.MedianFreq = pMedianFreq;
-  Hist.AccSum = pAccSum;
-  Hist.histbins = histbins;
-  Hist.imagesize = rows*cols*color_channels;
-  Hist.histsum = SequenceLength - 1;
-
-  unsigned char *image1, *image2;
-  for (i = 1; i < SequenceLength; i++)
-  {
-    // find diff between frame i,i-1;
-    image1 = pSequence + (i - 1)*imagesize;
-    image2 = pSequence + (i)*imagesize;
-
-    UpdateDiffHist(image1, image2, &Hist);
-  }
-
-  FindHistMedians(&Hist);
-
-  return Hist;
-}
-
-void EstimateSDsFromAbsDiffHist(DynamicMedianHistogram * pAbsDiffHist,
-  unsigned char * pSDs,
-  unsigned int imagesize,
-  double MinSD,
-  double MaxSD,
-  unsigned int kernelbins)
-{
-  double v;
-  double kernelbinfactor = (kernelbins - 1) / (MaxSD - MinSD);
-  int medianCount;
-  int sum;
-  int bin;
-  unsigned int histindex;
-  unsigned int j;
-  unsigned int x1, x2;
-
-  unsigned char *Hist = pAbsDiffHist->Hist;
-  unsigned char *MedianBins = pAbsDiffHist->MedianBins;
-  unsigned char *AccSum = pAbsDiffHist->AccSum;
-  unsigned char histsum = pAbsDiffHist->histsum;
-  unsigned char histbins = pAbsDiffHist->histbins;
-
-  medianCount = (histsum) / 2;
-
-  for (j = 0; j < imagesize; j++)
-  {
-    histindex = j*histbins;
-
-    bin = MedianBins[j];
-    sum = AccSum[j];
-
-    x1 = sum - Hist[histindex + bin];
-    x2 = sum;
-
-    // interpolate to get the median
-    // x1 < 50 % < x2
-
-    v = 1.04 * ((double)bin - (double)(x2 - medianCount) / (double)(x2 - x1));
-    v = (v <= MinSD ? MinSD : v);
-
-    // convert sd to kernel table bin
-
-    bin = (int)(v >= MaxSD ? kernelbins - 1 : floor((v - MinSD)*kernelbinfactor + .5));
-
-    assert(bin >= 0 && bin < kernelbins);
-
-    pSDs[j] = bin;
-  }
-}
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-NPBGSubtractor::NPBGSubtractor() {}
-
-NPBGSubtractor::~NPBGSubtractor()
-{
-  delete AbsDiffHist.Hist;
-  delete AbsDiffHist.MedianBins;
-  delete AbsDiffHist.MedianFreq;
-  delete AbsDiffHist.AccSum;
-  delete KernelTable;
-  delete BGModel->SDbinsImage;
-  delete BGModel;
-  delete Pimage1;
-  delete Pimage2;
-  delete tempFrame;
-  delete imageindex->List;
-  delete imageindex;
-}
-
-int NPBGSubtractor::Intialize(unsigned int prows,
-  unsigned int pcols,
-  unsigned int pcolor_channels,
-  unsigned int SequenceLength,
-  unsigned int pTimeWindowSize,
-  unsigned char pSDEstimationFlag,
-  unsigned char pUseColorRatiosFlag)
-{
-
-  rows = prows;
-  cols = pcols;
-  color_channels = pcolor_channels;
-  imagesize = rows*cols*color_channels;
-  SdEstimateFlag = pSDEstimationFlag;
-  UseColorRatiosFlag = pUseColorRatiosFlag;
-  //SampleSize = SequenceLength;
-
-  AdaptBGFlag = FALSE;
-  //
-  SubsetFlag = TRUE;
-
-  UpdateSDRate = 0;
-
-  BGModel = new NPBGmodel(rows, cols, color_channels, SequenceLength, pTimeWindowSize, 500);
-
-  Pimage1 = new double[rows*cols];
-  Pimage2 = new double[rows*cols];
-
-  tempFrame = new unsigned char[rows*cols * 3];
-
-  imageindex = new ImageIndex;
-  imageindex->List = new unsigned int[rows*cols];
-
-  // error checking
-  if (BGModel == NULL)
-    return 0;
-
-  return 1;
-}
-
-void NPBGSubtractor::AddFrame(unsigned char *ImageBuffer)
-{
-  if (UseColorRatiosFlag && color_channels == 3)
-    BGR2SnGnRn(ImageBuffer, ImageBuffer, rows, cols);
-
-  BGModel->AddFrame(ImageBuffer);
-}
-
-void NPBGSubtractor::Estimation()
-{
-  int SampleSize = BGModel->SampleSize;
-
-  memset(BGModel->TemporalMask, 0, rows*cols*BGModel->TemporalBufferLength);
-
-  //BGModel->AccMask= new unsigned int [rows*cols];
-  memset(BGModel->AccMask, 0, rows*cols * sizeof(unsigned int));
-
-  unsigned char *pSDs = new unsigned char[rows*cols*color_channels];
-
-  //DynamicMedianHistogram AbsDiffHist;
-
-  int Abshistbins = 20;
-
-  TimeIndex = 0;
-
-  // estimate standard deviations
-
-  if (SdEstimateFlag)
-  {
-    AbsDiffHist = BuildAbsDiffHist(BGModel->Sequence, rows, cols, color_channels, SampleSize, Abshistbins);
-    EstimateSDsFromAbsDiffHist(&AbsDiffHist, pSDs, imagesize, SEGMAMIN, SEGMAMAX, SEGMABINS);
-  }
-  else
-  {
-    unsigned int bin;
-    bin = (unsigned int)floor(((DEFAULTSEGMA - SEGMAMIN)*SEGMABINS) / (SEGMAMAX - SEGMAMIN));
-    memset(pSDs, bin, rows*cols*color_channels * sizeof(unsigned char));
-  }
-
-  BGModel->SDbinsImage = pSDs;
-
-  // Generate the Kernel
-  KernelTable = new KernelLUTable(KERNELHALFWIDTH, SEGMAMIN, SEGMAMAX, SEGMABINS);
-}
-
-/*********************************************************************/
-
-void BuildImageIndex(unsigned char * Image,
-  ImageIndex * imageIndex,
-  unsigned int rows,
-  unsigned int cols)
-{
-  unsigned int i, j;
-  unsigned int r, c;
-  unsigned int * image_list;
-
-  j = cols + 1;
-  i = 0;
-  image_list = imageIndex->List;
-
-  for (r = 1; r < rows - 1; r++)
-  {
-    for (c = 1; c < cols - 1; c++)
-    {
-      if (Image[j])
-        image_list[i++] = j;
-
-      j++;
-    }
-    j += 2;
-  }
-
-  imageIndex->cnt = i;
-}
-
-/*********************************************************************/
-
-void HystExpandOperatorIndexed(unsigned char * inImage,
-  ImageIndex * inIndex,
-  double * Pimage,
-  double hyst_th,
-  unsigned char * outImage,
-  ImageIndex * outIndex,
-  unsigned int urows,
-  unsigned int ucols)
-{
-  unsigned int * in_list;
-  unsigned int in_cnt;
-  unsigned int * out_list;
-
-  int rows, cols;
-
-  int Nbr[9];
-  unsigned int i, j;
-  unsigned int k;
-  unsigned int idx;
-
-  rows = (int)urows;
-  cols = (int)ucols;
-
-  in_cnt = inIndex->cnt;
-  in_list = inIndex->List;
-
-  Nbr[0] = -cols - 1;
-  Nbr[1] = -cols;
-  Nbr[2] = -cols + 1;
-  Nbr[3] = -1;
-  Nbr[4] = 0;
-  Nbr[5] = 1;
-  Nbr[6] = cols - 1;
-  Nbr[7] = cols;
-  Nbr[8] = cols + 1;
-
-  memset(outImage, 0, rows*cols);
-
-  out_list = outIndex->List;
-  k = 0;
-
-  for (i = 0; i < in_cnt; i++)
-  {
-    for (j = 0; j < 9; j++)
-    {
-      idx = in_list[i] + Nbr[j];
-
-      if (Pimage[idx] < hyst_th)
-        outImage[idx] = 255;
-    }
-  }
-
-  // build index for out image
-  BuildImageIndex(outImage, outIndex, urows, ucols);
-}
-
-/*********************************************************************/
-
-void HystShrinkOperatorIndexed(unsigned char * inImage,
-  ImageIndex * inIndex,
-  double * Pimage,
-  double hyst_th,
-  unsigned char * outImage,
-  ImageIndex * outIndex,
-  unsigned int urows,
-  unsigned int ucols)
-{
-  unsigned int * in_list;
-  unsigned int in_cnt;
-  unsigned int * out_list;
-
-  int rows, cols;
-
-  int Nbr[9];
-  unsigned int i, j;
-  unsigned int k, idx;
-
-  rows = (int)urows;
-  cols = (int)ucols;
-
-  in_cnt = inIndex->cnt;
-  in_list = inIndex->List;
-
-  Nbr[0] = -cols - 1;
-  Nbr[1] = -cols;
-  Nbr[2] = -cols + 1;
-  Nbr[3] = -1;
-  Nbr[4] = 0;
-  Nbr[5] = 1;
-  Nbr[6] = cols - 1;
-  Nbr[7] = cols;
-  Nbr[8] = cols + 1;
-
-  memset(outImage, 0, rows*cols);
-
-  out_list = outIndex->List;
-  k = 0;
-
-  for (i = 0; i < in_cnt; i++)
-  {
-    idx = in_list[i];
-    j = 0;
-
-    while (j < 9 && inImage[idx + Nbr[j]])
-      j++;
-
-    if (j >= 9 || Pimage[idx] <= hyst_th)
-      outImage[idx] = 255;
-  }
-
-  BuildImageIndex(outImage, outIndex, rows, cols);
-}
-
-/*********************************************************************/
-
-void ExpandOperatorIndexed(unsigned char * inImage,
-  ImageIndex * inIndex,
-  unsigned char * outImage,
-  ImageIndex * outIndex,
-  unsigned int urows,
-  unsigned int ucols)
-{
-  unsigned int * in_list;
-  unsigned int in_cnt;
-  unsigned int * out_list;
-
-  int rows, cols;
-
-  int Nbr[9];
-  unsigned int i, j;
-  unsigned int k;
-  unsigned int idx;
-
-  rows = (int)urows;
-  cols = (int)ucols;
-
-  in_cnt = inIndex->cnt;
-  in_list = inIndex->List;
-
-  Nbr[0] = -cols - 1;
-  Nbr[1] = -cols;
-  Nbr[2] = -cols + 1;
-  Nbr[3] = -1;
-  Nbr[4] = 0;
-  Nbr[5] = 1;
-  Nbr[6] = cols - 1;
-  Nbr[7] = cols;
-  Nbr[8] = cols + 1;
-
-
-  memset(outImage, 0, rows*cols);
-
-
-  out_list = outIndex->List;
-  k = 0;
-  for (i = 0; i < in_cnt; i++)
-    for (j = 0; j < 9; j++) {
-      idx = in_list[i] + Nbr[j];
-      outImage[idx] = 255;
-    }
-
-
-  // build index for out image
-
-  BuildImageIndex(outImage, outIndex, rows, cols);
-
-}
-
-/*********************************************************************/
-
-void ShrinkOperatorIndexed(unsigned char * inImage,
-  ImageIndex * inIndex,
-  unsigned char * outImage,
-  ImageIndex * outIndex,
-  unsigned int urows,
-  unsigned int ucols)
-{
-
-  unsigned int * in_list;
-  unsigned int in_cnt;
-  unsigned int * out_list;
-
-  int rows, cols;
-
-  int Nbr[9];
-  unsigned int i, j;
-  unsigned int k, idx;
-
-  rows = (int)urows;
-  cols = (int)ucols;
-
-  in_cnt = inIndex->cnt;
-  in_list = inIndex->List;
-
-  Nbr[0] = -cols - 1;
-  Nbr[1] = -cols;
-  Nbr[2] = -cols + 1;
-  Nbr[3] = -1;
-  Nbr[4] = 0;
-  Nbr[5] = 1;
-  Nbr[6] = cols - 1;
-  Nbr[7] = cols;
-  Nbr[8] = cols + 1;
-
-
-  memset(outImage, 0, rows*cols);
-
-  out_list = outIndex->List;
-  k = 0;
-  for (i = 0; i < in_cnt; i++) {
-    idx = in_list[i];
-    j = 0;
-
-    while (j < 9 && inImage[idx + Nbr[j]]) {
-      j++;
-    }
-
-    if (j >= 9) {
-      outImage[idx] = 255;
-    }
-  }
-
-  BuildImageIndex(outImage, outIndex, rows, cols);
-}
-
-/*********************************************************************/
-
-void NoiseFilter_o(unsigned char * Image,
-  unsigned char * ResultIm,
-  int rows,
-  int cols,
-  unsigned char th)
-{
-  /* assuming input is 1 for on, 0 for off */
-
-
-  int r, c;
-  unsigned char *p, *n, *nw, *ne, *e, *w, *s, *sw, *se;
-  unsigned int v;
-  unsigned int TH;
-
-  unsigned char * ResultPtr;
-
-  TH = 255 * th;
-
-  memset(ResultIm, 0, rows*cols);
-
-  p = Image + cols + 1;
-  ResultPtr = ResultIm + cols + 1;
-
-  for (r = 1; r < rows - 1; r++)
-  {
-    for (c = 1; c < cols - 1; c++)
-    {
-      if (*p)
-      {
-        n = p - cols;
-        ne = n + 1;
-        nw = n - 1;
-        e = p + 1;
-        w = p - 1;
-        s = p + cols;
-        se = s + 1;
-        sw = s - 1;
-
-        v = (unsigned int)*nw + *n + *ne + *w + *e + *sw + *s + *se;
-
-        if (v >= TH)
-          *ResultPtr = 255;
-        else
-          *ResultPtr = 0;
-      }
-      p++;
-      ResultPtr++;
-    }
-    p += 2;
-    ResultPtr += 2;
-  }
-}
-
-/*********************************************************************/
-
-void NPBGSubtractor::SequenceBGUpdate_Pairs(unsigned char * image,
-  unsigned char * Mask)
-{
-  unsigned int i, ic;
-  unsigned char * pSequence = BGModel->Sequence;
-  unsigned char * PixelQTop = BGModel->PixelQTop;
-  unsigned int Top = BGModel->Top;
-  unsigned int rate;
-
-  int TemporalBufferTop = (int)BGModel->TemporalBufferTop;
-  unsigned char * pTemporalBuffer = BGModel->TemporalBuffer;
-  unsigned char * pTemporalMask = BGModel->TemporalMask;
-  int TemporalBufferLength = BGModel->TemporalBufferLength;
-
-  unsigned int * AccMask = BGModel->AccMask;
-  unsigned int ResetMaskTh = BGModel->ResetMaskTh;
-
-  unsigned char *pAbsDiffHist = AbsDiffHist.Hist;
-  unsigned char histbins = AbsDiffHist.histbins;
-  int histbins_1 = histbins - 1;
-
-  int TimeWindowSize = BGModel->TimeWindowSize;
-  int SampleSize = BGModel->SampleSize;
-
-  int TemporalBufferNext;
-
-  unsigned int imagebuffersize = rows*cols*color_channels;
-  unsigned int imagespatialsize = rows*cols;
-
-  unsigned char mask;
-
-  unsigned int histindex;
-  unsigned char diff;
-  unsigned char bin;
-
-  static int TBCount = 0;
-
-  unsigned char * pTBbase1, *pTBbase2;
-  unsigned char * pModelbase1, *pModelbase2;
-
-  rate = TimeWindowSize / SampleSize;
-  rate = (rate > 2) ? rate : 2;
-
-
-  TemporalBufferNext = (TemporalBufferTop + 1)
-    % TemporalBufferLength;
-
-  // pointers to Masks : Top and Next
-  unsigned char * pTMaskTop = pTemporalMask + TemporalBufferTop*imagespatialsize;
-  unsigned char * pTMaskNext = pTemporalMask + TemporalBufferNext*imagespatialsize;
-
-  // pointers to TB frames: Top and Next
-  unsigned char * pTBTop = pTemporalBuffer + TemporalBufferTop*imagebuffersize;
-  unsigned char * pTBNext = pTemporalBuffer + TemporalBufferNext*imagebuffersize;
-
-  if (((TimeIndex) % rate == 0) && TBCount >= TemporalBufferLength)
-  {
-    for (i = 0, ic = 0; i < imagespatialsize; i++, ic += color_channels)
-    {
-      mask = *(pTMaskTop + i) || *(pTMaskNext + i);
-
-      if (!mask)
-      {
-        // pointer to TB pixels to be added to the model
-        pTBbase1 = pTBTop + ic;
-        pTBbase2 = pTBNext + ic;
-
-        // pointers to Model pixels to be replaced
-        pModelbase1 = pSequence + PixelQTop[i] * imagebuffersize + ic;
-        pModelbase2 = pSequence + ((PixelQTop[i] + 1) % SampleSize)*imagebuffersize + ic;
-
-        // update Deviation Histogram
-        if (SdEstimateFlag)
-        {
-          if (color_channels == 1)
-          {
-            histindex = i*histbins;
-
-            // add new pair from temporal buffer
-            diff = (unsigned char)abs((int)*pTBbase1 - (int)*pTBbase2);
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]++;
-
-
-            // remove old pair from the model
-            diff = (unsigned char)abs((int)*pModelbase1 - (int)*pModelbase2);
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]--;
-          }
-          else
-          {
-            // color
-
-            // add new pair from temporal buffer
-            histindex = ic*histbins;
-            diff = abs(*pTBbase1 -
-              *pTBbase2);
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]++;
-
-            histindex += histbins;
-            diff = abs(*(pTBbase1 + 1) -
-              *(pTBbase2 + 1));
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]++;
-
-            histindex += histbins;
-            diff = abs(*(pTBbase1 + 2) -
-              *(pTBbase2 + 2));
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]++;
-
-            // remove old pair from the model
-            histindex = ic*histbins;
-
-            diff = abs(*pModelbase1 -
-              *pModelbase2);
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]--;
-
-            histindex += histbins;
-            diff = abs(*(pModelbase1 + 1) -
-              *(pModelbase2 + 1));
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]--;
-
-            histindex += histbins;
-            diff = abs(*(pModelbase1 + 2) -
-              *(pModelbase2 + 2));
-            bin = (diff < histbins ? diff : histbins_1);
-            pAbsDiffHist[histindex + bin]--;
-          }
-        }
-
-        // add new pair into the model
-        memcpy(pModelbase1, pTBbase1, color_channels * sizeof(unsigned char));
-
-        memcpy(pModelbase2, pTBbase2, color_channels * sizeof(unsigned char));
-
-        PixelQTop[i] = (PixelQTop[i] + 2) % SampleSize;
-      }
-    }
-  } // end if (sampling event)
-
-  // update temporal buffer
-  // add new frame to Temporal buffer.
-  memcpy(pTBTop, image, imagebuffersize);
-
-  // update AccMask
-  // update new Mask with information in AccMask
-
-  for (i = 0; i < rows*cols; i++)
-  {
-    if (Mask[i])
-      AccMask[i]++;
-    else
-      AccMask[i] = 0;
-
-    if (AccMask[i] > ResetMaskTh)
-      Mask[i] = 0;
-  }
-
-  // add new mask
-  memcpy(pTMaskTop, Mask, imagespatialsize);
-
-  // advance Temporal buffer pointer
-  TemporalBufferTop = (TemporalBufferTop + 1) % TemporalBufferLength;
-
-  BGModel->TemporalBufferTop = TemporalBufferTop;
-
-  TBCount++;
-
-  // estimate SDs
-
-  if (SdEstimateFlag && UpdateSDRate && ((TimeIndex) % UpdateSDRate == 0))
-  {
-    double MaxSD = KernelTable->maxsegma;
-    double MinSD = KernelTable->minsegma;
-    int KernelBins = KernelTable->segmabins;
-
-    unsigned char * pSDs = BGModel->SDbinsImage;
-
-    FindHistMedians(&(AbsDiffHist));
-    EstimateSDsFromAbsDiffHist(&(AbsDiffHist), pSDs, imagebuffersize, MinSD, MaxSD, KernelBins);
-  }
-
-  TimeIndex++;
-}
-
-/*********************************************************************/
-
-void DisplayPropabilityImageWithThresholding(double * Pimage,
-  unsigned char * DisplayImage,
-  double Threshold,
-  unsigned int rows,
-  unsigned int cols)
-{
-  double p;
-
-  for (unsigned int i = 0; i < rows*cols; i++)
-  {
-    p = Pimage[i];
-
-    DisplayImage[i] = (p > Threshold) ? 0 : 255;
-  }
-}
-
-/*********************************************************************/
-
-void NPBGSubtractor::NPBGSubtraction_Subset_Kernel(
-  unsigned char * image,
-  unsigned char * FGImage,
-  unsigned char * FilteredFGImage)
-{
-  unsigned int i, j;
-  unsigned char *pSequence = BGModel->Sequence;
-
-  unsigned int SampleSize = BGModel->SampleSize;
-
-  double *kerneltable = KernelTable->kerneltable;
-  int KernelHalfWidth = KernelTable->tablehalfwidth;
-  double *KernelSum = KernelTable->kernelsums;
-  double KernelMaxSigma = KernelTable->maxsegma;
-  double KernelMinSigma = KernelTable->minsegma;
-  int KernelBins = KernelTable->segmabins;
-  unsigned char * SDbins = BGModel->SDbinsImage;
-
-  unsigned char * SaturationImage = FilteredFGImage;
-
-  // default sigmas .. to be removed.
-  double sigma1;
-  double sigma2;
-  double sigma3;
-
-  sigma1 = 2.25;
-  sigma2 = 2.25;
-  sigma3 = 2.25;
-
-  double p;
-  double th;
-
-  double alpha;
-
-  alpha = AlphaValue;
-
-  /* intialize FG image */
-
-  memset(FGImage, 0, rows*cols);
-
-  //Threshold=1;
-  th = Threshold * SampleSize;
-
-  double sum = 0, kernel1, kernel2, kernel3;
-  int k, g;
-
-
-  if (color_channels == 1)
-  {
-    // gray scale
-
-    int kernelbase;
-
-    for (i = 0; i < rows*cols; i++)
-    {
-      kernelbase = SDbins[i] * (2 * KernelHalfWidth + 1);
-      sum = 0;
-      j = 0;
-
-      while (j < SampleSize && sum < th)
-      {
-        g = pSequence[j*imagesize + i];
-        k = g - image[i] + KernelHalfWidth;
-        sum += kerneltable[kernelbase + k];
-        j++;
-      }
-
-      p = sum / j;
-      Pimage1[i] = p;
-    }
-  }
-  else if (UseColorRatiosFlag && SubsetFlag)
-  {
-    // color ratios
-
-    unsigned int ig;
-    int base;
-
-    int kernelbase1;
-    int kernelbase2;
-    int kernelbase3;
-
-    unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
-
-    double beta = 3.0;    // minimum bound on the range.
-    double betau = 100.0;
-
-    double beta_over_alpha = beta / alpha;
-    double betau_over_alpha = betau / alpha;
-
-
-    double brightness_lowerbound = 1 - alpha;
-    double brightness_upperbound = 1 + alpha;
-    int x1, x2;
-    unsigned int SubsampleCount;
-
-    for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
-    {
-      kernelbase1 = SDbins[i] * kerneltablewidth;
-      kernelbase2 = SDbins[i + 1] * kerneltablewidth;
-      kernelbase3 = SDbins[i + 2] * kerneltablewidth;
-
-      sum = 0;
-      j = 0;
-      SubsampleCount = 0;
-
-      while (j < SampleSize && sum < th)
-      {
-        base = j*imagesize + i;
-        g = pSequence[base];
-
-        if (g < beta_over_alpha)
-        {
-          x1 = (int)(g - beta);
-          x2 = (int)(g + beta);
-        }
-        else if (g > betau_over_alpha)
-        {
-          x1 = (int)(g - betau);
-          x2 = (int)(g + betau);
-        }
-        else
-        {
-          x1 = (int)(g*brightness_lowerbound + 0.5);
-          x2 = (int)(g*brightness_upperbound + 0.5);
-        }
-
-        if (x1 < image[i] && image[i] < x2)
-        {
-          g = pSequence[base + 1];
-          k = (g - image[i + 1]) + KernelHalfWidth;
-          kernel2 = kerneltable[kernelbase2 + k];
-
-          g = pSequence[base + 2];
-          k = (g - image[i + 2]) + KernelHalfWidth;
-          kernel3 = kerneltable[kernelbase3 + k];
-
-          sum += kernel2*kernel3;
-
-          SubsampleCount++;
-        }
-        j++;
-      }
-
-      p = sum / j;
-      Pimage1[ig] = p;
-    }
-  }
-  else if (UseColorRatiosFlag && !SubsetFlag)
-  {
-    // color ratios
-
-    unsigned int ig;
-    int base;
-    int bin;
-
-    int kernelbase1;
-    int kernelbase2;
-    int kernelbase3;
-
-    unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
-
-    int gmin, gmax;
-    double gfactor;
-
-    gmax = 200;
-    gmin = 10;
-
-    gfactor = (KernelMaxSigma - KernelMinSigma) / (double)(gmax - gmin);
-
-    for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
-    {
-
-      bin = (int)floor(((alpha * 16 - KernelMinSigma)*KernelBins) / (KernelMaxSigma - KernelMinSigma));
-
-      kernelbase1 = bin*kerneltablewidth;
-      kernelbase2 = SDbins[i + 1] * kerneltablewidth;
-      kernelbase3 = SDbins[i + 2] * kerneltablewidth;
-
-      sum = 0;
-      j = 0;
-
-      while (j < SampleSize && sum < th)
-      {
-        base = j*imagesize + i;
-        g = pSequence[base];
-
-        if (g < gmin)
-          bin = 0;
-        else if (g > gmax)
-          bin = KernelBins - 1;
-        else
-          bin = (int)((g - gmin) * gfactor + 0.5);
-
-        kernelbase1 = bin*kerneltablewidth;
-
-        k = (g - image[i]) + KernelHalfWidth;
-        kernel1 = kerneltable[kernelbase1 + k];
-
-        g = pSequence[base + 1];
-        k = (g - image[i + 1]) + KernelHalfWidth;
-        kernel2 = kerneltable[kernelbase2 + k];
-
-        g = pSequence[base + 2];
-        k = (g - image[i + 2]) + KernelHalfWidth;
-        kernel3 = kerneltable[kernelbase3 + k];
-
-        sum += kernel1*kernel2*kernel3;
-        j++;
-      }
-
-      p = sum / j;
-      Pimage1[ig] = p;
-    }
-  }
-  else // RGB color
-  {
-    unsigned int ig;
-    int base;
-
-    int kernelbase1;
-    int kernelbase2;
-    int kernelbase3;
-    unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
-
-    for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
-    {
-      // used extimated kernel width to access the right kernel
-      kernelbase1 = SDbins[i] * kerneltablewidth;
-      kernelbase2 = SDbins[i + 1] * kerneltablewidth;
-      kernelbase3 = SDbins[i + 2] * kerneltablewidth;
-
-      sum = 0;
-      j = 0;
-      while (j < SampleSize && sum < th)
-      {
-        base = j*imagesize + i;
-        g = pSequence[base];
-        k = (g - image[i]) + KernelHalfWidth;
-        kernel1 = kerneltable[kernelbase1 + k];
-
-        g = pSequence[base + 1];
-        k = (g - image[i + 1]) + KernelHalfWidth;
-        kernel2 = kerneltable[kernelbase2 + k];
-
-        g = pSequence[base + 2];
-        k = (g - image[i + 2]) + KernelHalfWidth;
-        kernel3 = kerneltable[kernelbase3 + k];
-
-        sum += kernel1*kernel2*kernel3;
-        j++;
-      }
-
-      p = sum / j;
-      Pimage1[ig] = p;
-    }
-  }
-
-  DisplayPropabilityImageWithThresholding(Pimage1, FGImage, Threshold, rows, cols);
-}
-
-/*********************************************************************/
-
-void NPBGSubtractor::NBBGSubtraction(unsigned char * Frame,
-  unsigned char * FGImage,
-  unsigned char * FilteredFGImage,
-  unsigned char ** DisplayBuffers)
-{
-  if (UseColorRatiosFlag)
-    BGR2SnGnRn(Frame, tempFrame, rows, cols);
-  else
-    memcpy(tempFrame, Frame, rows*cols*color_channels);
-
-  NPBGSubtraction_Subset_Kernel(tempFrame, FGImage, FilteredFGImage);
-  /*NoiseFilter_o(FGImage,DisplayBuffers[3],rows,cols,4);
-  BuildImageIndex(DisplayBuffers[3],imageindex,rows,cols);
-
-  ExpandOperatorIndexed(DisplayBuffers[3],imageindex,DisplayBuffers[4],imageindex,rows,cols);
-  ShrinkOperatorIndexed(DisplayBuffers[4],imageindex,FilteredFGImage,imageindex,rows,cols);
-
-  memset(DisplayBuffers[3],0,rows*cols);*/
-}
-
-void NPBGSubtractor::Update(unsigned char * FGMask)
-{
-  if (UpdateBGFlag)
-    SequenceBGUpdate_Pairs(tempFrame, FGMask);
-}
diff --git a/package_bgs/KDE/NPBGSubtractor.h b/package_bgs/KDE/NPBGSubtractor.h
deleted file mode 100644
index ce4bffc4812904a81a203c63f64bf1cf6080d14a..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/NPBGSubtractor.h
+++ /dev/null
@@ -1,146 +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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-
-// NPBGSubtractor.h: interface for the NPBGSubtractor class.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include "NPBGmodel.h"
-#include "KernelTable.h"
-
-#define FALSE 0
-#define TRUE 1
-
-// kernal look up table settings
-#define 	KERNELHALFWIDTH 255
-#define 	SEGMAMAX 36.5
-#define	  SEGMAMIN 0.5
-#define		SEGMABINS 80
-#define		DEFAULTSEGMA 1.0
-
-typedef struct
-{
-  unsigned char *Hist;
-  unsigned char *MedianBins;
-  unsigned char *MedianFreq;
-  unsigned char *AccSum;
-  unsigned char histbins;
-  unsigned char histsum;
-  unsigned int  imagesize;
-} DynamicMedianHistogram;
-
-typedef struct
-{
-  unsigned int cnt;
-  unsigned int *List;
-} ImageIndex;
-
-class NPBGSubtractor
-{
-private:
-  unsigned int rows;
-  unsigned int cols;
-  unsigned int color_channels;
-  unsigned int imagesize;
-  // flags
-  unsigned char UpdateBGFlag;
-  unsigned char SdEstimateFlag;
-  unsigned char UseColorRatiosFlag;
-  unsigned char AdaptBGFlag;
-  unsigned char SubsetFlag;
-  //
-  int UpdateSDRate;
-  double Threshold;
-  double AlphaValue;
-  unsigned int TimeIndex;
-  ImageIndex  *imageindex;
-  unsigned char *tempFrame;
-  KernelLUTable *KernelTable;
-  NPBGmodel *BGModel;
-  DynamicMedianHistogram AbsDiffHist;
-  double *Pimage1;
-  double *Pimage2;
-  //
-  void NPBGSubtraction_Subset_Kernel(unsigned char * image, unsigned char * FGImage, unsigned char * FilteredFGImage);
-  void SequenceBGUpdate_Pairs(unsigned char * image, unsigned char * Mask);
-
-public:
-  NPBGSubtractor();
-  virtual ~NPBGSubtractor();
-  //~NPBGSubtractor();
-
-  int Intialize(unsigned int rows,
-    unsigned int cols,
-    unsigned int color_channels,
-    unsigned int SequenceLength,
-    unsigned int TimeWindowSize,
-    unsigned char SDEstimationFlag,
-    unsigned char UseColorRatiosFlag);
-
-  void AddFrame(unsigned char * ImageBuffer);
-
-  void Estimation();
-
-  void NBBGSubtraction(unsigned char *Frame,
-    unsigned char *FGImage,
-    unsigned char *FilteredFGImage,
-    unsigned char **DisplayBuffers);
-
-  void Update(unsigned char *);
-
-  void SetThresholds(double th, double alpha)
-  {
-    Threshold = th;
-    AlphaValue = alpha;
-  };
-
-  void SetUpdateFlag(unsigned int bgflag) {
-    UpdateBGFlag = bgflag;
-  };
-};
diff --git a/package_bgs/KDE/NPBGmodel.cpp b/package_bgs/KDE/NPBGmodel.cpp
deleted file mode 100644
index a79a7b42f1ae663d3da1afaef56899bd4cd3f218..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/NPBGmodel.cpp
+++ /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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-
-// NPBGmodel.cpp: implementation of the NPBGmodel class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#include "NPBGmodel.h"
-#include "memory.h"
-
-#ifdef _DEBUG
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-//#define new DEBUG_NEW
-#endif
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-NPBGmodel::NPBGmodel()
-{
-  std::cout << "NPBGmodel()" << std::endl;
-}
-
-NPBGmodel::~NPBGmodel()
-{
-  delete Sequence;
-  delete PixelQTop;
-  delete TemporalBuffer;
-  delete TemporalMask;
-  delete AccMask;
-  //delete SDbinsImage;
-  std::cout << "~NPBGmodel()" << std::endl;
-}
-
-NPBGmodel::NPBGmodel(unsigned int Rows,
-  unsigned int Cols,
-  unsigned int ColorChannels,
-  unsigned int Length,
-  unsigned int pTimeWindowSize,
-  unsigned int bg_suppression_time)
-{
-  std::cout << "NPBGmodel()" << std::endl;
-
-  imagesize = Rows*Cols*ColorChannels;
-
-  rows = Rows;
-  cols = Cols;
-  color_channels = ColorChannels;
-
-  SampleSize = Length;
-
-  TimeWindowSize = pTimeWindowSize;
-
-  Sequence = new unsigned char[imagesize*Length];
-  Top = 0;
-  memset(Sequence, 0, imagesize*Length);
-
-  PixelQTop = new unsigned char[rows*cols];
-
-  // temporalBuffer
-  TemporalBufferLength = (TimeWindowSize / Length > 2 ? TimeWindowSize / Length : 2);
-  TemporalBuffer = new unsigned char[imagesize*TemporalBufferLength];
-  TemporalMask = new unsigned char[rows*cols*TemporalBufferLength];
-
-  TemporalBufferTop = 0;
-
-  AccMask = new unsigned int[rows*cols];
-
-  ResetMaskTh = bg_suppression_time;
-}
-
-void NPBGmodel::AddFrame(unsigned char *ImageBuffer)
-{
-  memcpy(Sequence + Top*imagesize, ImageBuffer, imagesize);
-  Top = (Top + 1) % SampleSize;
-
-  memset(PixelQTop, (unsigned char)Top, rows*cols);
-
-  memcpy(TemporalBuffer, ImageBuffer, imagesize);
-}
diff --git a/package_bgs/KDE/NPBGmodel.h b/package_bgs/KDE/NPBGmodel.h
deleted file mode 100644
index ba4a927875ea083f5e99dad42ee7a4bee3f9ea32..0000000000000000000000000000000000000000
--- a/package_bgs/KDE/NPBGmodel.h
+++ /dev/null
@@ -1,103 +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/>.
-*/
-/*
-*
-* Copyright 2001 by Ahmed Elgammal All  rights reserved.
-*
-* Permission to use, copy,  or modify this software and  its documentation
-* for  educational  and  research purposes only and without fee  is hereby
-* granted, provided  that this copyright notice and the original authors's
-* name appear  on all copies and supporting documentation.  If individual
-* files are  separated from  this  distribution directory  structure, this
-* copyright notice must be included.  For any other uses of this software,
-* in original or  modified form, including but not limited to distribution
-* in whole or in  part, specific  prior permission  must be  obtained from
-* Author or UMIACS.  These programs shall not  be  used, rewritten, or
-* adapted as  the basis  of  a commercial  software  or  hardware product
-* without first obtaining appropriate licenses  from Author.
-* Other than these cases, no part of this software may be used or
-* distributed without written permission of the author.
-*
-* Neither the author nor UMIACS make any representations about the
-* suitability of this software for any purpose.  It is provided
-* "as is" without express or implied warranty.
-*
-* Ahmed Elgammal
-*
-* University of Maryland at College Park
-* UMIACS
-* A.V. Williams Bldg.
-* CollegePark, MD 20742
-* E-mail:  elgammal@umiacs.umd.edu
-*
-**/
-
-// NPBGmodel.h: interface for the NPBGmodel class.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include <iostream>
-
-class NPBGmodel
-{
-private:
-  unsigned char *Sequence;
-  unsigned int SampleSize;
-  unsigned int TimeWindowSize;
-
-  unsigned int rows, cols, color_channels;
-  unsigned int imagesize;
-
-  unsigned int Top;
-  unsigned char *PixelQTop;
-
-  //unsigned int *PixelUpdateCounter;
-
-  unsigned char *SDbinsImage;
-
-  unsigned char *TemporalBuffer;
-  unsigned char TemporalBufferLength;
-  unsigned char TemporalBufferTop;
-  unsigned char *TemporalBufferMask;
-
-  unsigned char *TemporalMask;
-  unsigned char TemporalMaskLength;
-  unsigned char TemporalMaskTop;
-
-  unsigned int *AccMask;
-  unsigned int ResetMaskTh;	// Max continous duration a pixel can be detected before
-  // it is forced to be updated...
-
-  double *weights;
-
-public:
-  NPBGmodel();
-  //~NPBGmodel();
-  virtual ~NPBGmodel();
-
-  NPBGmodel(unsigned int Rows,
-    unsigned int Cols,
-    unsigned int ColorChannels,
-    unsigned int Length,
-    unsigned int pTimeWindowSize,
-    unsigned int bg_suppression_time);
-
-  void AddFrame(unsigned char *ImageBuffer);
-
-  friend class NPBGSubtractor;
-};
diff --git a/package_bgs/KNN.cpp b/package_bgs/KNN.cpp
deleted file mode 100644
index d2e14127ee2efcde134226b10871716994bc1f5e..0000000000000000000000000000000000000000
--- a/package_bgs/KNN.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 "KNN.h"
-
-#if CV_MAJOR_VERSION == 3
-
-using namespace bgslibrary::algorithms;
-
-KNN::KNN() :
-  history(500), nSamples(7), dist2Threshold(20.0f * 20.0f), knnSamples(0),
-  doShadowDetection(true), shadowValue(127), shadowThreshold(0.5f)
-{
-  std::cout << "KNN()" << std::endl;
-  setup("./config/KNN.xml");
-}
-
-KNN::~KNN()
-{
-  std::cout << "~KNN()" << std::endl;
-}
-
-void KNN::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  //------------------------------------------------------------------
-  // BackgroundSubtractorKNN
-  // http://docs.opencv.org/trunk/modules/video/doc/motion_analysis_and_object_tracking.html#backgroundsubtractorknn
-  //
-  //  The class implements the K nearest neigbours algorithm from:
-  //  "Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction"
-  //  Z.Zivkovic, F. van der Heijden
-  //  Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006
-  //  http:  //www.zoranz.net/Publications/zivkovicPRL2006.pdf
-  //
-  //  Fast for small foreground object. Results on the benchmark data is at http://www.changedetection.net.
-  //------------------------------------------------------------------
-
-  int prevNSamples = nSamples;
-  if (firstTime)
-    knn = cv::createBackgroundSubtractorKNN(history, dist2Threshold, doShadowDetection);
-
-  knn->setNSamples(nSamples);
-  knn->setkNNSamples(knnSamples);
-  knn->setShadowValue(shadowValue);
-  knn->setShadowThreshold(shadowThreshold);
-
-  knn->apply(img_input, img_foreground, prevNSamples != nSamples ? 0.f : 1.f);
-  knn->getBackgroundImage(img_background);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("KNN FG", img_foreground);
-    cv::imshow("KNN BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void KNN::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "history", history);
-  cvWriteInt(fs, "nSamples", nSamples);
-  cvWriteReal(fs, "dist2Threshold", dist2Threshold);
-  cvWriteInt(fs, "knnSamples", knnSamples);
-  cvWriteInt(fs, "doShadowDetection", doShadowDetection);
-  cvWriteInt(fs, "shadowValue", shadowValue);
-  cvWriteReal(fs, "shadowThreshold", shadowThreshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void KNN::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  history = cvReadIntByName(fs, nullptr, "history", 500);
-  nSamples = cvReadIntByName(fs, nullptr, "nSamples", 7);
-  dist2Threshold = cvReadRealByName(fs, nullptr, "dist2Threshold", 20.0f * 20.0f);
-  knnSamples = cvReadIntByName(fs, nullptr, "knnSamples", 0);
-  doShadowDetection = cvReadIntByName(fs, nullptr, "doShadowDetection", 1);
-  shadowValue = cvReadIntByName(fs, nullptr, "shadowValue", 127);
-  shadowThreshold = cvReadRealByName(fs, nullptr, "shadowThreshold", 0.5f);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
-
-#endif
diff --git a/package_bgs/KNN.h b/package_bgs/KNN.h
deleted file mode 100644
index 87f20b249444b5ad2da2864e6b30eb0b9b36e78b..0000000000000000000000000000000000000000
--- a/package_bgs/KNN.h
+++ /dev/null
@@ -1,57 +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
-
-#include "opencv2/core/version.hpp"
-#if CV_MAJOR_VERSION == 3
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-#include <opencv2/video/background_segm.hpp>
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class KNN : public IBGS
-    {
-    private:
-      cv::Ptr<cv::BackgroundSubtractorKNN> knn;
-      int history;
-      int nSamples;
-      float dist2Threshold;
-      int knnSamples;
-      bool doShadowDetection;
-      int shadowValue;
-      float shadowThreshold;
-
-    public:
-      KNN();
-      ~KNN();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
-
-#endif
diff --git a/package_bgs/LBAdaptiveSOM.cpp b/package_bgs/LBAdaptiveSOM.cpp
deleted file mode 100644
index 188e11d450ca29709fd5b1fcc567982ecb0f1360..0000000000000000000000000000000000000000
--- a/package_bgs/LBAdaptiveSOM.cpp
+++ /dev/null
@@ -1,102 +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 "LBAdaptiveSOM.h"
-
-using namespace bgslibrary::algorithms;
-
-LBAdaptiveSOM::LBAdaptiveSOM() :
-  sensitivity(75), trainingSensitivity(245), learningRate(62), trainingLearningRate(255), trainingSteps(55)
-{
-  std::cout << "LBAdaptiveSOM()" << std::endl;
-  setup("./config/LBAdaptiveSOM.xml");
-}
-
-LBAdaptiveSOM::~LBAdaptiveSOM()
-{
-  delete m_pBGModel;
-  std::cout << "~LBAdaptiveSOM()" << std::endl;
-}
-
-void LBAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage *frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    int w = cvGetSize(frame).width;
-    int h = cvGetSize(frame).height;
-
-    m_pBGModel = new BGModelSom(w, h);
-    m_pBGModel->InitModel(frame);
-  }
-
-  m_pBGModel->setBGModelParameter(0, sensitivity);
-  m_pBGModel->setBGModelParameter(1, trainingSensitivity);
-  m_pBGModel->setBGModelParameter(2, learningRate);
-  m_pBGModel->setBGModelParameter(3, trainingLearningRate);
-  m_pBGModel->setBGModelParameter(5, trainingSteps);
-
-  m_pBGModel->UpdateModel(frame);
-
-  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("SOM Mask", img_foreground);
-    cv::imshow("SOM Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-
-  firstTime = false;
-}
-
-void LBAdaptiveSOM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "sensitivity", sensitivity);
-  cvWriteInt(fs, "trainingSensitivity", trainingSensitivity);
-  cvWriteInt(fs, "learningRate", learningRate);
-  cvWriteInt(fs, "trainingLearningRate", trainingLearningRate);
-  cvWriteInt(fs, "trainingSteps", trainingSteps);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBAdaptiveSOM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 75);
-  trainingSensitivity = cvReadIntByName(fs, nullptr, "trainingSensitivity", 245);
-  learningRate = cvReadIntByName(fs, nullptr, "learningRate", 62);
-  trainingLearningRate = cvReadIntByName(fs, nullptr, "trainingLearningRate", 255);
-  trainingSteps = cvReadIntByName(fs, nullptr, "trainingSteps", 55);
-  showOutput = cvReadIntByName(fs, 0, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBAdaptiveSOM.h b/package_bgs/LBAdaptiveSOM.h
deleted file mode 100644
index 7671ae1df9ff0540e2c74e3da8d53c5d58cceccd..0000000000000000000000000000000000000000
--- a/package_bgs/LBAdaptiveSOM.h
+++ /dev/null
@@ -1,50 +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
-
-#include "lb/BGModelSom.h"
-#include "IBGS.h"
-
-using namespace lb_library;
-using namespace lb_library::AdaptiveSOM;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBAdaptiveSOM : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int trainingSensitivity;
-      int learningRate;
-      int trainingLearningRate;
-      int trainingSteps;
-
-    public:
-      LBAdaptiveSOM();
-      ~LBAdaptiveSOM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/LBFuzzyAdaptiveSOM.cpp b/package_bgs/LBFuzzyAdaptiveSOM.cpp
deleted file mode 100644
index 73df1d7ba56f18bc35f2ca667727495b254f7555..0000000000000000000000000000000000000000
--- a/package_bgs/LBFuzzyAdaptiveSOM.cpp
+++ /dev/null
@@ -1,102 +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 "LBFuzzyAdaptiveSOM.h"
-
-using namespace bgslibrary::algorithms;
-
-LBFuzzyAdaptiveSOM::LBFuzzyAdaptiveSOM() :
-  sensitivity(90), trainingSensitivity(240), learningRate(38), trainingLearningRate(255), trainingSteps(81)
-{
-  std::cout << "LBFuzzyAdaptiveSOM()" << std::endl;
-  setup("./config/LBFuzzyAdaptiveSOM.xml");
-}
-
-LBFuzzyAdaptiveSOM::~LBFuzzyAdaptiveSOM()
-{
-  delete m_pBGModel;
-  std::cout << "~LBFuzzyAdaptiveSOM()" << std::endl;
-}
-
-void LBFuzzyAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage *frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    int w = cvGetSize(frame).width;
-    int h = cvGetSize(frame).height;
-
-    m_pBGModel = new BGModelFuzzySom(w, h);
-    m_pBGModel->InitModel(frame);
-  }
-
-  m_pBGModel->setBGModelParameter(0, sensitivity);
-  m_pBGModel->setBGModelParameter(1, trainingSensitivity);
-  m_pBGModel->setBGModelParameter(2, learningRate);
-  m_pBGModel->setBGModelParameter(3, trainingLearningRate);
-  m_pBGModel->setBGModelParameter(5, trainingSteps);
-
-  m_pBGModel->UpdateModel(frame);
-
-  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("FSOM Mask", img_foreground);
-    cv::imshow("FSOM Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-
-  firstTime = false;
-}
-
-void LBFuzzyAdaptiveSOM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "sensitivity", sensitivity);
-  cvWriteInt(fs, "trainingSensitivity", trainingSensitivity);
-  cvWriteInt(fs, "learningRate", learningRate);
-  cvWriteInt(fs, "trainingLearningRate", trainingLearningRate);
-  cvWriteInt(fs, "trainingSteps", trainingSteps);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBFuzzyAdaptiveSOM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 90);
-  trainingSensitivity = cvReadIntByName(fs, nullptr, "trainingSensitivity", 240);
-  learningRate = cvReadIntByName(fs, nullptr, "learningRate", 38);
-  trainingLearningRate = cvReadIntByName(fs, nullptr, "trainingLearningRate", 255);
-  trainingSteps = cvReadIntByName(fs, nullptr, "trainingSteps", 81);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBFuzzyAdaptiveSOM.h b/package_bgs/LBFuzzyAdaptiveSOM.h
deleted file mode 100644
index 6a4a85c0007951b3a82b6f11941e669d16430332..0000000000000000000000000000000000000000
--- a/package_bgs/LBFuzzyAdaptiveSOM.h
+++ /dev/null
@@ -1,50 +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
-
-#include "IBGS.h"
-#include "lb/BGModelFuzzySom.h"
-
-using namespace lb_library;
-using namespace lb_library::FuzzyAdaptiveSOM;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBFuzzyAdaptiveSOM : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int trainingSensitivity;
-      int learningRate;
-      int trainingLearningRate;
-      int trainingSteps;
-
-    public:
-      LBFuzzyAdaptiveSOM();
-      ~LBFuzzyAdaptiveSOM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/LBFuzzyGaussian.cpp b/package_bgs/LBFuzzyGaussian.cpp
deleted file mode 100644
index b1610260bf407bc19a0750234fed4e1528ea7f06..0000000000000000000000000000000000000000
--- a/package_bgs/LBFuzzyGaussian.cpp
+++ /dev/null
@@ -1,99 +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 "LBFuzzyGaussian.h"
-
-using namespace bgslibrary::algorithms;
-
-LBFuzzyGaussian::LBFuzzyGaussian() :
-  sensitivity(72), bgThreshold(162), learningRate(49), noiseVariance(195)
-{
-  std::cout << "LBFuzzyGaussian()" << std::endl;
-  setup("./config/LBFuzzyGaussian.xml");
-}
-
-LBFuzzyGaussian::~LBFuzzyGaussian()
-{
-  delete m_pBGModel;
-  std::cout << "~LBFuzzyGaussian()" << std::endl;
-}
-
-void LBFuzzyGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage *frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    int w = cvGetSize(frame).width;
-    int h = cvGetSize(frame).height;
-
-    m_pBGModel = new BGModelFuzzyGauss(w, h);
-    m_pBGModel->InitModel(frame);
-  }
-
-  m_pBGModel->setBGModelParameter(0, sensitivity);
-  m_pBGModel->setBGModelParameter(1, bgThreshold);
-  m_pBGModel->setBGModelParameter(2, learningRate);
-  m_pBGModel->setBGModelParameter(3, noiseVariance);
-
-  m_pBGModel->UpdateModel(frame);
-
-  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("FG Mask", img_foreground);
-    cv::imshow("FG Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-
-  firstTime = false;
-}
-
-void LBFuzzyGaussian::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "sensitivity", sensitivity);
-  cvWriteInt(fs, "bgThreshold", bgThreshold);
-  cvWriteInt(fs, "learningRate", learningRate);
-  cvWriteInt(fs, "noiseVariance", noiseVariance);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBFuzzyGaussian::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 72);
-  bgThreshold = cvReadIntByName(fs, nullptr, "bgThreshold", 162);
-  learningRate = cvReadIntByName(fs, nullptr, "learningRate", 49);
-  noiseVariance = cvReadIntByName(fs, nullptr, "noiseVariance", 195);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBFuzzyGaussian.h b/package_bgs/LBFuzzyGaussian.h
deleted file mode 100644
index 53c26679d55f1d7720b1eabbce8486f609e7c15d..0000000000000000000000000000000000000000
--- a/package_bgs/LBFuzzyGaussian.h
+++ /dev/null
@@ -1,49 +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
-
-#include "IBGS.h"
-#include "lb/BGModelFuzzyGauss.h"
-
-using namespace lb_library;
-using namespace lb_library::FuzzyGaussian;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBFuzzyGaussian : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int bgThreshold;
-      int learningRate;
-      int noiseVariance;
-
-    public:
-      LBFuzzyGaussian();
-      ~LBFuzzyGaussian();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/LBMixtureOfGaussians.cpp b/package_bgs/LBMixtureOfGaussians.cpp
deleted file mode 100644
index 6cd9c917ca6d9fddbc01e94e7eb71a998418ba5e..0000000000000000000000000000000000000000
--- a/package_bgs/LBMixtureOfGaussians.cpp
+++ /dev/null
@@ -1,99 +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 "LBMixtureOfGaussians.h"
-
-using namespace bgslibrary::algorithms;
-
-LBMixtureOfGaussians::LBMixtureOfGaussians() :
-  sensitivity(81), bgThreshold(83), learningRate(59), noiseVariance(206)
-{
-  std::cout << "LBMixtureOfGaussians()" << std::endl;
-  setup("./config/LBMixtureOfGaussians.xml");
-}
-
-LBMixtureOfGaussians::~LBMixtureOfGaussians()
-{
-  delete m_pBGModel;
-  std::cout << "~LBMixtureOfGaussians()" << std::endl;
-}
-
-void LBMixtureOfGaussians::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage *frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    int w = cvGetSize(frame).width;
-    int h = cvGetSize(frame).height;
-
-    m_pBGModel = new BGModelMog(w, h);
-    m_pBGModel->InitModel(frame);
-  }
-
-  m_pBGModel->setBGModelParameter(0, sensitivity);
-  m_pBGModel->setBGModelParameter(1, bgThreshold);
-  m_pBGModel->setBGModelParameter(2, learningRate);
-  m_pBGModel->setBGModelParameter(3, noiseVariance);
-
-  m_pBGModel->UpdateModel(frame);
-
-  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("MOG Mask", img_foreground);
-    cv::imshow("MOG Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-
-  firstTime = false;
-}
-
-void LBMixtureOfGaussians::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "sensitivity", sensitivity);
-  cvWriteInt(fs, "bgThreshold", bgThreshold);
-  cvWriteInt(fs, "learningRate", learningRate);
-  cvWriteInt(fs, "noiseVariance", noiseVariance);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBMixtureOfGaussians::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 81);
-  bgThreshold = cvReadIntByName(fs, nullptr, "bgThreshold", 83);
-  learningRate = cvReadIntByName(fs, nullptr, "learningRate", 59);
-  noiseVariance = cvReadIntByName(fs, nullptr, "noiseVariance", 206);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBMixtureOfGaussians.h b/package_bgs/LBMixtureOfGaussians.h
deleted file mode 100644
index 8d4cb5619d42f85a74491cea340615f869b72d9a..0000000000000000000000000000000000000000
--- a/package_bgs/LBMixtureOfGaussians.h
+++ /dev/null
@@ -1,50 +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
-
-#include "IBGS.h"
-#include "lb/BGModelMog.h"
-
-using namespace lb_library;
-using namespace lb_library::MixtureOfGaussians;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBMixtureOfGaussians : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int bgThreshold;
-      int learningRate;
-      int noiseVariance;
-
-    public:
-      LBMixtureOfGaussians();
-      ~LBMixtureOfGaussians();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
-
diff --git a/package_bgs/LBP_MRF.cpp b/package_bgs/LBP_MRF.cpp
deleted file mode 100644
index b9e6bbe019511ccff12706fd40f4effbb479c054..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF.cpp
+++ /dev/null
@@ -1,84 +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/>.
-
-Csaba, Kertész: Texture-Based Foreground Detection, International Journal of Signal Processing,
-Image Processing and Pattern Recognition (IJSIP), Vol. 4, No. 4, 2011.
-
-*/
-#include "LBP_MRF.h"
-
-using namespace bgslibrary::algorithms;
-
-LBP_MRF::LBP_MRF() :
-  Detector(nullptr)
-{
-  std::cout << "LBP_MRF()" << std::endl;
-  setup("./config/LBP_MRF.xml");
-  Detector = new MotionDetection();
-  Detector->SetMode(MotionDetection::md_LBPHistograms);
-}
-
-LBP_MRF::~LBP_MRF()
-{
-  std::cout << "~LBP_MRF()" << std::endl;
-  delete Detector;
-  Detector = nullptr;
-}
-
-void LBP_MRF::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage TempImage(img_input);
-  MEImage InputImage(img_input.cols, img_input.rows, img_input.channels());
-  MEImage OutputImage(img_input.cols, img_input.rows, img_input.channels());
-
-  InputImage.SetIplImage((void*)&TempImage);
-
-  Detector->DetectMotions(InputImage);
-  Detector->GetMotionsMask(OutputImage);
-  img_foreground = cv::cvarrToMat((IplImage*)OutputImage.GetIplImage());
-  //bitwise_not(img_foreground, img_background);
-  img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("LBP-MRF FG", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void LBP_MRF::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBP_MRF::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBP_MRF.h b/package_bgs/LBP_MRF.h
deleted file mode 100644
index a6e5c05b984d6ee3c8beb6cc97f94804a8de506d..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF.h
+++ /dev/null
@@ -1,43 +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
-
-#include "IBGS.h"
-#include "LBP_MRF/MotionDetection.hpp"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBP_MRF : public IBGS
-    {
-    private:
-      MotionDetection* Detector;
-      cv::Mat img_segmentation;
-
-    public:
-      LBP_MRF();
-      ~LBP_MRF();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/LBP_MRF/MEDefs.cpp b/package_bgs/LBP_MRF/MEDefs.cpp
deleted file mode 100644
index 95b803333991104738bf58a771f7ff4882f9c488..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MEDefs.cpp
+++ /dev/null
@@ -1,57 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include "MEDefs.hpp"
-
-#include <math.h>
-
-float MERound(float number)
-{
-  double FracPart = 0.0;
-  double IntPart = 0.0;
-  float Ret = 0.0;
-
-  FracPart = modf((double)number, &IntPart);
-  if (number >= 0)
-  {
-    Ret = (float)(FracPart >= 0.5 ? IntPart + 1 : IntPart);
-  }
-  else {
-    Ret = (float)(FracPart <= -0.5 ? IntPart - 1 : IntPart);
-  }
-  return Ret;
-}
diff --git a/package_bgs/LBP_MRF/MEDefs.hpp b/package_bgs/LBP_MRF/MEDefs.hpp
deleted file mode 100644
index a886ee9ff3be75eb4c3841b38609fbd33dc30037..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MEDefs.hpp
+++ /dev/null
@@ -1,90 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-#pragma once
-
- /// Pi value
-#ifndef ME_PI_VALUE
-#define ME_PI_VALUE 3.14159265
-#endif
-
-/*! Process state */
-typedef enum {
-  ps_Min = 0,                /*!< Minimum value */
-  ps_Uninitialized = ps_Min, /*!< Uninitialized state */
-  ps_Initialized,            /*!< Initialized state */
-  ps_InProgress,             /*!< In progress state */
-  ps_Successful,             /*!< Successful state */
-  ps_Max = ps_Successful     /*!< Maximum value */
-} MEProcessStateType;
-
-template <typename T>
-const T& MEMin(const T& a, const T& b)
-{
-  if (a < b)
-    return a;
-  return b;
-}
-
-template <typename T>
-const T& MEMax(const T& a, const T& b)
-{
-  if (a < b)
-    return b;
-  return a;
-}
-
-template <typename T>
-const T& MEBound(const T& min, const T& val, const T& max)
-{
-  return MEMax(min, MEMin(max, val));
-}
-
-/*!
- * @brief Round a float number
- *
- * @param number number to round
- *
- * @return New float number
- *
- * This method rounds a float number, if the fraction is .5 or lower
- * then it rounds down, otherwise up.
- *
- */
-
-float MERound(float number);
-
-/** @} */
diff --git a/package_bgs/LBP_MRF/MEHistogram.hpp b/package_bgs/LBP_MRF/MEHistogram.hpp
deleted file mode 100644
index 0b2fb0dbd833f78fc7140e284fcb1ebd90925af5..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MEHistogram.hpp
+++ /dev/null
@@ -1,360 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-#pragma once
-
- /**
-  *  @addtogroup mindeye
-  *  @{
-  */
-
-class MEImage;
-
-/**
- * MEHistogram
- * @brief The class provides basic histogram operations
- */
-class MEHistogram
-{
-public:
-
-  /// Types of histogram calculation
-  typedef enum {
-    h_Min = 0,           /*!< Minimum value */
-    h_Overwrite = h_Min, /*!< Overwrite */
-    h_Add,               /*!< Add */
-    h_Max = h_Add        /*!< Maximum value */
-  } HistogramType;
-
-  /// Types of histogram stretching
-  typedef enum {
-    s_Min = 0,          /*!< Minimum value */
-    s_OwnMode = s_Min,  /*!< Own mode */
-    s_GimpMode,         /*!< Gimp mode */
-    s_Max = s_GimpMode  /*!< Maximum value */
-  } StretchType;
-
-  /// Constructor of class
-  MEHistogram();
-  /// Destructor of class
-  ~MEHistogram();
-
-  /*!
-   * @brief Clear histogram data
-   *
-   * Clear histogram data.
-   *
-   */
-
-  void Clear();
-
-  /*!
-   * @brief Equality (==) operator
-   *
-   * @param histogram Histogram to be compared
-   *
-   * @return True if the two histograms are equal.
-   *
-   * Compare two histograms.
-   *
-   */
-
-  bool operator==(MEHistogram& histogram) const;
-
-  /*!
-   * @brief Calculate the histogram of one color channel
-   *
-   * @param image Given image for the calculations
-   * @param channel Selected color channel for calculation (Range: 1..x)
-   * @param mode The mode of calculation.
-   *
-   * The method calculates the histograms of a color channel.
-   * There is two different type of the function:
-   *
-   * - h_Add: Add the data to the existing histogram.
-   * - h_Overwrite: Clear the histogram data before the
-   * calculation.
-   *
-   */
-
-  void Calculate(MEImage& image, int channel, HistogramType mode);
-
-  /*!
-   * @brief Calculate the average histogram of an image
-   *
-   * @param image Given image for the calculations
-   * @param mode Histogram calculation mode
-   *
-   * The method calculates the average histogram of an image.
-   *
-   */
-
-  void Calculate(MEImage& image, HistogramType mode = h_Overwrite);
-
-  /*!
-   * @brief Calculate the histogram of an image region
-   *
-   * @param image Given image for the calculations
-   * @param channel Selected color channel for calculation (Range: 1..x)
-   * @param x0 x0 coordinate of the region
-   * @param y0 y0 coordinate of the region
-   * @param x1 x1 coordinate of the region
-   * @param y1 y1 coordinate of the region
-   *
-   * The method calculates the average histogram of an image region
-   * (x0,y0)-(x1,y1).
-   *
-   */
-
-  void Calculate(MEImage& image, int channel, int x0, int y0, int x1, int y1);
-
-  /*!
-   * @brief Get the index of maximum value of the histogram
-   *
-   * @return Index number
-   *
-   * Function gives an index value back where is the highest
-   * peak of the histogram.
-   *
-   */
-
-  int GetPeakIndex() const;
-
-  /*!
-   * @brief Get the lowest histogram index with an threshold value
-   *
-   * @param threshold Specified threshold (in percent: 0..100 %)
-   *
-   * @return Index number
-   *
-   * Function gives the lowest index back whose value reaches
-   * an threshold value calculated by (counted pixel number /
-   * 10*threshold / 100).
-   *
-   */
-
-  int GetLowestLimitIndex(int threshold) const;
-
-  /*!
-   * @brief Get the highest histogram index with an threshold value
-   *
-   * @param threshold Specified threshold (in percent: 0..100 %)
-   *
-   * @return Index number
-   *
-   * Function gives the highest index back whose value reaches
-   * an threshold value calculated by (counted pixel number /
-   * 10*threshold / 100).
-   *
-   */
-
-  int GetHighestLimitIndex(int threshold) const;
-
-  /*!
-   * @brief Get the amount of the histogram values in an interval
-   *
-   * @param minindex Minimal index of the interval
-   * @param maxindex Maximal index of the interval
-   *
-   * @return Amount of the values
-   *
-   * Function calculates the amount of the histogram values
-   * in a given interval.
-   *
-   */
-
-  int GetPowerAmount(int min_index, int max_index) const;
-
-  /*!
-   * @brief Get index value of the centroid point of the histogram
-   *
-   * @return Index number
-   *
-   * Function calculates the centre of area of the histogram and
-   * gives the index number back.
-   *
-   */
-
-  int GetCentroidIndex() const;
-
-  /*!
-   * @brief Stretch the histogram
-   *
-   * @param mode Mode of the histogram stretching
-   *
-   * @return True if successful, otherwise false.
-   *
-   * The function selects and stretches the main power
-   * interval of the histogram. The following calculation
-   * modes are available:
-   *
-   * - s_OwnMode: The calculation of the power
-   * interval is selected by functions Histogram::GetHistogramLowestLimitIndex()
-   * and Histogram::GetHistogramHighestLimitIndex() where the
-   * threshold is 20, 10, 5, 2, 1 in order. The power range will
-   * be selected if the length is at least 52 long or the used
-   * threshold reaches the 1 value.
-   * - s_GimpMode: The minimum index of power interval is
-   * specified by the first fulfilled abs(percentage[i]-0.006) <
-   * fabs(percentage[i+1]-0.006) where the percentage[i] means
-   * the amount of the histogram values in the interval [0, i].
-   * The maximum index is specified by the first fulfilled
-   * (from the end of the histogram) abs(percentage[i]-0.006) <
-   * fabs(percentage[i-1]-0.006) where the percentage[i] means
-   * the amount of the histogram values in the interval [i, 255].
-   *
-   * The stretch operation is rejected if the power interval is
-   * less than 10 or less than 20 and the percentage[min_index, max_index]
-   * / percentage[0, 255] < 0.2.
-   *
-   */
-
-  bool Stretch(StretchType mode);
-
-  /// Histogram spectrum
-  int HistogramData[256];
-};
-
-
-/**
- * MEHistogramTransform
- * @brief The class provides histogram operations
- */
-class MEHistogramTransform
-{
-public:
-  /// Types of histogram processing
-  typedef enum {
-    p_Min = 0,                   /*!< Minimum value */
-    p_SeparateChannels = p_Min, /*!< Separate channels */
-    p_Average,                   /*!< Average */
-    p_Max = p_Average           /*!< Maximum value */
-  } ProcessingType;
-
-  /// Types of histogram transformations
-  typedef enum {
-    t_Min = 0,             /*!< Minimum value */
-    t_Continuous = t_Min, /*!< Continuous */
-    t_Discrete,            /*!< Discrete */
-    t_Max = t_Discrete    /*!< Maximum value */
-  } TransformType;
-
-  /// Constructor of class
-  MEHistogramTransform();
-  /// Destructor of class
-  ~MEHistogramTransform();
-
-  /*!
-   * @brief Histogram stretching an image
-   *
-   * @param image Source image to stretch
-   *
-   * The function stretches the histogram of the given image with
-   * default parameters: process the color channels separately
-   * and continuously.
-   *
-   */
-
-  void HistogramStretch(MEImage& image);
-
-  /*!
-   * @brief Histogram stretching with specified parameters
-   *
-   * @param image Source image to stretch
-   * @param time_mode Mode of the histogram stretching
-   *
-   * The function transformations the histogram of the image.
-   * There is some different possibilities to make the operation:
-   *
-   * - t_Continuous: The function always stretches the
-   * image at each call of the method.
-   * - t_Discrete: A histogram is calculated at the first
-   * call of the function and all further images will be
-   * stretched by this initial histogram.
-   *
-   */
-
-  void HistogramStretch(MEImage& image, TransformType time_mode);
-
-  /*!
-   * @brief Histogram equalization on an image
-   *
-   * @param image Source image to equalize
-   *
-   * The source image is transformed by histogram
-   * equalization.
-   *
-   */
-
-  void HistogramEqualize(MEImage& image);
-
-  /*!
-   * @brief Set the process mode of the histogram transformation
-   *
-   * @param new_channel_mode New mode of processing channels
-   * @param new_stretch_mode New mode of histogram stretching
-   *
-   * The process mode of histogram transformation can be
-   * set by this method. Two process modes are available for
-   * processing channels:
-   *
-   * - p_SeparateChannels: The class processes the color channels
-   * separately.
-   * - p_Average: The color channels are averaged
-   * in the histogram operations.
-   *
-   * Two process modes are usable for histogram stretching:
-   * s_OwnMode and s_GimpMode. See Histogram::Stretch()
-   * for more details.
-   *
-   */
-
-  void SetStretchProcessingMode(ProcessingType new_channel_mode, MEHistogram::StretchType new_stretch_mode);
-
-private:
-  /// Type of the process of histograms
-  ProcessingType ChannelMode;
-  /// Stretch mode
-  MEHistogram::StretchType StretchMode;
-  /// Histograms for red, green and blue color channels
-  MEHistogram RedChannel, GreenChannel, BlueChannel;
-  /// Histogram for average calculation
-  MEHistogram AverageChannel;
-  /// Continuous histogram stretch is done already
-  bool DiscreteStretchingDone;
-};
-
-/** @} */
diff --git a/package_bgs/LBP_MRF/MEImage.cpp b/package_bgs/LBP_MRF/MEImage.cpp
deleted file mode 100644
index b01d494e1091985dc04d312aa99712d440fea80e..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MEImage.cpp
+++ /dev/null
@@ -1,1487 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include "MEImage.hpp"
-
-#include <opencv2/opencv.hpp>
-
-#include "MEDefs.hpp"
-
-#define ME_CAST_TO_IPLIMAGE(image_ptr) ((IplImage*)image_ptr)
-#define ME_RELEASE_IPLIMAGE(image_ptr) \
-  cvReleaseImage((IplImage**)&image_ptr); \
-  image_ptr = NULL;
-
- // RGB to YUV transform
-const float RGBtoYUVMatrix[3][3] =
-{ { 0.299, 0.587, 0.114 },
- { -0.147, -0.289, 0.436 },
- { 0.615, -0.515, -0.100 } };
-
-// RGB to YIQ transform
-const float RGBtoYIQMatrix[3][3] =
-{ { 0.299, 0.587, 0.114 },
- { 0.596, -0.274, -0.322 },
- { 0.212, -0.523, 0.311 } };
-
-MEImage::MEImage(int width, int height, int layers) : cvImg(NULL)
-{
-  _Init(width, height, layers);
-}
-
-
-MEImage::MEImage(const MEImage& other) : cvImg(NULL)
-{
-  _Copy(other);
-}
-
-
-MEImage::~MEImage()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg))
-  {
-    ME_RELEASE_IPLIMAGE(cvImg);
-  }
-}
-
-
-void MEImage::Clear()
-{
-  cvSetZero(ME_CAST_TO_IPLIMAGE(cvImg));
-}
-
-
-void MEImage::GetLayer(MEImage& new_layer, int layer_number) const
-{
-  int LayerNumber = layer_number;
-
-  if ((new_layer.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width) ||
-    (new_layer.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height) ||
-    (new_layer.GetLayers() != 1))
-  {
-    new_layer.Realloc(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height, 1);
-  }
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels < LayerNumber)
-  {
-    printf("The given layer number is too large (%d > %d)\n",
-      LayerNumber, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-    LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
-  }
-  if (LayerNumber <= 0)
-  {
-    printf("The given layer number is too small (%d <= 0)\n", LayerNumber);
-    LayerNumber = 1;
-  }
-
-  cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), LayerNumber);
-  cvCopy(ME_CAST_TO_IPLIMAGE(cvImg), (IplImage*)new_layer.GetIplImage(), NULL);
-  cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), 0);
-}
-
-
-void MEImage::SetLayer(MEImage& layer, int layer_number)
-{
-  int LayerNumber = layer_number;
-
-  if (layer.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    layer.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height)
-  {
-    printf("The dimensions of the layer and "
-      "destination image is different (%dx%d <> %dx%d)\n",
-      layer.GetWidth(), layer.GetHeight(), ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height);
-    return;
-  }
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels < LayerNumber)
-  {
-    printf("The given layer number is too large (%d > %d)\n",
-      LayerNumber, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
-  }
-  if (LayerNumber <= 0)
-  {
-    printf("The given layer number is too small (%d <= 0)\n", LayerNumber);
-    LayerNumber = 1;
-  }
-  if (layer.GetLayers() != 1)
-  {
-    printf("The layer image has not one color channel (1 != %d)\n",
-      layer.GetLayers());
-    return;
-  }
-  cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), LayerNumber);
-  cvCopy((IplImage*)layer.GetIplImage(), ME_CAST_TO_IPLIMAGE(cvImg), NULL);
-  cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), 0);
-}
-
-
-void MEImage::CopyImageData(unsigned char* data)
-{
-  memcpy(ME_CAST_TO_IPLIMAGE(cvImg)->imageData, data, ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-}
-
-
-void* MEImage::GetIplImage() const
-{
-  return (void*)ME_CAST_TO_IPLIMAGE(cvImg);
-}
-
-
-void MEImage::SetIplImage(void* image)
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg))
-  {
-    ME_RELEASE_IPLIMAGE(cvImg);
-  }
-  cvImg = cvCloneImage((IplImage*)image);
-  // Correct the origin of the image
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->origin == 1)
-  {
-    MirrorVertical();
-    ME_CAST_TO_IPLIMAGE(cvImg)->origin = 0;
-  }
-}
-
-
-bool MEImage::operator==(const MEImage& image)
-{
-  return Equal(image);
-}
-
-
-bool MEImage::operator!=(const MEImage& image)
-{
-  return !operator==(image);
-}
-
-
-MEImage& MEImage::operator=(const MEImage& other_image)
-{
-  if (&other_image == this)
-    return *this;
-
-  _Copy(other_image);
-  return *this;
-}
-
-
-int MEImage::GetWidth() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : 0;
-}
-
-
-int MEImage::GetRowWidth() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->widthStep : 0;
-}
-
-
-int MEImage::GetHeight() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : 0;
-}
-
-
-int MEImage::GetLayers() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->nChannels : 0;
-}
-
-
-int MEImage::GetPixelDataNumber() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? GetWidth()*GetHeight()*GetLayers() : 0;
-}
-
-
-unsigned char* MEImage::GetImageData() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData : NULL;
-}
-
-
-void MEImage::SetData(unsigned char* image_data, int width, int height, int channels)
-{
-  _Init(width, height, channels);
-
-  for (int y = height - 1; y >= 0; --y)
-  {
-    int Start = GetRowWidth()*y;
-    int Start2 = width*channels*y;
-
-    memcpy(&ME_CAST_TO_IPLIMAGE(cvImg)->imageData[Start], &image_data[Start2], width*channels);
-  }
-}
-
-
-float MEImage::GetRatio() const
-{
-  return ME_CAST_TO_IPLIMAGE(cvImg) ? (float)ME_CAST_TO_IPLIMAGE(cvImg)->height / (float)ME_CAST_TO_IPLIMAGE(cvImg)->width : 0.0;
-}
-
-
-void MEImage::Realloc(int width, int height)
-{
-  Realloc(width, height, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-}
-
-
-void MEImage::Realloc(int width, int height, int layers)
-{
-  _Init(width, height, layers);
-}
-
-
-void MEImage::Resize(int new_width, int new_height)
-{
-  if (new_height < 1)
-  {
-    printf("Invalid new height: %d < 1\n", new_height);
-    return;
-  }
-  if (new_width < 1)
-  {
-    printf("Invalid new width: %d < 1\n", new_width);
-    return;
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(new_width, new_height), 8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  cvResize(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_INTER_NN);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::ResizeScaleX(int new_width)
-{
-  if (new_width < 1)
-  {
-    printf("Invalid new width: %d < 1\n", new_width);
-    return;
-  }
-  Resize(new_width, (int)((float)new_width*GetRatio()));
-}
-
-
-void MEImage::ResizeScaleY(int new_height)
-{
-  if (new_height < 1)
-  {
-    printf("Invalid new height: %d < 1\n", new_height);
-    return;
-  }
-  Resize((int)((float)new_height * 1 / GetRatio()), new_height);
-}
-
-
-void MEImage::MirrorHorizontal()
-{
-  cvFlip(ME_CAST_TO_IPLIMAGE(cvImg), NULL, 1);
-}
-
-
-void MEImage::MirrorVertical()
-{
-  cvFlip(ME_CAST_TO_IPLIMAGE(cvImg), NULL, 0);
-}
-
-
-void MEImage::Crop(int x1, int y1, int x2, int y2)
-{
-  int NewX1 = x1;
-  int NewY1 = y1;
-  int NewX2 = x2;
-  int NewY2 = y2;
-
-  NewX1 = (NewX1 < 0) ? 0 : NewX1;
-  NewX1 = (NewX1 > ME_CAST_TO_IPLIMAGE(cvImg)->width) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : NewX1;
-  NewY1 = (NewY1 < 0) ? 0 : NewY1;
-  NewY1 = (NewY1 > ME_CAST_TO_IPLIMAGE(cvImg)->height) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : NewY1;
-
-  NewX2 = (NewX2 < 0) ? 0 : NewX2;
-  NewX2 = (NewX2 > ME_CAST_TO_IPLIMAGE(cvImg)->width) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : NewX2;
-  NewY2 = (NewY2 < 0) ? 0 : NewY2;
-  NewY2 = (NewY2 > ME_CAST_TO_IPLIMAGE(cvImg)->height) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : NewY2;
-
-  if ((NewX2 - NewX1) <= 0)
-  {
-    printf("Invalid new width: %d <= 0\n", NewX2 - NewX1);
-    return;
-  }
-  if ((NewY2 - NewY1) <= 0)
-  {
-    printf("Invalid new height: %d <= 0\n", NewY2 - NewY1);
-    return;
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(NewX2 - NewX1, NewY2 - NewY1), 8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  cvSetImageROI(ME_CAST_TO_IPLIMAGE(cvImg), cvRect(NewX1, NewY1, NewX2 - NewX1, NewY2 - NewY1));
-  cvCopy(ME_CAST_TO_IPLIMAGE(cvImg), TempImg);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::CopyImageInside(int x, int y, MEImage& source_image)
-{
-  int NewX = x;
-  int NewY = y;
-  int PasteLengthX = source_image.GetWidth();
-  int PasteLengthY = source_image.GetHeight();
-
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != source_image.GetLayers())
-  {
-    if (source_image.GetLayers() == 1 && ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 3)
-    {
-      source_image.ConvertGrayscaleToRGB();
-    }
-    if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1 && source_image.GetLayers() == 3)
-    {
-      source_image.ConvertToGrayscale(g_OpenCV);
-    }
-  }
-  if (NewX < 0)
-    NewX = 0;
-  if (NewX > ME_CAST_TO_IPLIMAGE(cvImg)->width)
-    NewX = ME_CAST_TO_IPLIMAGE(cvImg)->width;
-  if (NewY < 0)
-    NewY = 0;
-  if (NewY > ME_CAST_TO_IPLIMAGE(cvImg)->height)
-    NewY = ME_CAST_TO_IPLIMAGE(cvImg)->height;
-  if (NewX + PasteLengthX > ME_CAST_TO_IPLIMAGE(cvImg)->width)
-    PasteLengthX = ME_CAST_TO_IPLIMAGE(cvImg)->width - NewX;
-  if (NewY + PasteLengthY > ME_CAST_TO_IPLIMAGE(cvImg)->height)
-    PasteLengthY = ME_CAST_TO_IPLIMAGE(cvImg)->height - NewY;
-
-  if (PasteLengthX != source_image.GetWidth() ||
-    PasteLengthY != source_image.GetHeight())
-  {
-    source_image.Resize(PasteLengthX, PasteLengthY);
-  }
-  cvSetImageROI(ME_CAST_TO_IPLIMAGE(cvImg), cvRect(NewX, NewY, PasteLengthX, PasteLengthY));
-  cvCopy((IplImage*)source_image.GetIplImage(), ME_CAST_TO_IPLIMAGE(cvImg));
-  cvResetImageROI(ME_CAST_TO_IPLIMAGE(cvImg));
-}
-
-
-void MEImage::Erode(int iterations)
-{
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-    ME_CAST_TO_IPLIMAGE(cvImg)->height),
-    8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  cvErode(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, NULL, iterations);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::Dilate(int iterations)
-{
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-    ME_CAST_TO_IPLIMAGE(cvImg)->height),
-    8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  cvDilate(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, NULL, iterations);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::Smooth()
-{
-  SmoothAdvanced(s_Median, 3);
-}
-
-
-void MEImage::SmoothAdvanced(SmoothType filtermode, int filtersize)
-{
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-    ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  switch (filtermode)
-  {
-  case s_Blur:
-    cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_BLUR, filtersize, filtersize, 0);
-    break;
-  case s_Median:
-    cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_MEDIAN, filtersize, 0, 0);
-    break;
-  case s_Gaussian:
-    cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_GAUSSIAN, filtersize, filtersize, 0);
-    break;
-  default:
-    cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_MEDIAN, filtersize, 0, 0);
-    break;
-  }
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::Canny()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-    ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-  cvCanny(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 800, 1100, 5);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::Laplace()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-    ME_CAST_TO_IPLIMAGE(cvImg)->height),
-    IPL_DEPTH_16S, 1);
-  cvLaplace(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 3);
-  cvConvertScale(TempImg, ME_CAST_TO_IPLIMAGE(cvImg), 1, 0);
-  ME_RELEASE_IPLIMAGE(cvImg);
-}
-
-
-void MEImage::Quantize(int levels)
-{
-  if (levels <= 0)
-  {
-    printf("Level number is too small (%d <= 0)\n", levels);
-    return;
-  }
-  if (levels > 256)
-  {
-    printf("Level number is too large (%d > 256)\n", levels);
-    return;
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-
-  for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
-  {
-    ImageData[i] = ImageData[i] / (256 / levels)*(256 / levels);
-  }
-}
-
-
-void MEImage::Threshold(int threshold_limit)
-{
-  if (threshold_limit < 0)
-  {
-    printf("Threshold number is too small (%d <= 0)\n", threshold_limit);
-    return;
-  }
-  if (threshold_limit > 255)
-  {
-    printf("Threshold number is too large (%d > 255)\n", threshold_limit);
-    return;
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-
-  for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
-  {
-    if (ImageData[i] < threshold_limit)
-    {
-      ImageData[i] = 0;
-    }
-  }
-}
-
-
-void MEImage::AdaptiveThreshold()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-    ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-  cvAdaptiveThreshold(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 25,
-    CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, -7);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::ThresholdByMask(MEImage& mask_image)
-{
-  if (mask_image.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    mask_image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height)
-  {
-    printf("Image properties are different\n");
-    return;
-  }
-  if (mask_image.GetLayers() != 3 && ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 3)
-  {
-    mask_image.ConvertGrayscaleToRGB();
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* MaskImageData = mask_image.GetImageData();
-
-  for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
-  {
-    if (MaskImageData[i] == 0)
-    {
-      ImageData[i] = 0;
-    }
-  }
-}
-
-
-void MEImage::ColorSpace(ColorSpaceConvertType mode)
-{
-  IplImage* TempImg = NULL;
-  unsigned char* ImageData = NULL;
-  int WidthStep = 0;
-  int RowStart = 0;
-
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1)
-  {
-    printf("No sense to convert: source image is greyscale\n");
-    ConvertGrayscaleToRGB();
-  }
-  switch (mode)
-  {
-  case csc_RGBtoXYZCIED65:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-      ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2XYZ);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_XYZCIED65toRGB:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-      ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_XYZ2RGB);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_RGBtoHSV:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-      ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2HSV);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_HSVtoRGB:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
-      ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_HSV2RGB);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_RGBtoHLS:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2HLS);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_HLStoRGB:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_HLS2RGB);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_RGBtoCIELab:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2Lab);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_CIELabtoRGB:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_Lab2RGB);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_RGBtoCIELuv:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2Luv);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_CIELuvtoRGB:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_Luv2RGB);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case csc_RGBtoYUV:
-    ComputeColorSpace(csc_RGBtoYUV);
-    break;
-
-  case csc_RGBtoYIQ:
-    ComputeColorSpace(csc_RGBtoYIQ);
-    break;
-
-  case csc_RGBtorgI:
-    ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-    WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-    RowStart = 0;
-    for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-    {
-      for (int x = (ME_CAST_TO_IPLIMAGE(cvImg)->width - 1) * 3; x >= 0; x -= 3)
-      {
-        int r = 0;
-        int g = 0;
-        int I = 0;
-
-        I = (int)ImageData[RowStart + x] + (int)ImageData[RowStart + x + 1] + (int)ImageData[RowStart + x + 2];
-        r = (int)((float)ImageData[RowStart + x] / I * 255);
-        g = (int)((float)ImageData[RowStart + x + 1] / I * 255);
-        ImageData[RowStart + x] = (unsigned char)r;
-        ImageData[RowStart + x + 1] = (unsigned char)g;
-        ImageData[RowStart + x + 2] = (unsigned char)(I / 3);
-      }
-      RowStart += WidthStep;
-    }
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MEImage::ConvertToGrayscale(GrayscaleType grayscale_mode)
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1)
-  {
-    printf("Image is already grayscale\n");
-    return;
-  }
-  IplImage* TempImg = NULL;
-  unsigned char* ImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* ImageData = NULL;
-
-  switch (grayscale_mode)
-  {
-  case g_Average:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
-    ImageData = (unsigned char*)TempImg->imageData;
-
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 3; i >= 0; i -= 3)
-    {
-      ImageData[i / 3] = (ImgData[i] + ImgData[i + 1] + ImgData[i + 2]) / 3;
-    }
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  case g_OpenCV:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
-    cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2GRAY);
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MEImage::ConvertGrayscaleToRGB()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
-  {
-    return;
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 3);
-
-  cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_GRAY2RGB);
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::ConvertBGRToRGB()
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 3)
-  {
-    return;
-  }
-  cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), ME_CAST_TO_IPLIMAGE(cvImg), CV_RGB2BGR);
-}
-
-
-void MEImage::LBP(LBPType mode)
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
-  unsigned char* TempImgData = (unsigned char*)TempImg->imageData;
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int WidthStep_2 = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep * 2;
-
-  cvSetZero(TempImg);
-  switch (mode)
-  {
-  case lbp_Normal:
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*(ME_CAST_TO_IPLIMAGE(cvImg)->height - 2) - 1; i >= ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1; --i)
-    {
-      TempImgData[i] =
-        (ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1]) +
-        ((ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep]) * 2) +
-        ((ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1]) * 4) +
-        ((ImageData[i] <= ImageData[i - 1]) * 8) +
-        ((ImageData[i] <= ImageData[i + 1]) * 16) +
-        ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1]) * 32) +
-        ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep]) * 64) +
-        ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1]) * 128);
-    }
-    break;
-
-  case lbp_Special:
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*(ME_CAST_TO_IPLIMAGE(cvImg)->height - 3) - 2; i >= ME_CAST_TO_IPLIMAGE(cvImg)->widthStep * 2 + 2; --i)
-    {
-      int CenterPixel = (ImageData[i + 1] + ImageData[i - 1] +
-        ImageData[i - WidthStep] + ImageData[i + WidthStep]) / 4;
-      TempImgData[i] = ((CenterPixel <= (ImageData[i - (WidthStep_2)-2] +
-        ImageData[i - (WidthStep_2)-1] +
-        ImageData[i - WidthStep - 2] +
-        ImageData[i - WidthStep - 1]) / 4)) +
-        ((CenterPixel <= (ImageData[i - WidthStep] +
-          ImageData[i - (WidthStep_2)]) / 2) * 2) +
-          ((CenterPixel <= ((ImageData[i - (WidthStep_2)+2] +
-            ImageData[i - (WidthStep_2)+1] +
-            ImageData[i - WidthStep + 2] +
-            ImageData[i - WidthStep + 1]) / 4)) * 4) +
-            ((CenterPixel <= (ImageData[i - 1] +
-              ImageData[i - 2]) / 2) * 8) +
-              ((CenterPixel <= (ImageData[i + 1] +
-                ImageData[i + 2]) / 2) * 16) +
-                ((CenterPixel <= ((ImageData[i + (WidthStep_2)-2] +
-                  ImageData[i + (WidthStep_2)-1] +
-                  ImageData[i + WidthStep - 2] +
-                  ImageData[i + WidthStep - 1]) / 4)) * 32) +
-                  ((CenterPixel <= (ImageData[i + WidthStep] +
-                    ImageData[i - WidthStep_2]) / 2) * 64) +
-                    ((CenterPixel <= ((ImageData[i + (WidthStep_2)+2] +
-                      ImageData[i + (WidthStep_2)+1] +
-                      ImageData[i + WidthStep + 2] +
-                      ImageData[i + WidthStep + 1]) / 4)) * 128);
-    }
-    break;
-
-  default:
-    break;
-  }
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-void MEImage::Binarize(int threshold)
-{
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-
-  for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
-  {
-    if (ImageData[i] >= threshold)
-    {
-      ImageData[i] = 255;
-    }
-    else {
-      ImageData[i] = 0;
-    }
-  }
-}
-
-
-void MEImage::Subtract(MEImage& source, SubtractModeType mode)
-{
-  if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
-    source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
-  {
-    printf("Image properties are different.\n");
-    return;
-  }
-  unsigned char* ImageData = NULL;
-  unsigned char* DstData = NULL;
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-
-  switch (mode)
-  {
-  case sub_Normal:
-    ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-    DstData = source.GetImageData();
-    RowStart = 0;
-
-    for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-    {
-      for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-      {
-        ImageData[RowStart + x] =
-          ImageData[RowStart + x] - DstData[RowStart + x] < 0 ? 0 :
-          ImageData[RowStart + x] - DstData[RowStart + x];
-      }
-      RowStart += WidthStep;
-    }
-    break;
-
-  case sub_Absolut:
-    ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-    DstData = source.GetImageData();
-    RowStart = 0;
-
-    for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-    {
-      for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-      {
-        ImageData[RowStart + x] = ImageData[RowStart + x] -
-          DstData[RowStart + x] < 0 ? -ImageData[RowStart + x] +
-          DstData[RowStart + x] : ImageData[RowStart + x] - DstData[RowStart + x];
-      }
-      RowStart += WidthStep;
-    }
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MEImage::Multiple(MEImage& source, MultiplicationType mode)
-{
-  if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
-    source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
-  {
-    printf("Image properties are different.\n");
-    return;
-  }
-  float Result = 0.0;
-  IplImage* TempImg = NULL;
-  unsigned char* ImageData = NULL;
-  unsigned char* ImageData2 = NULL;
-  unsigned char* ImageData3 = NULL;
-  unsigned char* DstData = NULL;
-
-  switch (mode)
-  {
-  case m_Normal:
-    Result = 0;
-    ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-    DstData = source.GetImageData();
-
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
-    {
-      if ((ImageData[i] >= 128) && (DstData[i] >= 128))
-      {
-        Result = (float)ImageData[i] / 128 * (float)DstData[i] / 128;
-
-        if (Result >= 1)
-        {
-          ImageData[i] = 255;
-        }
-        else {
-          ImageData[i] = 0;
-        }
-      }
-      else {
-        ImageData[i] = 0;
-      }
-    }
-    break;
-
-  case m_Neighbourhood:
-    TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-      ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    ImageData2 = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-    DstData = source.GetImageData();
-    ImageData3 = (unsigned char*)TempImg->imageData;
-
-    for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-      for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width - 1; x >= 0; --x)
-        for (int l = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; l >= 0; --l)
-        {
-          if (((DstData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
-            x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] == 255) ||
-            (ImageData2[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
-              x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] == 255)) &&
-              (NeighbourhoodCounter(x - 2, y - 2, n_5x5) > 3) &&
-            (source.NeighbourhoodCounter(x - 2, y - 2, n_5x5) > 3))
-          {
-            ImageData3[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
-              x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] = 255;
-          }
-        }
-    ME_RELEASE_IPLIMAGE(cvImg);
-    cvImg = TempImg;
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MEImage::Addition(MEImage& source, AdditionType mode)
-{
-  if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
-    source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
-  {
-    printf("Image properties are different.\n");
-    return;
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* DstData = source.GetImageData();
-
-  switch (mode)
-  {
-  case a_Average:
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
-    {
-      ImageData[i] = (ImageData[i] + DstData[i]) / 2;
-    }
-    break;
-
-  case a_Union:
-    for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
-    {
-      if (DstData[i] > ImageData[i])
-      {
-        ImageData[i] = DstData[i];
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MEImage::EliminateSinglePixels()
-{
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-    ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* DstData = (unsigned char*)TempImg->imageData;
-  int sum = 0;
-  int xy = 0;
-  int ywidth = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width - 1; x >= 0; --x)
-    {
-      xy = y*ywidth + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
-
-      for (int l = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; l >= 0; --l)
-      {
-        if ((ImageData[xy + l] > 0) && (x > 0) && (y > 0) && (x < ME_CAST_TO_IPLIMAGE(cvImg)->width - 1) && (y < ME_CAST_TO_IPLIMAGE(cvImg)->height - 1))
-        {
-          sum = (ImageData[xy - ywidth - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
-            (ImageData[xy - ywidth + l] > 0) +
-            (ImageData[xy - ywidth + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
-            (ImageData[xy - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
-            (ImageData[xy + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
-            (ImageData[xy + ywidth - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
-            (ImageData[xy + ywidth + l] > 0) +
-            (ImageData[xy + ywidth + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0);
-
-          if (sum > 3)
-          {
-            DstData[xy + l] = 255;
-          }
-          else {
-            DstData[xy + l] = 0;
-          }
-        }
-        else {
-          DstData[xy + l] = 0;
-        }
-      }
-    }
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
-
-
-float MEImage::DifferenceAreas(MEImage& reference, int difference) const
-{
-  if (reference.GetWidth() != GetWidth() ||
-    reference.GetHeight() != GetHeight() ||
-    reference.GetLayers() != GetLayers())
-  {
-    printf("Image dimensions or channels are different\n");
-    return -1.0;
-  }
-  float PixelDiff = 0.0;
-  int Pixels = 0;
-  unsigned char* OrigImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* RefImgData = reference.GetImageData();
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-  {
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-    {
-      if (abs(OrigImgData[RowStart + x] - RefImgData[RowStart + x]) > difference)
-        Pixels++;
-    }
-    RowStart += WidthStep;
-  }
-  PixelDiff = (float)Pixels / (ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep) * 100;
-  return PixelDiff;
-}
-
-
-int MEImage::AverageDifference(MEImage& reference) const
-{
-  if (reference.GetWidth() != GetWidth() ||
-    reference.GetHeight() != GetHeight() ||
-    reference.GetLayers() != GetLayers())
-  {
-    printf("Image dimensions or channels are different\n");
-    return -1;
-  }
-  int Difference = 0;
-  unsigned char* OrigImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* RefImgData = reference.GetImageData();
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-  {
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-    {
-      Difference += abs(OrigImgData[RowStart + x] - RefImgData[RowStart + x]);
-    }
-    RowStart += WidthStep;
-  }
-  Difference = Difference / (ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep);
-  return Difference;
-}
-
-
-void MEImage::Minimum(MEImage& image)
-{
-  if (image.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
-    image.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
-  {
-    printf("Image properties are different\n");
-    return;
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* SecData = image.GetImageData();
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-  {
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-    {
-      ImageData[RowStart + x] = ImageData[RowStart + x] > SecData[RowStart + x] ?
-        SecData[RowStart + x] : ImageData[RowStart + x];
-    }
-    RowStart += WidthStep;
-  }
-}
-
-
-float MEImage::AverageBrightnessLevel() const
-{
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-  int BrightnessLevel = 0;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-  {
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-    {
-      BrightnessLevel += (int)ImageData[RowStart + x];
-    }
-    RowStart += WidthStep;
-  }
-  return BrightnessLevel / (GetWidth()*GetHeight()*GetLayers());
-}
-
-
-bool MEImage::Equal(const MEImage& reference) const
-{
-  return Equal(reference, 1);
-}
-
-
-bool MEImage::Equal(const MEImage& reference, int maxabsdiff) const
-{
-  bool Ret = true;
-
-  if (reference.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
-    reference.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
-    reference.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
-  {
-    printf("Image properties are different\n");
-    return false;
-  }
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* RefData = reference.GetImageData();
-  int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
-  int RowStart = 0;
-
-  for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
-  {
-    for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
-    {
-      if (abs(ImageData[RowStart + x] - RefData[RowStart + x]) >= maxabsdiff)
-      {
-        Ret = false;
-        return Ret;
-      }
-    }
-    RowStart += WidthStep;
-  }
-  return Ret;
-}
-
-
-unsigned char MEImage::GrayscalePixel(int x, int y) const
-{
-  int NewX = x;
-  int NewY = y;
-
-  NewX = NewX < 0 ? 0 : NewX;
-  NewX = NewX > ME_CAST_TO_IPLIMAGE(cvImg)->width - 1 ? ME_CAST_TO_IPLIMAGE(cvImg)->width - 1 : NewX;
-  NewY = NewY < 0 ? 0 : NewY;
-  NewY = NewY > ME_CAST_TO_IPLIMAGE(cvImg)->height - 1 ? ME_CAST_TO_IPLIMAGE(cvImg)->height - 1 : NewY;
-
-  float Sum = 0;
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-
-  for (int l = 0; l < ME_CAST_TO_IPLIMAGE(cvImg)->nChannels; l++)
-  {
-    Sum = Sum + (int)ImageData[NewY*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + NewX*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l];
-  }
-  Sum = Sum / ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
-  return (unsigned char)(Sum);
-}
-
-
-int MEImage::NeighbourhoodCounter(int startx, int starty,
-  NeighbourhoodType neighbourhood) const
-{
-  int IterX = 0;
-  int IterY = 0;
-  int Counter = 0;
-
-  // Determine the iteration numbers
-  switch (neighbourhood)
-  {
-  case n_2x2:
-    IterX = 2;
-    IterY = 2;
-    break;
-
-  case n_3x3:
-    IterX = 3;
-    IterY = 3;
-    break;
-
-  case n_3x2:
-    IterX = 2;
-    IterY = 3;
-    break;
-
-  case n_5x5:
-    IterX = 5;
-    IterY = 5;
-    break;
-
-  case n_7x7:
-    IterX = 7;
-    IterY = 7;
-    break;
-
-  default:
-    IterX = 3;
-    IterY = 3;
-    break;
-  }
-
-  int NewStartX = startx;
-  int NewStartY = starty;
-
-  NewStartX = startx < 0 ? 0 : startx;
-  NewStartX = startx >= ME_CAST_TO_IPLIMAGE(cvImg)->width - IterX ? ME_CAST_TO_IPLIMAGE(cvImg)->width - IterX - 1 : startx;
-  NewStartY = starty < 0 ? 0 : starty;
-  NewStartY = starty >= ME_CAST_TO_IPLIMAGE(cvImg)->height - IterY ? ME_CAST_TO_IPLIMAGE(cvImg)->height - IterY - 1 : starty;
-
-  int Value = 0;
-  unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-
-  for (int x = NewStartX; x < NewStartX + IterX; x++)
-    for (int y = NewStartY; y < NewStartY + IterY; y++)
-    {
-      Value = ((int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels] +
-        (int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + 1] +
-        (int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + 2]) / 3;
-
-      if (Value == 255)
-      {
-        Counter++;
-      }
-    }
-  return Counter;
-}
-
-
-void MEImage::GradientVector(bool smooth, int x, int y, int mask_size, int& result_x, int& result_y)
-{
-  int Results[8];
-  int DiagonalMaskSize = (int)((float)mask_size / sqrtf(2));
-
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-  if (smooth)
-  {
-    SmoothAdvanced(s_Gaussian, mask_size * 3 - (mask_size * 3 - 1) % 2);
-  }
-
-  Results[0] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x, y - mask_size);
-  Results[1] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y - DiagonalMaskSize);
-  Results[2] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + mask_size, y);
-  Results[3] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y + DiagonalMaskSize);
-  Results[4] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x, y + mask_size);
-  Results[5] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x - DiagonalMaskSize, y + DiagonalMaskSize);
-  Results[6] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x - mask_size, y);
-  Results[7] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y - DiagonalMaskSize);
-
-  result_x = (DiagonalMaskSize*Results[1] + mask_size*Results[2] +
-    DiagonalMaskSize*Results[3] - DiagonalMaskSize*Results[5] -
-    mask_size*Results[6] + DiagonalMaskSize*Results[7]) / 256;
-  result_y = (-mask_size*Results[0] - DiagonalMaskSize*Results[1] +
-    DiagonalMaskSize*Results[3] + mask_size*Results[4] +
-    DiagonalMaskSize*Results[5] - DiagonalMaskSize*Results[7]) / 256;
-}
-
-
-void MEImage::GradientVisualize(int vector_x, int vector_y)
-{
-  if (vector_x <= 0)
-  {
-    printf("vectorx: wrong parameter (%d <= 0)\n", vector_x);
-    return;
-  }
-  if (vector_y <= 0)
-  {
-    printf("vectory: wrong parameter (%d <= 0)\n", vector_y);
-    return;
-  }
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
-  {
-    ConvertToGrayscale(g_OpenCV);
-  }
-
-  int masksize = (ME_CAST_TO_IPLIMAGE(cvImg)->width < ME_CAST_TO_IPLIMAGE(cvImg)->height) ?
-    ME_CAST_TO_IPLIMAGE(cvImg)->width / (vector_x + 1) :
-    ME_CAST_TO_IPLIMAGE(cvImg)->height / (vector_y + 1);
-
-  SmoothAdvanced(s_Gaussian, masksize * 2 - 1);
-  for (int i = 1; i < vector_x; i++)
-    for (int i1 = 1; i1 < vector_y; i1++)
-    {
-      int Resultx = 0, Resulty = 0;
-      int x = (int)(((float)ME_CAST_TO_IPLIMAGE(cvImg)->width*i / (vector_x)));
-      int y = (int)(((float)ME_CAST_TO_IPLIMAGE(cvImg)->height*i1 / (vector_y)));
-
-      GradientVector(false, x, y, (int)(0.707*masksize), Resultx, Resulty);
-
-      CvPoint Point1;
-      CvPoint Point2;
-
-      Point1.x = x - Resultx / 2;
-      Point1.y = y - Resulty / 2;
-      Point2.x = x + Resultx / 2;
-      Point2.y = y + Resulty / 2;
-      cvLine(ME_CAST_TO_IPLIMAGE(cvImg), Point1, Point2, CV_RGB(255, 255, 255), 1, 8);
-    }
-}
-
-
-bool MEImage::_Copy(const MEImage& other_image)
-{
-  if (&other_image == this)
-    return true;
-
-  if (ME_CAST_TO_IPLIMAGE(cvImg))
-  {
-    ME_RELEASE_IPLIMAGE(cvImg);
-  }
-  cvImg = cvCloneImage((IplImage*)other_image.GetIplImage());
-  return true;
-}
-
-
-void MEImage::_Init(int width, int height, int layers)
-{
-  if (width < 1)
-  {
-    printf("Given width for the new image is too small (%d <= 0)\n", width);
-    return;
-  }
-  if (height < 1)
-  {
-    printf("Given height for the new image is (%d <= 0)\n", height);
-    return;
-  }
-  if ((layers != 1) && (layers != 3))
-  {
-    printf("Only one or three (%d != 1 or 3) layer allowed\n", layers);
-    return;
-  }
-
-  if (ME_CAST_TO_IPLIMAGE(cvImg))
-  {
-    ME_RELEASE_IPLIMAGE(cvImg);
-  }
-  cvImg = cvCreateImage(cvSize(width, height), 8, layers);
-}
-
-
-void MEImage::ComputeColorSpace(ColorSpaceConvertType mode)
-{
-  if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 3)
-  {
-    printf("Image has to have three color channels (%d != 3)\n", ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-    return;
-  }
-  IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
-    ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
-
-  for (int i = 0; i < 3; i++)
-    for (int i1 = 0; i1 < 3; i1++)
-    {
-      if (mode == csc_RGBtoYUV)
-        TransformMatrix[i][i1] = RGBtoYUVMatrix[i][i1];
-      if (mode == csc_RGBtoYIQ)
-        TransformMatrix[i][i1] = RGBtoYIQMatrix[i][i1];
-    }
-  float x = 0.0;
-  float y = 0.0;
-  float z = 0.0;
-  float xmin = 0.0;
-  float xmax = 0.0;
-  float ymin = 0.0;
-  float ymax = 0.0;
-  float zmin = 0.0;
-  float zmax = 0.0;
-
-  if (mode == csc_RGBtoYUV)
-  {
-    xmin = 0.0;
-    xmax = 255.0;
-    ymin = -111.18;
-    ymax = 111.18;
-    zmin = -156.825;
-    zmax = 156.825;
-  }
-  if (mode == csc_RGBtoYIQ)
-  {
-    xmin = 0.0;
-    xmax = 255.0;
-    ymin = -151.98;
-    ymax = 151.98;
-    zmin = -133.365;
-    zmax = 133.365;
-  }
-  unsigned char* SrcData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
-  unsigned char* DstData = (unsigned char*)TempImg->imageData;
-
-  for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; i -= 3)
-  {
-    x = (float)SrcData[i] * TransformMatrix[0][0] +
-      (float)SrcData[i + 1] * TransformMatrix[0][1] +
-      (float)SrcData[i + 2] * TransformMatrix[0][2];
-    y = (float)SrcData[i] * TransformMatrix[1][0] +
-      (float)SrcData[i + 1] * TransformMatrix[1][1] +
-      (float)SrcData[i + 2] * TransformMatrix[1][2];
-    z = (float)SrcData[i] * TransformMatrix[2][0] +
-      (float)SrcData[i + 1] * TransformMatrix[2][1] +
-      (float)SrcData[i + 2] * TransformMatrix[2][2];
-
-    x = xmax - xmin != 0.0 ? 255.0 : (x - xmin) / (xmax - xmin)*255.0;
-    y = ymax - ymin != 0.0 ? 255.0 : (y - xmin) / (ymax - ymin)*255.0;
-    z = zmax - zmin != 0.0 ? 255.0 : (z - xmin) / (zmax - zmin)*255.0;
-
-    DstData[i] = (unsigned char)MEBound(0, (int)x, 255);
-    DstData[i + 1] = (unsigned char)MEBound(0, (int)y, 255);
-    DstData[i + 2] = (unsigned char)MEBound(0, (int)z, 255);
-  }
-  ME_RELEASE_IPLIMAGE(cvImg);
-  cvImg = TempImg;
-}
diff --git a/package_bgs/LBP_MRF/MEImage.hpp b/package_bgs/LBP_MRF/MEImage.hpp
deleted file mode 100644
index 3a52a779a282ad02332df009a4021091645d22d7..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MEImage.hpp
+++ /dev/null
@@ -1,1011 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-#pragma once
-
- /**
-  *  @addtogroup mindeye
-  *  @{
-  */
-
-  /**
-   * MEImage
-   * @brief Basic image functions
-   */
-class MEImage
-{
-public:
-  /// Types of LBP operator
-  typedef enum {
-    lbp_Min = 0,          /*!< Minimum value */
-    lbp_Normal = lbp_Min, /*!< Normal LBP pattern */
-    lbp_Special,          /*!< Special LBP pattern */
-    lbp_Max = lbp_Special /*!< Maximum value */
-  } LBPType;
-
-  /// Types of image subtraction
-  typedef enum {
-    sub_Min = 0,          /*!< Minimum value */
-    sub_Normal = sub_Min, /*!< Normal */
-    sub_Absolut,          /*!< Absolut */
-    sub_Max = sub_Absolut /*!< Maximum value */
-  } SubtractModeType;
-
-  /// Types of image addition
-  typedef enum {
-    a_Min = 0,         /*!< Minimum value */
-    a_Average = a_Min, /*!< Average */
-    a_Union,           /*!< Union */
-    a_Max = a_Union    /*!< Maximum value */
-  } AdditionType;
-
-  /// Types of image multiplication
-  typedef enum {
-    m_Min = 0,              /*!< Minimum value */
-    m_Normal = m_Min,       /*!< Normal */
-    m_Neighbourhood,        /*!< Neighbourhood */
-    m_Max = m_Neighbourhood /*!< Maximum value */
-  } MultiplicationType;
-
-  /// Types of grayscale conversation
-  typedef enum {
-    g_Min = 0,         /*!< Minimum value */
-    g_Average = g_Min, /*!< Average */
-    g_OpenCV,          /*!< OpenCV */
-    g_Max = g_OpenCV   /*!< Maximum value */
-  } GrayscaleType;
-
-  /// Types of pixel neighbourhoods
-  typedef enum {
-    n_Min = 0,     /*!< Minimum value */
-    n_2x2 = n_Min, /*!< 2x2 */
-    n_3x2,         /*!< 3x2 */
-    n_3x3,         /*!< 3x3 */
-    n_5x5,         /*!< 5x5 */
-    n_7x7,         /*!< 7x7 */
-    n_Max = n_7x7  /*!< Maximum value */
-  } NeighbourhoodType;
-
-  /// Types of special pixels
-  typedef enum {
-    p_Min = 0,         /*!< Minimum value */
-    p_Minimum = p_Min, /*!< Minimum */
-    p_Maximum,         /*!< Maximum */
-    p_Counter,         /*!< Counter */
-    p_Max = p_Counter  /*!< Maximum value */
-  } PixelType;
-
-  /// Types of smooth operation
-  typedef enum {
-    s_Min = 0,       /*!< Minimum value */
-    s_Blur = s_Min,  /*!< Blur */
-    s_Gaussian,      /*!< Gaussian */
-    s_Median,        /*!< Medium */
-    s_Max = s_Median /*!< Maximum value */
-  } SmoothType;
-
-  /// Types of color space conversions
-  typedef enum {
-    csc_Min = 0,                  /*!< Minimum value */
-    csc_RGBtoXYZCIED65 = csc_Min, /*!< RGB to XYZCIED65 */
-    csc_XYZCIED65toRGB,           /*!< XYZCIED65 to RGB */
-    csc_RGBtoHSV,                 /*!< RGB to HSV */
-    csc_HSVtoRGB,                 /*!< HSV to RGB */
-    csc_RGBtoHLS,                 /*!< RGB to HLS */
-    csc_HLStoRGB,                 /*!< HLS to RGB */
-    csc_RGBtoCIELab,              /*!< RGB to CIELab */
-    csc_CIELabtoRGB,              /*!< CIELab to RGB */
-    csc_RGBtoCIELuv,              /*!< RGB to CIELuv */
-    csc_CIELuvtoRGB,              /*!< CIELuv to RGB */
-    csc_RGBtoYUV,                 /*!< RGB to YUV */
-    csc_RGBtoYIQ,                 /*!< RGB to YIQ */
-    csc_RGBtorgI,                 /*!< RGB to rgI */
-    csc_Max = csc_RGBtorgI        /*!< Maximum value */
-  } ColorSpaceConvertType;
-
-  /*!
-   * @brief Class constructor
-   *
-   * @param width Image width
-   * @param height Image height
-   * @param layers Layers
-   *
-   * Class constructor with the possibility to specify the image width,
-   * height and the layers. The default options are 16x16x1.
-   *
-   */
-
-  MEImage(int width = 16, int height = 16, int layers = 1);
-
-  /*!
-   * @brief Class constructor
-   *
-   * @param other Other image
-   *
-   * Class constructor with the possibility to specify the image width,
-   * height and the layers. The default options are 16x16x1.
-   *
-   */
-
-  MEImage(const MEImage& other);
-  /// Destructor of class
-  ~MEImage();
-
-  /*
-  -------------------------------------------------------------------
-                          Basic functions
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Clear image
-   *
-   * This function clears image by filling all image data with zero
-   * value.
-   *
-   */
-
-  void Clear();
-
-  /*!
-   * @brief Get an color layer of image
-   *
-   * @param new_layer new image of layer
-   * @param layernumber number of layer which will be copied
-   *
-   * Copy an image layer (R, G or B) to @a new_layer image. @a new_layer has to
-   * have only one color layer (greyscale). If @a new_layer is not
-   * greyscale or it has got different width or height like source image
-   * than function reallocates it with appropriate features before
-   * copying image data.
-   *
-   */
-
-  void GetLayer(MEImage& new_layer, int layernumber) const;
-
-  /*!
-   * @brief Copy a new color layer to image
-   *
-   * @param new_layer image data of new color layer
-   * @param layernumber number of layer where image data will copy
-   *
-   * Copy a new image layer from @a new_layer image. @a new_layer has to
-   * have only one color layer (greyscale). If @a new_layer is not
-   * greyscale or it has got different width or height like source image
-   * than function halts with an error message.
-   *
-   */
-
-  void SetLayer(MEImage& new_layer, int layernumber);
-
-  /*!
-   * @brief Copy image data to a pointer
-   *
-   * @param data pointer where image data will be copied
-   *
-   * Function in order to acquire image data to an external
-   * (unsigned char*) pointer.
-   *
-   */
-
-  void CopyImageData(unsigned char* data);
-
-  /*!
-   * @brief Get a pointer to the internal IplImage
-   *
-   * @return Pointer to the IplImage
-   *
-   * This function returns the internal IplImage of the class. The
-   * image data can not be modified.
-   *
-   */
-
-  void* GetIplImage() const;
-
-  /*!
-   * @brief Set the internal IplImage
-   *
-   * @param image Pointer to the IplImage
-   *
-   * This function sets the internal IplImage of the class.
-   *
-   */
-
-  void SetIplImage(void* image);
-
-  /*!
-   * @brief Handle operator == for MEImage
-   *
-   * @param image image to check
-   *
-   * @return true if the images are equal otherwise false.
-   *
-   * The operator checks the equality of two images.
-   *
-   */
-
-  bool operator==(const MEImage& image);
-
-  /*!
-   * @brief Handle operator != for MEImage
-   *
-   * @param image image to check
-   *
-   * @return true if the images are not equal otherwise false.
-   *
-   * The operator checks the non-equality of two images.
-   *
-   */
-
-  bool operator!=(const MEImage& image);
-
-  /*!
-   * @brief Handle operator = for MEImage
-   *
-   * @param other_image image to copy operation
-   *
-   * @return Reference to the actual instance.
-   *
-   * Copy image data to @a other_image image. Function calls only
-   * _Copy() directly.
-   *
-   */
-
-  MEImage& operator=(const MEImage& other_image);
-
-  /*!
-   * @brief Get the width of the image
-   *
-   * @return Width of the image
-   *
-   * Get the width of the image.
-   *
-   */
-
-  int GetWidth() const;
-
-  /*!
-   * @brief Get the height of the image
-   *
-   * @return Height of the image
-   *
-   * Get the height of the image.
-   */
-
-  int GetHeight() const;
-
-  /*!
-   * @brief Get the length of a pixel row of the image
-   *
-   * @return Length of a pixel row
-   *
-   * Get the row width of the image.
-   *
-   */
-
-  int GetRowWidth() const;
-
-  /*!
-   * @brief Get the number of color layers of the image
-   *
-   * @return Number of color layer of the image
-   *
-   * Get the number of color layer of the image.
-   *
-   */
-
-  int GetLayers() const;
-
-  /*!
-   * @brief Get the number of the image pixel data
-   *
-   * @return Number of the image pixel data
-   *
-   * Get the number of the image pixel data.
-   *
-   */
-
-  int GetPixelDataNumber() const;
-
-  /*!
-   * @brief Get the image data
-   *
-   * @return Pointer to the image data
-   *
-   * Get a pointer to the image.
-   *
-   */
-
-  unsigned char* GetImageData() const;
-
-  /*!
-   * @brief Set the image data
-   *
-   * @param image_data New image data
-   * @param width New image width
-   * @param height New image height
-   * @param channels New image color channels
-   *
-   * Get a pointer to the image.
-   *
-   */
-
-  void SetData(unsigned char* image_data, int width, int height, int channels);
-
-  /*!
-   * @brief Get ratio of image width and height
-   *
-   * @return float ratio of image dimensions
-   *
-   * Function calculates ratio of image width and height with
-   * following equation: ratio = height / width.
-   */
-
-  float GetRatio() const;
-
-  /*
-  -------------------------------------------------------------------
-                       Basic image manipulation
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Reallocate image data
-   *
-   * @param width New width of the image
-   * @param height New height of the image
-   *
-   * Image data will be reallocated with new dimensions @a width
-   * and @a height. Number of color channels is not changed.
-   *
-   */
-
-  void Realloc(int width, int height);
-
-  /*!
-   * @brief Reallocate image data
-   *
-   * @param width New width of the image
-   * @param height New height of the image
-   * @param layers Number of color channels of the image
-   *
-   * Image data will be reallocated with new dimensions @a width,
-   * @a height and new number of color channels @a layers.
-   *
-   */
-
-  void Realloc(int width, int height, int layers);
-
-  /*!
-   * @brief Resize image
-   *
-   * @param newwidth new width of image
-   * @param newheight new height of image
-   *
-   * Resize image to @a newwidth width and @a newheight
-   * height dimensions.
-   *
-   */
-
-  void Resize(int newwidth, int newheight);
-
-  /*!
-   * @brief Resize image with new width
-   *
-   * @param newwidth new width of image
-   *
-   * Image is resized with only new width information therefore
-   * fit to original ratio.
-   *
-   */
-
-  void ResizeScaleX(int newwidth);
-
-  /*!
-   * @brief Resize image with new height
-   *
-   * @param newheight new height of image
-   *
-   * Image is resized with only new height information therefore
-   * fit to original ratio.
-   *
-   */
-
-  void ResizeScaleY(int newheight);
-
-  /*!
-   * @brief Reverse image in horizontal direction
-   *
-   * Function makes a mirror transformation on image in horizontal
-   * direction.
-   *
-   */
-
-  void MirrorHorizontal();
-
-  /*!
-   * @brief Reverse image in vertical direction
-   *
-   * Function makes a mirror transformation on image in vertical
-   * direction.
-   *
-   */
-
-  void MirrorVertical();
-
-  /*!
-   * @brief Crop image
-   *
-   * @param x1, y1 coordinates of top-left point of rectangle
-   * @param x2, y2 coordinates of bottom-right point of rectangle
-   *
-   * Crop the image in a smaller piece whose dimensions are
-   * specified as a rectangle. Top-left and bottom-right
-   * coordinates of rectangle are (x1, y1) and (x2, y2) wherefrom
-   * comes that the width of the new image is x2-x1 and height is
-   * y2-y1.
-   *
-   */
-
-  void Crop(int x1, int y1, int x2, int y2);
-
-  /*!
-   * @brief Copy all image data from an other picture
-   *
-   * @param x0 x coordinate to paste the new image data
-   * @param y0 y coordinate to paste the new image data
-   * @param source_image source image
-   *
-   * Function copies all image data from @a source_image
-   * to the given coordinate (x0,y0).
-   *
-   */
-
-  void CopyImageInside(int x0, int y0, MEImage& source_image);
-
-  /*
-  -------------------------------------------------------------------
-                     Image processing functions
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Erode function
-   *
-   * @param iterations iterations of erode method
-   *
-   * Method makes an erode filter on an image @a iterations
-   * times with standard 3x3 matrix size.
-   *
-   */
-
-  void Erode(int iterations);
-
-  /*!
-   * @brief Dilate function
-   *
-   * @param iterations iterations of dilate method
-   *
-   * Method makes an dilate filter on an image
-   * @a iterations times with standard 3x3 matrix size.
-   *
-   */
-
-  void Dilate(int iterations);
-
-  /*!
-   * @brief Smooth function
-   *
-   * Method smooths with median filter and standard 3x3 matrix size.
-   * (Median filter works fine and fast.)
-   *
-   */
-
-  void Smooth();
-
-  /*!
-   * @brief Smooth function with defined parameters
-   *
-   * @param filtermode type of smooth method
-   * @param filtersize the size of the convolution matrix
-   *
-   * Method smooths with median filter and the given matrix
-   * size (@a filtersize x @a filtersize). There are more
-   * types of smooth function (@a filtermode):
-   *
-   * - s_Blur: Blur filter.
-   * - s_Gaussian: Gaussian filter.
-   * - s_Median: Median filter.
-   *
-   */
-
-  void SmoothAdvanced(SmoothType filtermode, int filtersize);
-
-  /*!
-   * @brief Canny function
-   *
-   * Canny operator is usable for edge detection. Function makes
-   * this operation with standard 3x3 matrix
-   * size. Canny has two threshold value which are set to zero
-   * in this function by default.
-   *
-   */
-
-  void Canny();
-
-  /*!
-   * @brief Laplace function
-   *
-   * Laplace operator is usable for edge detection like Canny.
-   * This function makes a laplace filter with
-   * standard 3x3 matrix size. After calculating destination image will
-   * be converted from 16 bit back to 8 bit.
-   *
-   */
-
-  void Laplace();
-
-  /*!
-   * @brief Image quantisation
-   *
-   * @param levels level of quantisation
-   *
-   * Quantize an image with @a levels level. It means by 16
-   * level color range 0-255 quantizes to 0-15, by 4 level to 0-63 etc.
-   *
-   */
-
-  void Quantize(int levels);
-
-  /*!
-   * @brief Threshold a picture
-   *
-   * @param threshold_limit limit for threshold
-   *
-   * Threshold an image with @a threshold_limit limit. Value range
-   * of @a threshold_limit is between 0-255. E.g. by value 160 functions
-   * will eliminate all color values under 160 with black color
-   * (color value zero).
-   *
-   */
-
-  void Threshold(int threshold_limit);
-
-  /*!
-   * @brief Adaptive threshold function
-   *
-   * This function does adaptive threshold function.
-   *
-   */
-
-  void AdaptiveThreshold();
-
-  /*!
-   * @brief Threshold a picture by a mask image
-   *
-   * @param mask_image mask image for thresholding
-   *
-   * Threshold an image with a mask image @a mask_image.
-   *
-   */
-
-  void ThresholdByMask(MEImage& mask_image);
-
-  /*!
-   * @brief Convert an image into a new color space
-   *
-   * @param transformation Definition of color transformation
-   *
-   * This function converts an image from a specified color space
-   * to an other.
-   * Current supported conversions (@a transformation):
-   * - csc_RGBtoXYZCIED65: RGB to XYZ (D65 reference light),
-   * - csc_XYZCIED65toRGB: XYZ to RGB (D65 reference light),
-   * - csc_RGBtoHSV: RGB to HSV,
-   * - csc_HSVtoRGB: HSV to RGB,
-   * - csc_RGBtoHLS: RGB to HSV,
-   * - csc_HLStoRGB: HSV to RGB,
-   * - csc_RGBtoCIELab: RGB to CIELab,
-   * - csc_CIELabtoRGB: CIELuv to RGB,
-   * - csc_RGBtoCIELuv: RGB to CIELuv,
-   * - csc_CIELuvtoRGB: CIELuv to RGB,
-   * - csc_RGBtoYUV: RGB to YUV color space,
-   * - csc_RGBtoYIQ: RGB to YIQ color space.
-   *
-   */
-
-  void ColorSpace(ColorSpaceConvertType transformation);
-
-  /*!
-   * @brief Convert an image to grayscale
-   *
-   * @param grayscale_mode mode of grayscale conversation
-   *
-   * The function converts the image to grayscale version
-   * (one color channel after the conversion). There is four
-   * different ways to convert the image to grayscale what we
-   * can define with @a grayscale_mode:
-   *
-   *  - g_Average: It computes the average grayscale
-   * values of the pixels with arithmetical average.
-   *  - g_OpenCV: It computes the average grayscale
-   * values by help of the values of the Y channel.
-   *
-   */
-
-  void ConvertToGrayscale(GrayscaleType grayscale_mode = g_OpenCV);
-
-  /*!
-   * @brief Convert a grayscale image to RGB
-   *
-   * The function converts the grayscale image to RGB version.
-   * (It copies the info from a single color channel to
-   * three color channel.)
-   *
-   */
-
-  void ConvertGrayscaleToRGB();
-
-  /*!
-   * @brief Change the red and blue components of every pixels
-   *
-   * Function changes the red component with the blue of
-   * every pixels. (Simple conversion from RGB->BGR.)
-   *
-   */
-
-  void ConvertBGRToRGB();
-
-  /*!
-   * @brief Compute an LBP filter on the image
-   *
-   * @param mode The LBP operator type
-   *
-   * The function converts the image to binary version over the
-   * threshold value.
-   *
-   */
-
-  void LBP(LBPType mode = lbp_Special);
-
-  /*!
-   * @brief Binarize an image
-   *
-   * @param threshold Threshold value
-   *
-   * The function converts the image to binary version over the
-   * threshold value.
-   *
-   */
-
-  void Binarize(int threshold);
-
-  /*!
-   * @brief Subtract an image from the internal picture
-   *
-   * @param source Source image for subtraction
-   * @param mode Calculation mode of difference feature
-   *
-   * Function generates a difference image between two image:
-   * the internal picture of this class and @a source_image.
-   * The calculation mode is determined by @a mode parameter.
-   * Function supports the following modes:
-   *
-   *  - sub_Normal: Simple subtraction between each
-   * correspondent pixel (per color channels). The result values
-   * are converted to absolute value and normalized to
-   * range 0-255.
-   *
-   */
-
-  void Subtract(MEImage& source, SubtractModeType mode);
-
-  /*!
-   * @brief Multiple an image with the internal picture
-   *
-   * @param source Second source image for multiplication
-   * @param mode Multiplication mode
-   *
-   * Function multiples an image with the internal image of this class and
-   * the result is stored in the internal image. The implemented calculation
-   * modes:
-   *
-   *  - m_Normal: It multiples the corresponding pixel values
-   * of the two images. The original pixel values are divided by 128 and
-   * multiplied together. If the result is at least 1 then the new pixel value
-   * is 255 otherwise 0.
-   *  - m_Neighbourhood: It multiples all pixel values of its
-   * 3x3 neighbourhood separately (see the method at MULTIPLICATION_NORMAL)
-   * and the new pixel value is 255 if at least two pixel is active in the
-   * 3x3 neighbourhood otherwise 0.
-   *
-   */
-
-  void Multiple(MEImage& source, MultiplicationType mode);
-
-  /*!
-   * @brief Addition of an image and the internal picture
-   *
-   * @param source second source image for addition method
-   * @param mode the declaration of the used addition mode
-   *
-   * Function makes an addition operation between an image and the internal
-   * image of this class and the result is stored in the internal image.
-   * Supported modes:
-   *
-   *  - a_Average: It sums the average of the corresponding pixels
-   * of each pictures.
-   *  - a_Union: It sums the union of the corresponding pixels
-   * of each pictures.
-   *
-   */
-
-  void Addition(MEImage& source, AdditionType mode);
-
-  /*!
-   * @brief Eliminate the single pixels from a binary image
-   *
-   * Function eliminates such a pixels which do not have neighbour pixels with
-   * 255 value in a 3x3 neighbourhood. The image should be converted to binary
-   * version.
-   *
-   */
-
-  void EliminateSinglePixels();
-
-  /*!
-   * @brief Calculate an area difference feature between two images
-   *
-   * @param reference Reference image
-   * @param difference Difference
-   *
-   * @return The percentage of image areas representing the conditions
-   *
-   * Function calculates a similarity feature between two pictures.
-   * Counts the number of the pixels whose intensity difference is
-   * higher than @a difference. (Range: 0..100)
-   *
-   */
-
-  float DifferenceAreas(MEImage& reference, int difference) const;
-
-  /*!
-   * @brief Calculate an average difference between two images
-   *
-   * @param reference Reference image
-   *
-   * @return Average difference of the pixels
-   *
-   * Function calculates a similarity feature between
-   * two images. It returns a simple sum of the absolute difference
-   * of each pixel in the two images and averaged by the pixel number.
-   * (Range: 0..255)
-   *
-   */
-
-  int AverageDifference(MEImage& reference) const;
-
-  /*!
-   * @brief Calculate minimum of image data
-   *
-   * @param image Second image
-   *
-   * Function calculates the minimum of current and given image.
-   *
-   */
-
-  void Minimum(MEImage& image);
-
-  /*!
-   * @brief Calculate average brightness level
-   *
-   * @return Brightness level in range 0-255.
-   *
-   * Function calculates the average brightness level of the image.
-   *
-   */
-
-  float AverageBrightnessLevel() const;
-
-  /*!
-   * @brief Check the equalization with a reference image
-   *
-   * @param reference Reference image
-   *
-   * @return true in case of binary equalization, otherwise false.
-   *
-   * Function calculates the binary difference between
-   * the image and the reference image.
-   *
-   */
-
-  bool Equal(const MEImage& reference) const;
-
-  /*!
-   * @brief Check the equalization with a reference image
-   *
-   * @param reference Reference image
-   * @param maxabsdiff Maximal absolute difference
-   *
-   * @return true in case of equalization, otherwise false.
-   *
-   * Function checks the difference between the image and
-   * the reference image. Two pixels are equal in a range of
-   * a maximal absolute difference.
-   *
-   */
-
-  bool Equal(const MEImage& reference, int maxabsdiff) const;
-
-  /*!
-   * @brief Get the grayscale value of a pixel
-   *
-   * @param x X coordinate of the pixel
-   * @param y Y coordinate of the pixel
-   *
-   * @return grayscale value of the pixel
-   *
-   * The method gives the grayscale value of a pixel back. If
-   * the image has 3 color channels (e.g. RGB) then Y value of
-   * YIQ/YUV color space will be calculated otherwise normal
-   * averaged grayscale value.
-   *
-   */
-
-  unsigned char GrayscalePixel(int x, int y) const;
-
-  /*!
-   * @brief Count the number of neighbourhood pixels with maximum intensity
-   *
-   * @param startx X coordinate of the top-left pixel
-   * @param starty Y coordinate of the top-left pixel
-   * @param neighbourhood Specific subset of pixels
-   *
-   * @return number of the pixels with maximum intensity.
-   *
-   * The method counts the number of the pixels with maximum
-   * intensity (255) in a specified subset of pixels.
-   * The grayscale values of the pixels are used in the counter
-   * process. The following neighbourhood forms are allowed with
-   * the @a neighbourhood parameter:
-   *
-   *  - n_2X2: Simple 2x2 matrix.
-   *  - n_3X3: Simple 3x3 matrix.
-   *  - n_3x2: Simple 3x2 matrix.
-   *
-   */
-
-  int NeighbourhoodCounter(int startx, int starty, NeighbourhoodType neighbourhood) const;
-
-  /*!
-   * @brief Calculate the gradient vector in a point
-   *
-   * @param smooth compute smooth filter
-   * @param x X coordinate of the point
-   * @param y Y coordinate of the point
-   * @param mask_size The mask size to calculate the gradient
-   *
-   * @param result_x X component of the calculated vector
-   * @param result_y Y component of the calculated vector
-   *
-   * The method calculates the gradient vector in a given point.
-   * The image is preprocessed with a Gauss filter to smooth the
-   * image content. The filter size of the Gauss filter depends on
-   * mask size of the gradient vector: filter size = mask size*3.
-   * Eight points are assigned to the initial point to compute
-   * a vector sum: (x, y-mask_size), (x+mask_size/√2, y-mask_size/√2),
-   * (x+mask_size, y), (x+mask_size/√2, y+mask_size/√2), (x, y+mask_size),
-   * (x-mask_size/√2, y+mask_size/√2), (x-mask_size, y), (x-mask_size/√2, y-mask_size/√2).
-   * The lengths of all vectors equalize with the mask size.
-   * After that each vector is multiplied with the gradient difference between
-   * its two end points. The results are summarized and normalized by
-   * the mask size.
-   *
-   */
-
-  void GradientVector(bool smooth, int x, int y, int mask_size, int& result_x, int& result_y);
-
-  /*!
-   * @brief Visualize gradient vectors
-   *
-   * @param vector_x Number of points horizontally
-   * @param vector_y Number of points vertically
-   *
-   * This function draws a wire (@a vector_x * @a vector_y) with
-   * gradient vectors.
-   *
-   */
-
-  void GradientVisualize(int vector_x, int vector_y);
-
-private:
-
-  /*
-  -------------------------------------------------------------------
-                          Internal methods
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Copy image data
-   *
-   * @param other_image Input image with new image data
-   *
-   * @return true if it is successful, otherwise false.
-   *
-   * Copy image data from @a other_image to MEImage image data.
-   *
-   */
-
-  bool _Copy(const MEImage& other_image);
-
-  /*!
-   * @brief Inherent initialization function
-   *
-   * @param width Width of the image
-   * @param height Height of the image
-   * @param layer Number of color channels of the image
-   *
-   * Initialization function of MEImage class which allocates
-   * memory to internal MEImage image and sets its properties.
-   *
-   */
-
-  void _Init(int width, int height, int layer);
-
-  /*!
-   * @brief Compute an image to a different color space
-   *
-   * @param mode Mode of the conversion
-   *
-   * Currently, the internal function allows to use a few
-   * mode to convert an image between color spaces.
-   * Current supported conversions (@a mode):
-   * - RGBtoYUV: RGB to YUV color space,
-   * - RGBtoYIQ: RGB to YIQ color space.
-   *
-   */
-
-  void ComputeColorSpace(ColorSpaceConvertType mode);
-
-private:
-  /// This matrix stores the matrix of the actual color space transform
-  float TransformMatrix[3][3];
-  /// The OpenCV image which contains the image data
-  void* cvImg;
-};
-
-/** @} */
diff --git a/package_bgs/LBP_MRF/MotionDetection.cpp b/package_bgs/LBP_MRF/MotionDetection.cpp
deleted file mode 100644
index e591faa92cacdf776db0198f309f76a89f955aa9..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MotionDetection.cpp
+++ /dev/null
@@ -1,1519 +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/>.
-*/
-/*
-*  This file is part of the AiBO+ project
-*
-*  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
-*
-*  AiBO+ 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 2 of the License, or
-*  (at your option) any later version.
-*
-*  AiBO+ 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 this program; if not, write to the Free Software
-*  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
-*
-*  Paper: Csaba, Kertész: Texture-Based Foreground Detection, International Journal of Signal Processing,
-*  Image Processing and Pattern Recognition (IJSIP), Vol. 4, No. 4, 2011.
-*/
-
-#include "MotionDetection.hpp"
-
-#include "graph.h"
-using namespace ck;
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#include <cvaux.h>
-#else
-#include <opencv/cvaux.h>
-#endif
-
-#include "MEHistogram.hpp"
-#include "MEImage.hpp"
-
-// Pyramid picture for the tracking
-IplImage *HUOFPyramid;
-// Pyramid picture for the tracking
-IplImage *HUOFPrevPyramid;
-
-// Struct for histogram update data of a pixel
-struct MEPixelDataType
-{
-  float BackgroundRate;
-  int LifeCycle;
-  float *Weights;
-  bool *BackgroundHistogram;
-  float **Histograms;
-  float *PreviousHistogram;
-};
-
-MotionDetection::MotionDetection(DetectorType mode) :
-  MDMode(md_NotDefined), MDDataState(ps_Uninitialized), Frames(0), ReadyMask(false),
-  HUColorSpace(MEImage::csc_RGBtoCIELuv), HULBPMode(MEImage::lbp_Special),
-  HUHistogramsPerPixel(3), HUHistogramArea(5), HUHistogramBins(8),
-  HUImageWidth(-1), HUImageHeight(-1), HULBPPixelData(NULL),
-  HUPrThres(0.75), HUBackgrThres(0.95), HUHistLRate(0.01), HUWeightsLRate(0.01),
-  HUSamplePixels(-1), HUDesiredSamplePixels(-1), HUMinCutWeight(8.0),
-  HUOFDataState(ps_Uninitialized), HUOFPointsNumber(-1),
-  HUOFCamMovementX(0), MaxTrackedPoints(0), HUOFFrames(-1),
-  HUOFCamMovement(false)
-{
-  HUOFPyramid = NULL;
-  HUOFPrevPyramid = NULL;
-  HUOFPoints[0] = NULL;
-  HUOFPoints[1] = NULL;
-  SetMode(mode);
-}
-
-
-MotionDetection::~MotionDetection()
-{
-  if (MDMode != md_NotDefined)
-  {
-    ReleaseData();
-  }
-}
-
-
-void MotionDetection::SetMode(DetectorType newmode)
-{
-  if (MDMode != md_NotDefined && MDMode != newmode)
-  {
-    ReleaseData();
-    Frames = 0;
-    HUOFFrames = -1;
-    HUOFCamMovement = false;
-    HUOFCamMovementX = 0;
-    ReadyMask = false;
-  }
-
-  switch (newmode)
-  {
-  case md_LBPHistograms:
-    MDMode = md_LBPHistograms;
-    break;
-
-  case md_DLBPHistograms:
-    MDMode = md_DLBPHistograms;
-    break;
-
-  default:
-    MDMode = md_LBPHistograms;
-    break;
-  }
-}
-
-
-float MotionDetection::GetParameter(ParametersType param) const
-{
-  float ret = 0.0;
-
-  switch (param)
-  {
-  case mdp_HUProximityThreshold:
-    ret = (float)HUPrThres;
-    break;
-
-  case mdp_HUBackgroundThreshold:
-    ret = (float)HUBackgrThres;
-    break;
-
-  case mdp_HUHistogramLearningRate:
-    ret = (float)HUHistLRate;
-    break;
-
-  case mdp_HUWeightsLearningRate:
-    ret = (float)HUWeightsLRate;
-    break;
-
-  case mdp_HUMinCutWeight:
-    ret = (float)HUMinCutWeight;
-    break;
-
-  case mdp_HUDesiredSamplePixels:
-    ret = (float)HUDesiredSamplePixels;
-    break;
-
-  case mdp_HUHistogramsPerPixel:
-    ret = (float)HUHistogramsPerPixel;
-    break;
-
-  case mdp_HUHistogramArea:
-    ret = (float)HUHistogramArea;
-    break;
-
-  case mdp_HUHistogramBins:
-    ret = (float)HUHistogramBins;
-    break;
-
-  case mdp_HUColorSpace:
-    ret = (float)HUColorSpace;
-    break;
-
-  case mdp_HULBPMode:
-    ret = (float)HULBPMode;
-    break;
-
-  default:
-    break;
-  }
-  return ret;
-}
-
-
-void MotionDetection::SetParameter(ParametersType param, float value)
-{
-  switch (param)
-  {
-  case mdp_HUProximityThreshold:
-    HUPrThres = (float)value;
-    break;
-
-  case mdp_HUBackgroundThreshold:
-    HUBackgrThres = (float)value;
-    break;
-
-  case mdp_HUHistogramLearningRate:
-    HUHistLRate = (float)value;
-    break;
-
-  case mdp_HUWeightsLearningRate:
-    HUWeightsLRate = (float)value;
-    break;
-
-  case mdp_HUMinCutWeight:
-    HUMinCutWeight = (float)value;
-    break;
-
-  case mdp_HUDesiredSamplePixels:
-    HUDesiredSamplePixels = (int)value;
-    break;
-
-  case mdp_HUHistogramsPerPixel:
-    HUHistogramsPerPixel = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramsPerPixel;
-    break;
-
-  case mdp_HUHistogramArea:
-    HUHistogramArea = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramArea;
-    break;
-
-  case mdp_HUHistogramBins:
-    HUHistogramBins = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramBins;
-    break;
-
-  case mdp_HUColorSpace:
-    HUColorSpace = (MDDataState == ps_Uninitialized) ? (int)value : HUColorSpace;
-    break;
-
-  case mdp_HULBPMode:
-    HULBPMode = (MDDataState == ps_Uninitialized) ? (int)value : HULBPMode;
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MotionDetection::DetectMotions(MEImage& image)
-{
-  switch (MDMode)
-  {
-  case md_LBPHistograms:
-  case md_DLBPHistograms:
-    DetectMotionsHU(image);
-    break;
-
-  default:
-    break;
-  }
-}
-
-
-void MotionDetection::GetMotionsMask(MEImage& mask_image)
-{
-  if (ReadyMask)
-  {
-    mask_image = MaskImage;
-  }
-
-  switch (MDMode)
-  {
-  case md_LBPHistograms:
-  case md_DLBPHistograms:
-    GetMotionsMaskHU(MaskImage);
-    break;
-
-  default:
-    break;
-  }
-
-  ReadyMask = true;
-  mask_image = MaskImage;
-}
-
-
-void MotionDetection::CalculateResults(MEImage& referenceimage, int& tnegatives, int& tpositives,
-  int& ttnegatives, int& ttpositives)
-{
-  if (MDDataState != ps_Successful)
-  {
-    printf("No data for calculation.\n");
-    return;
-  }
-
-  if (referenceimage.GetLayers() != 1)
-    referenceimage.ConvertToGrayscale(MEImage::g_OpenCV);
-
-  referenceimage.Binarize(1);
-
-  MEImage mask_image;
-
-  GetMotionsMask(mask_image);
-
-  if ((mask_image.GetWidth() != referenceimage.GetWidth()) ||
-    (mask_image.GetHeight() != referenceimage.GetHeight()))
-  {
-    printf("Different resolutions of mask<->reference image.\n");
-    return;
-  }
-
-  unsigned char* RefMaskImgData = referenceimage.GetImageData();
-  unsigned char* MaskImgData = mask_image.GetImageData();
-  int RowStart = 0;
-  int RowWidth = referenceimage.GetRowWidth();
-
-  int TrueNegatives = 0;
-  int TruePositives = 0;
-  int TotalTrueNegatives = 0;
-  int TotalTruePositives = 0;
-
-  int ImageFrame = 0;
-
-  if (MDMode == md_LBPHistograms || md_DLBPHistograms)
-  {
-    ImageFrame = HUHistogramArea / 2;
-  }
-
-  for (int y = referenceimage.GetHeight() - ImageFrame - 1; y >= ImageFrame; --y)
-  {
-    for (int x = referenceimage.GetWidth() - ImageFrame - 1; x >= ImageFrame; --x)
-    {
-      TrueNegatives +=
-        (RefMaskImgData[RowStart + x] == 0) &&
-        (MaskImgData[RowStart + x] == 0);
-      TotalTrueNegatives += (RefMaskImgData[RowStart + x] == 0);
-      TruePositives +=
-        (RefMaskImgData[RowStart + x] == 255) &&
-        (MaskImgData[RowStart + x] == 255);
-      TotalTruePositives += (RefMaskImgData[RowStart + x] == 255);
-    }
-    RowStart += RowWidth;
-  }
-
-  tnegatives = TrueNegatives;
-  ttnegatives = TotalTrueNegatives;
-  tpositives = TruePositives;
-  ttpositives = TotalTruePositives;
-}
-
-
-void MotionDetection::ReleaseData()
-{
-  if (MDMode == md_LBPHistograms || MDMode == md_DLBPHistograms)
-  {
-    ReleaseHUData();
-  }
-}
-
-
-void MotionDetection::InitHUData(int imagewidth, int imageheight)
-{
-  if ((HUImageWidth != imagewidth - HUHistogramArea + 1) ||
-    (HUImageHeight != imageheight - HUHistogramArea + 1) ||
-    (MDDataState == ps_Uninitialized))
-  {
-    if (MDDataState != ps_Uninitialized)
-    {
-      ReleaseHUData();
-    }
-
-    MDDataState = ps_Initialized;
-
-    HUImageWidth = imagewidth - HUHistogramArea + 1;
-    HUImageHeight = imageheight - HUHistogramArea + 1;
-
-    HULBPPixelData = new MEPixelDataType**[HUImageWidth / 2];
-
-    for (int i = 0; i < HUImageWidth / 2; ++i)
-    {
-      HULBPPixelData[i] = new MEPixelDataType*[HUImageHeight];
-    }
-
-    for (int i = 0; i < HUImageWidth / 2; ++i)
-      for (int i1 = 0; i1 < HUImageHeight; ++i1)
-      {
-        HULBPPixelData[i][i1] = new MEPixelDataType;
-        HULBPPixelData[i][i1]->Weights = new float[HUHistogramsPerPixel];
-        HULBPPixelData[i][i1]->BackgroundHistogram = new bool[HUHistogramsPerPixel];
-        HULBPPixelData[i][i1]->Histograms = new float*[HUHistogramsPerPixel];
-        for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-          HULBPPixelData[i][i1]->Histograms[i2] = new float[HUHistogramBins];
-        HULBPPixelData[i][i1]->PreviousHistogram = new float[HUHistogramBins];
-      }
-
-    // Allocate auxiliary variables
-    HUMaskColumnAddDel = new int*[HUHistogramArea];
-    for (int i = 0; i < HUHistogramArea; ++i)
-      HUMaskColumnAddDel[i] = new int[2];
-
-    HUMaskRowAddDel = new int*[HUHistogramArea];
-    for (int i = 0; i < HUHistogramArea; ++i)
-      HUMaskRowAddDel[i] = new int[2];
-
-    // Generate sample mask
-    SetSampleMaskHU(sm_Circle, HUDesiredSamplePixels);
-
-    // Init HU optical flow data
-    if (MDMode == md_DLBPHistograms)
-      InitHUOFData(imagewidth, imageheight);
-
-    ClearHUData();
-  }
-}
-
-
-void MotionDetection::InitHUOFData(int imagewidth, int imageheight)
-{
-  if (HUOFDataState != ps_Uninitialized)
-  {
-    ReleaseHUOFData();
-  }
-
-  if (HUOFDataState == ps_Uninitialized)
-  {
-    HUOFPointsNumber = imagewidth*imageheight / 1000;
-    HUOFPyramid = cvCreateImage(cvSize(imagewidth, imageheight), 8, 1);
-    HUOFPrevPyramid = cvCreateImage(cvSize(imagewidth, imageheight), 8, 1);
-    HUOFPoints[0] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[0][0]));
-    HUOFPoints[1] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[1][0]));
-  }
-}
-
-
-void MotionDetection::ReleaseHUData()
-{
-  if (MDDataState != ps_Uninitialized)
-  {
-    for (int i = 0; i < HUImageWidth / 2; i++)
-      for (int i1 = 0; i1 < HUImageHeight; i1++)
-      {
-        delete[] HULBPPixelData[i][i1]->PreviousHistogram;
-        for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-          delete[] HULBPPixelData[i][i1]->Histograms[i2];
-        delete[] HULBPPixelData[i][i1]->Histograms;
-        delete[] HULBPPixelData[i][i1]->BackgroundHistogram;
-        delete[] HULBPPixelData[i][i1]->Weights;
-        delete HULBPPixelData[i][i1];
-      }
-
-    for (int i = 0; i < HUImageWidth / 2; i++)
-    {
-      delete[] HULBPPixelData[i];
-    }
-    delete[] HULBPPixelData;
-
-    if (MDMode == md_DLBPHistograms)
-      ReleaseHUOFData();
-
-    HUImageWidth = -1;
-    HUImageHeight = -1;
-    HULBPPixelData = NULL;
-    MDDataState = ps_Uninitialized;
-
-    // Release auxiliary variables
-    for (int i = 0; i < HUHistogramArea; ++i)
-      delete[] HUMaskColumnAddDel[i];
-    delete[] HUMaskColumnAddDel;
-
-    for (int i = 0; i < HUHistogramArea; ++i)
-      delete[] HUMaskRowAddDel[i];
-    delete[] HUMaskRowAddDel;
-
-    HUMaskColumnAddDel = NULL;
-    HUMaskRowAddDel = NULL;
-  }
-}
-
-
-void MotionDetection::ReleaseHUOFData()
-{
-  if (MDDataState != ps_Uninitialized)
-  {
-    if (HUOFPyramid)
-    {
-      cvReleaseImage(&HUOFPyramid);
-      HUOFPyramid = NULL;
-    }
-    if (HUOFPrevPyramid)
-    {
-      cvReleaseImage(&HUOFPrevPyramid);
-      HUOFPrevPyramid = NULL;
-    }
-    if (HUOFPoints[0])
-    {
-      cvFree(&HUOFPoints[0]);
-      HUOFPoints[0] = NULL;
-    }
-    if (HUOFPoints[1])
-    {
-      cvFree(&HUOFPoints[1]);
-      HUOFPoints[1] = NULL;
-    }
-    HUOFDataState = ps_Uninitialized;
-  }
-}
-
-
-void MotionDetection::ClearHUData()
-{
-  if (MDDataState != ps_Uninitialized)
-  {
-    for (int i = (HUImageWidth / 2) - 1; i >= 0; --i)
-      for (int i1 = HUImageHeight - 1; i1 >= 0; --i1)
-      {
-        for (int i2 = HUHistogramsPerPixel - 1; i2 >= 0; --i2)
-        {
-          memset(HULBPPixelData[i][i1]->Histograms[i2], 0,
-            HUHistogramBins * sizeof(float));
-          HULBPPixelData[i][i1]->Weights[i2] = 1.0 / HUHistogramsPerPixel;
-          HULBPPixelData[i][i1]->BackgroundHistogram[i2] = true;
-        }
-        HULBPPixelData[i][i1]->BackgroundRate = 1.0;
-        HULBPPixelData[i][i1]->LifeCycle = 0;
-      }
-    MDDataState = ps_Initialized;
-  }
-}
-
-
-void MotionDetection::DetectMotionsHU(MEImage& image)
-{
-  unsigned char *ImgData = NULL;
-  MEImage newimage = image;
-  float DiffAreas = 0;
-
-  // Init the histogram update data structures if needs be
-  if ((MDDataState == ps_Uninitialized) ||
-    (HUImageWidth != newimage.GetWidth() - HUHistogramArea + 1) ||
-    (HUImageHeight != newimage.GetHeight() - HUHistogramArea + 1))
-  {
-    InitHUData(newimage.GetWidth(), newimage.GetHeight());
-  }
-
-  if (newimage.GetLayers() == 1)
-  {
-    newimage.ConvertGrayscaleToRGB();
-  }
-
-  MEImage blueimage = newimage;
-  blueimage.ColorSpace(MEImage::csc_RGBtoCIELuv);
-
-  if (HUColorSpace != -1)
-  {
-    newimage.ColorSpace((MEImage::ColorSpaceConvertType)HUColorSpace);
-  }
-
-  if (Frames == 0)
-  {
-    MEImage BlueLayer;
-    blueimage.GetLayer(BlueLayer, 1);
-    BlueLayer.Resize(32, 24);
-    PreviousBlueLayer = BlueLayer;
-  }
-
-  Frames++;
-
-  // Detect the fast, big changes in the scene
-  MEImage BlueLayer;
-  blueimage.GetLayer(BlueLayer, 1);
-  BlueLayer.Resize(32, 24);
-  DiffAreas = BlueLayer.DifferenceAreas(PreviousBlueLayer, 12);
-
-  if (DiffAreas > 80)
-  {
-    MDDataState = ps_Initialized;
-    if (MDMode == md_DLBPHistograms)
-      HUOFDataState = ps_Initialized;
-    printf("Frame: %d - big changes in the scene (%f)", Frames, DiffAreas);
-    Frames = 1;
-    HUOFFrames = -1;
-  }
-  PreviousBlueLayer = BlueLayer;
-
-  if (Frames == 1)
-  {
-    CurrentImage = image;
-    PreviousImage = CurrentImage;
-  }
-  else
-    if (Frames > 1)
-    {
-      PreviousImage = CurrentImage;
-      CurrentImage = image;
-      // Optical flow correction of the camera movements
-      if (MDMode == md_DLBPHistograms)
-      {
-        OpticalFlowCorrection();
-      }
-    }
-
-  newimage.ConvertToGrayscale(MEImage::g_OpenCV);
-
-  if (HULBPMode != -1)
-  {
-    newimage.LBP((MEImage::LBPType)HULBPMode);
-  }
-
-  // Set some auxiliary variables
-  ImgData = newimage.GetImageData();
-  int DivisionOperator = (int)(log((double)256 / HUHistogramBins) / log((double) 2.)) + 1;
-
-  // Downscale the image
-  for (int i = newimage.GetRowWidth()*newimage.GetHeight() - 1; i >= 0; --i)
-  {
-    ImgData[i] >>= DivisionOperator;
-  }
-
-  UpdateModelHU(newimage, HULBPPixelData);
-
-  // Change the state of the HU data structures
-  if (MDDataState == ps_Initialized)
-  {
-    MDDataState = ps_Successful;
-  }
-  HUOFCamMovement = false;
-  ReadyMask = false;
-}
-
-
-void MotionDetection::UpdateModelHU(MEImage& image, MEPixelDataType*** model)
-{
-  float *CurrentHistogram = new float[HUHistogramBins];
-  float *CurrentHistogram2 = new float[HUHistogramBins];
-  unsigned char *ImgData = image.GetImageData();
-  int RowWidth = image.GetRowWidth();
-  int RowStart = (HUImageHeight - 1)*RowWidth;
-
-  memset(CurrentHistogram, 0, HUHistogramBins * sizeof(float));
-  // Calculate the first histogram
-  for (int y = HUHistogramArea - 1; y >= 0; --y)
-  {
-    for (int x = HUHistogramArea - 1; x >= 0; --x)
-    {
-      if ((HUMaskRowAddDel[y][1] > x) && (HUMaskRowAddDel[y][0] <= x) &&
-        (HUMaskColumnAddDel[x][1] > y) && (HUMaskColumnAddDel[x][0] <= y))
-      {
-        CurrentHistogram[ImgData[RowStart + HUImageWidth - 1 + x]]++;
-      }
-    }
-    RowStart += RowWidth;
-  }
-
-  // This cycle generates the last row of histograms
-  for (int y = HUImageHeight - 1; y >= 0; --y)
-  {
-    if (HUImageHeight - 1 > y)
-    {
-      // Delete and add a pixel column from the histogram data
-      for (int i = HUHistogramArea - 1; i >= 0; --i)
-      {
-        if (HUMaskColumnAddDel[i][0] != -1)
-          CurrentHistogram[ImgData[RowWidth*(y + HUMaskColumnAddDel[i][0]) + HUImageWidth - 1 + i]]++;
-        if (HUMaskColumnAddDel[i][1] != -1)
-          CurrentHistogram[ImgData[RowWidth*(y + HUMaskColumnAddDel[i][1]) + HUImageWidth - 1 + i]]--;
-      }
-    }
-
-    if (y % 2 == HUImageWidth % 2)
-    {
-      MEPixelDataType* PixelData = model[(HUImageWidth - 1) / 2][y];
-
-      // Allocate and initialize the pixel data if needs be
-      if (!PixelData)
-      {
-        // Memory allocation
-        PixelData = new MEPixelDataType;
-        PixelData->Weights = new float[HUHistogramsPerPixel];
-        PixelData->BackgroundHistogram = new bool[HUHistogramsPerPixel];
-        PixelData->Histograms = new float*[HUHistogramsPerPixel];
-        for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-          PixelData->Histograms[i2] = new float[HUHistogramBins];
-        PixelData->PreviousHistogram = new float[HUHistogramBins];
-
-        for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-        {
-          memcpy(PixelData->Histograms[i], CurrentHistogram, HUHistogramBins * sizeof(float));
-          PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
-          PixelData->BackgroundHistogram[i] = true;
-        }
-        PixelData->BackgroundRate = 1.0;
-        PixelData->LifeCycle = 0;
-        memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
-
-        model[(HUImageWidth - 1) / 2][y] = PixelData;
-      }
-      else {
-        bool InitHistograms = (MDDataState == ps_Initialized);
-
-        if (MDDataState != ps_Initialized && HUOFCamMovement)
-        {
-          // Histogram intersection between the previous and the current histogram
-          float Difference = 0.0;
-          for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
-          {
-            Difference += (float)(CurrentHistogram[i1] < PixelData->PreviousHistogram[i1] ?
-              CurrentHistogram[i1] : PixelData->PreviousHistogram[i1]);
-          }
-          Difference /= HUSamplePixels;
-
-          if (Difference < HUBackgrThres)
-            InitHistograms = true;
-        }
-        if (InitHistograms)
-        {
-          // Copy the histogram data to the HU data structures
-          for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-          {
-            memcpy(PixelData->Histograms[i], CurrentHistogram, HUHistogramBins * sizeof(float));
-            PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
-            PixelData->BackgroundHistogram[i] = true;
-          }
-          memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
-          PixelData->BackgroundRate = 1.0;
-          PixelData->LifeCycle = 0;
-        }
-        else {
-          // Update the HU data structures
-          UpdateHUPixelData(PixelData, CurrentHistogram);
-
-          if (MDMode == md_DLBPHistograms)
-          {
-            memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
-          }
-        }
-      }
-    }
-
-    // Copy the histogram
-    memcpy(CurrentHistogram2, CurrentHistogram, HUHistogramBins * sizeof(float));
-
-    // This cycle generates a column of histograms
-    for (int x = HUImageWidth - 2; x >= 0; --x)
-    {
-      RowStart = RowWidth*y;
-
-      // Delete and add a pixel column from the histogram data
-      for (int i = HUHistogramArea - 1; i >= 0; --i)
-      {
-        if (HUMaskRowAddDel[i][0] != -1)
-          CurrentHistogram2[ImgData[RowStart + x + HUMaskRowAddDel[i][0]]]++;
-        if (HUMaskRowAddDel[i][1] != -1)
-          CurrentHistogram2[ImgData[RowStart + x + HUMaskRowAddDel[i][1]]]--;
-
-        RowStart += RowWidth;
-      }
-      if (x % 2 == 0)
-      {
-        MEPixelDataType* PixelData = model[x / 2][y];
-
-        // Allocate and initialize the pixel data if needs be
-        if (!PixelData)
-        {
-          // Memory allocation
-          PixelData = new MEPixelDataType;
-          PixelData->Weights = new float[HUHistogramsPerPixel];
-          PixelData->BackgroundHistogram = new bool[HUHistogramsPerPixel];
-          PixelData->Histograms = new float*[HUHistogramsPerPixel];
-          for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-            PixelData->Histograms[i2] = new float[HUHistogramBins];
-          PixelData->PreviousHistogram = new float[HUHistogramBins];
-
-          for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-          {
-            memcpy(PixelData->Histograms[i], CurrentHistogram2, sizeof(CurrentHistogram2));
-            PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
-            PixelData->BackgroundHistogram[i] = true;
-          }
-          PixelData->BackgroundRate = 1.0;
-          PixelData->LifeCycle = 0;
-          model[x / 2][y] = PixelData;
-          memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
-        }
-        else {
-          bool InitHistograms = (MDDataState == ps_Initialized);
-
-          if (MDDataState != ps_Initialized && HUOFCamMovement)
-          {
-            // Histogram intersection between the previous and the current histogram
-            float Difference = 0.0;
-            for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
-            {
-              Difference += (float)(CurrentHistogram2[i1] < PixelData->PreviousHistogram[i1] ?
-                CurrentHistogram2[i1] : PixelData->PreviousHistogram[i1]);
-            }
-            Difference /= HUSamplePixels;
-
-            if (Difference < HUBackgrThres)
-              InitHistograms = true;
-          }
-          if (InitHistograms)
-          {
-            // Copy the histogram data to the HU data structures
-            for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-            {
-              memcpy(PixelData->Histograms[i], CurrentHistogram2, sizeof(CurrentHistogram2));
-              PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
-              PixelData->BackgroundHistogram[i] = true;
-            }
-            memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
-            PixelData->BackgroundRate = 1.0;
-            PixelData->LifeCycle = 0;
-          }
-          else {
-            // Update the HU data structures
-            UpdateHUPixelData(PixelData, CurrentHistogram2);
-
-            if (MDMode == md_DLBPHistograms)
-            {
-              memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
-            }
-          }
-        }
-      }
-
-    }
-  }
-  delete[] CurrentHistogram;
-  delete[] CurrentHistogram2;
-}
-
-
-void MotionDetection::UpdateHUPixelData(MEPixelDataType* PixelData, const float *histogram)
-{
-  int MaxIndex = 0;
-  float MaxValue = -1;
-  bool Replace = true;
-  float *IntersectionResults = new float[HUHistogramsPerPixel];
-
-  PixelData->LifeCycle++;
-  PixelData->BackgroundRate = 0.0;
-
-  // Compute intersection between the currect and older histograms
-  for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-  {
-    // Histogram intersection
-    float Difference = 0.0;
-    for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
-    {
-      Difference += (float)histogram[i1] < PixelData->Histograms[i][i1] ?
-        (float)histogram[i1] : PixelData->Histograms[i][i1];
-    }
-
-    IntersectionResults[i] = (float)Difference / (float)(HUSamplePixels);
-
-    if (PixelData->BackgroundHistogram[i] &&
-      IntersectionResults[i] > PixelData->BackgroundRate)
-    {
-      PixelData->BackgroundRate = IntersectionResults[i];
-    }
-
-    if (MaxValue < IntersectionResults[i])
-    {
-      MaxValue = IntersectionResults[i];
-      MaxIndex = i;
-    }
-
-    Replace = Replace && (IntersectionResults[i] < HUPrThres);
-  }
-
-  // Replace the histogram with the lowest weight
-  if (Replace)
-  {
-    // Find the histogram with minimal weight
-    int MinIndex = 0;
-    float MinValue = PixelData->Weights[0];
-    for (int i1 = HUHistogramsPerPixel - 1; i1 > 0; --i1)
-    {
-      if (MinValue > PixelData->Weights[i1])
-      {
-        MinValue = PixelData->Weights[i1];
-        MinIndex = i1;
-      }
-    }
-
-    PixelData->Weights[MinIndex] = 0.01;
-    for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
-      PixelData->Histograms[MinIndex][i1] = (float)histogram[i1];
-    PixelData->BackgroundHistogram[MinIndex] = 0;
-
-    // Normalize the weights
-    float sum = 0;
-    for (int i1 = HUHistogramsPerPixel - 1; i1 >= 0; --i1)
-      sum += PixelData->Weights[i1];
-
-    for (int i1 = HUHistogramsPerPixel - 1; i1 >= 0; --i1)
-      PixelData->Weights[i1] = PixelData->Weights[i1] / sum;
-
-    return;
-  }
-
-  float LearningRate = HUHistLRate;
-
-  if (PixelData->LifeCycle < 100)
-    LearningRate += (float)(100 - PixelData->LifeCycle) / 100;
-  else
-    if (MDMode == md_DLBPHistograms && HUOFFrames != -1 && HUOFFrames < 40)
-      LearningRate += (HUOFFrames < 80 ? 0.05 : 0);
-
-  // Match was found -> Update the histogram of the best match
-  for (int i = HUHistogramBins - 1; i >= 0; --i)
-  {
-    PixelData->Histograms[MaxIndex][i] *= (1.0 - LearningRate);
-    PixelData->Histograms[MaxIndex][i] += LearningRate*(float)histogram[i];
-  }
-
-  LearningRate = HUWeightsLRate;
-  if (PixelData->LifeCycle < 100)
-    LearningRate += (float)(100 - PixelData->LifeCycle) / 100;
-  else
-    if (MDMode == md_DLBPHistograms && HUOFFrames != -1 && HUOFFrames < 40)
-      LearningRate += (HUOFFrames < 80 ? 0.05 : 0);
-
-  // Update the weights of the histograms
-  for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-  {
-    PixelData->Weights[i] =
-      (LearningRate*(i == MaxIndex) + (1.0 - LearningRate)*PixelData->Weights[i]);
-  }
-
-  // Order and select the background histograms
-  float **Weights = new float*[HUHistogramsPerPixel];
-  for (int i = 0; i < HUHistogramsPerPixel; ++i)
-    Weights[i] = new float[2];
-
-  for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
-  {
-    Weights[i][0] = (float)i;
-    Weights[i][1] = PixelData->Weights[i];
-  }
-
-  for (int i1 = HUHistogramsPerPixel - 1; i1 >= 2; --i1)
-    for (int i = i1; i >= 1; --i)
-    {
-      if (Weights[i][1] <= Weights[i - 1][1])
-      {
-        float tmp = Weights[i][0];
-        float tmp2 = Weights[i][1];
-
-        Weights[i][0] = Weights[i - 1][0];
-        Weights[i][1] = Weights[i - 1][1];
-
-        Weights[i - 1][0] = tmp;
-        Weights[i - 1][1] = tmp2;
-      }
-    }
-
-  float Sum = 0;
-  int i = 0;
-
-  for (i = HUHistogramsPerPixel - 1; i >= 0; --i)
-  {
-    Sum += Weights[i][1];
-    PixelData->BackgroundHistogram[(int)Weights[i][0]] = true;
-
-    if (Sum > HUBackgrThres)
-      break;
-  }
-  for (int i1 = i - 1; i1 >= 0; --i1)
-  {
-    PixelData->BackgroundHistogram[(int)Weights[i1][0]] = false;
-  }
-  delete[] IntersectionResults;
-  for (int i = 0; i < HUHistogramsPerPixel; ++i)
-    delete[] Weights[i];
-  delete[] Weights;
-}
-
-
-void MotionDetection::OpticalFlowCorrection()
-{
-  IplImage *PreviousGray = NULL, *CurrentGray = NULL;
-  char* PointsStatus = (char*)cvAlloc(HUOFPointsNumber);
-  int i = 0, i1 = 0;
-
-  if (HUOFFrames != -1)
-    HUOFFrames++;
-
-  // Convert the images into grayscale
-  if (CurrentImage.GetLayers() > 1)
-  {
-    CurrentGray = cvCreateImage(cvGetSize(CurrentImage.GetIplImage()), IPL_DEPTH_8U, 1);
-    cvCvtColor(CurrentImage.GetIplImage(), CurrentGray, CV_BGR2GRAY);
-  }
-  else
-    CurrentGray = (IplImage*)CurrentImage.GetIplImage();
-  if (PreviousImage.GetLayers() > 1)
-  {
-    PreviousGray = cvCreateImage(cvGetSize(CurrentImage.GetIplImage()), IPL_DEPTH_8U, 1);
-    cvCvtColor(PreviousImage.GetIplImage(), PreviousGray, CV_BGR2GRAY);
-  }
-  else
-    PreviousGray = (IplImage*)PreviousImage.GetIplImage();
-
-  if (HUOFDataState != ps_Successful)
-  {
-    printf("Search new corners\n");
-    IplImage* TempEig = cvCreateImage(cvGetSize(CurrentGray), 32, 1);
-    IplImage* Temp = cvCreateImage(cvGetSize(CurrentGray), 32, 1);
-    double MinDistance = (CurrentImage.GetWidth() + CurrentImage.GetHeight()) / 20;
-    HUOFPointsNumber = MaxTrackedPoints = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
-
-    // Search good trackable points
-    cvGoodFeaturesToTrack(PreviousGray, TempEig, Temp,
-      HUOFPoints[0], &HUOFPointsNumber,
-      0.01, MinDistance, NULL, 3);
-    MaxTrackedPoints = HUOFPointsNumber;
-    // Release temporary images
-    cvReleaseImage(&TempEig);
-    cvReleaseImage(&Temp);
-    // Realloc the point status array
-    if (PointsStatus)
-    {
-      cvFree(&PointsStatus);
-      PointsStatus = NULL;
-    }
-
-    if (MaxTrackedPoints < 2)
-    {
-      HUOFDataState = ps_Initialized;
-      HUOFPointsNumber = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
-      return;
-    }
-    else
-      HUOFDataState = ps_Successful;
-    PointsStatus = (char*)cvAlloc(HUOFPointsNumber);
-  }
-
-  cvCalcOpticalFlowPyrLK(PreviousGray, CurrentGray, HUOFPrevPyramid, HUOFPyramid,
-    HUOFPoints[0], HUOFPoints[1], HUOFPointsNumber,
-    cvSize(10, 10), 3, PointsStatus, NULL,
-    cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 5, 1), 0);
-
-  // Count the distances of the tracked points
-  int **Distances = new int*[HUOFPointsNumber];
-  for (int i = 0; i < HUOFPointsNumber; ++i)
-    Distances[i] = new int[3];
-
-  int DistanceMax = 0;
-  for (i = 0; i < HUOFPointsNumber; ++i)
-  {
-    int DiffX = (int)MERound(HUOFPoints[1][i].x - HUOFPoints[0][i].x);
-    int DiffY = (int)MERound(HUOFPoints[1][i].y - HUOFPoints[0][i].y);
-    if ((PointsStatus[i] == 1) && !((DiffX == 0) && (DiffY == 0)))
-    {
-      bool found = false;
-      // Create a list from the differences to count them
-      for (i1 = 0; i1 < DistanceMax; ++i1)
-      {
-        if ((Distances[i1][0] == DiffX) &&
-          (Distances[i1][1] == DiffY))
-        {
-          Distances[i1][2]++;
-          found = true;
-          break;
-        }
-      }
-      if ((!found) && !((DiffX == 0) && (DiffY == 0)))
-      {
-        Distances[DistanceMax][0] = (int)MERound(HUOFPoints[1][i].x - HUOFPoints[0][i].x);
-        Distances[DistanceMax][1] = (int)MERound(HUOFPoints[1][i].y - HUOFPoints[0][i].y);
-        Distances[DistanceMax][2] = 1;
-        DistanceMax++;
-      }
-    }
-  }
-
-  // Sort the results
-  for (int i1 = DistanceMax - 1; i1 >= 2; --i1)
-  {
-    for (int i = i1; i >= 1; --i)
-    {
-      if ((Distances[i][2] > Distances[i - 1][2]) ||
-        ((Distances[i][2] == Distances[i - 1][2]) &&
-        (abs(Distances[i][0]) + abs(Distances[i][1]) <
-          abs(Distances[i - 1][0]) + abs(Distances[i - 1][1]))))
-      {
-        int tmp = Distances[i][0];
-        int tmp2 = Distances[i][1];
-        int tmp3 = Distances[i][2];
-
-        Distances[i][0] = Distances[i - 1][0];
-        Distances[i][1] = Distances[i - 1][1];
-        Distances[i][2] = Distances[i - 1][2];
-
-        Distances[i - 1][0] = tmp;
-        Distances[i - 1][1] = tmp2;
-        Distances[i - 1][2] = tmp3;
-      }
-    }
-  }
-
-  float MoveX = 0.0;
-  float MoveY = 0.0;
-  int SampleNums = 0;
-  float DistanceMeasure = 0.0;
-
-  // Calculate the final camera movement
-  for (i = 0; i < DistanceMax; ++i)
-  {
-    if ((Distances[i][2] <= MaxTrackedPoints / 10))
-      break;
-
-    if (i > 0)
-    {
-      DistanceMeasure += (Distances[i][0] - Distances[i - 1][0])*(Distances[i][0] - Distances[i - 1][0]);
-      DistanceMeasure += (Distances[i][1] - Distances[i - 1][1])*(Distances[i][1] - Distances[i - 1][1]);
-    }
-
-    MoveX += Distances[i][0] * Distances[i][2];
-    MoveY += Distances[i][1] * Distances[i][2];
-    SampleNums += Distances[i][2];
-  }
-
-  if (SampleNums > 0)
-  {
-    MoveX = MERound(MoveX / SampleNums);
-    MoveY = MERound(MoveY / SampleNums);
-  }
-
-  if (!((MoveX == 0) && (MoveY == 0)) &&
-    (SampleNums > MaxTrackedPoints / 2))
-  {
-    HUOFCamMovementX += (int)MoveX;
-    int HUOFCamMovementY = (int)MoveY;
-    int MaxX = (HUImageWidth / 2) - 1;
-    int MaxY = HUImageHeight - 1;
-    /*
-    printf("-----------\n");
-
-    for (i = 0; i < DistanceMax; ++i)
-    printf("%d: %d,%d\n", Distances[i][2], Distances[i][0], Distances[i][1]);
-
-    printf("FINAL: %d,%d,%1.2f\n", (int)MoveX, (int)MoveY, DistanceMeasure);
-    printf("-----------\n");
-    printf("Camera movement: %d,%d,%d (max: %d, current: %d)\n",
-    SampleNums, HUOFCamMovementX, HUOFCamMovementY, MaxTrackedPoints, HUOFPointsNumber);
-    */
-    HUOFFrames = 0;
-    HUOFCamMovement = true;
-
-    if (!(HUOFCamMovementY == 0 && HUOFCamMovementX >= -1 && HUOFCamMovementX <= 1))
-    {
-      MEPixelDataType ***PreviousData = new MEPixelDataType**[MaxX + 1];
-
-      for (int i = 0; i < MaxX + 1; ++i)
-        PreviousData[i] = new MEPixelDataType*[MaxY + 1];
-
-      // Camera movement being happened
-      for (int y = MaxY; y >= 0; --y)
-      {
-        for (int x = MaxX; x >= 0; --x)
-        {
-          PreviousData[x][y] = NULL;
-        }
-      }
-
-      // Move the LBP data to new locations
-      for (int y = MaxY; y >= 0; --y)
-      {
-        for (int x = MaxX; x >= 0; --x)
-        {
-          int NewX = x + (HUOFCamMovementX / 2);
-          int NewY = y + HUOFCamMovementY;
-
-          if (NewX >= 0 && NewX <= MaxX &&
-            NewY >= 0 && NewY <= MaxY)
-          {
-            if (HULBPPixelData[NewX][NewY])
-            {
-              PreviousData[NewX][NewY] = HULBPPixelData[NewX][NewY];
-              HULBPPixelData[NewX][NewY] = NULL;
-              if (PreviousData[x][y])
-              {
-                HULBPPixelData[NewX][NewY] = PreviousData[x][y];
-                PreviousData[x][y] = NULL;
-              }
-              else
-              {
-                HULBPPixelData[NewX][NewY] = HULBPPixelData[x][y];
-                HULBPPixelData[x][y] = NULL;
-              }
-            }
-            else
-            {
-              if (PreviousData[x][y])
-              {
-                HULBPPixelData[NewX][NewY] = PreviousData[x][y];
-                PreviousData[x][y] = NULL;
-              }
-              else
-              {
-                HULBPPixelData[NewX][NewY] = HULBPPixelData[x][y];
-                HULBPPixelData[x][y] = NULL;
-              }
-            }
-          }
-          else
-          {
-            if (HULBPPixelData[x][y])
-            {
-              delete[] HULBPPixelData[x][y]->PreviousHistogram;
-              for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-                delete[] HULBPPixelData[x][y]->Histograms[i2];
-              delete[] HULBPPixelData[x][y]->Histograms;
-              delete[] HULBPPixelData[x][y]->BackgroundHistogram;
-              delete[] HULBPPixelData[x][y]->Weights;
-              delete HULBPPixelData[x][y];
-              HULBPPixelData[x][y] = NULL;
-            }
-          }
-        }
-      }
-
-      // Release unused data
-      for (int y = MaxY; y >= 0; --y)
-      {
-        for (int x = MaxX; x >= 0; --x)
-        {
-          if (PreviousData[x][y])
-          {
-            delete[] PreviousData[x][y]->PreviousHistogram;
-            for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
-              delete[] PreviousData[x][y]->Histograms[i2];
-            delete[] PreviousData[x][y]->Histograms;
-            delete[] PreviousData[x][y]->BackgroundHistogram;
-            delete[] PreviousData[x][y]->Weights;
-            delete PreviousData[x][y];
-            PreviousData[x][y] = NULL;
-          }
-        }
-      }
-
-      HUOFCamMovementX = HUOFCamMovementX % 1;
-
-      for (int i = 0; i < MaxX + 1; ++i)
-        delete[] PreviousData[i];
-      delete[] PreviousData;
-    }
-  }
-
-  i1 = 0;
-  // Throw the missed points away
-  for (i = 0; i < HUOFPointsNumber; ++i)
-  {
-    if (PointsStatus[i] == 1)
-    {
-      HUOFPoints[0][i1] = HUOFPoints[1][i];
-      i1++;
-    }
-  }
-  HUOFPointsNumber -= i + 1 - i1;
-
-  if (HUOFPointsNumber < MaxTrackedPoints / 2)
-  {
-    printf("Re-init the optical flow\n");
-    HUOFDataState = ps_Initialized;
-    HUOFPointsNumber = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
-  }
-  // Free memory
-  if (PreviousGray != PreviousImage.GetIplImage())
-    cvReleaseImage(&PreviousGray);
-  if (CurrentGray != CurrentImage.GetIplImage())
-    cvReleaseImage(&CurrentGray);
-  cvFree(&PointsStatus);
-
-  for (int i = 0; i < HUOFPointsNumber; ++i)
-    delete[] Distances[i];
-  delete[] Distances;
-}
-
-
-void MotionDetection::GetMotionsMaskHU(MEImage& mask_image)
-{
-  if (MDDataState != ps_Successful)
-  {
-    mask_image.Clear();
-    return;
-  }
-
-  // Reallocate the mask image if needs be
-  if ((HUImageWidth + HUHistogramArea - 1 != mask_image.GetWidth()) ||
-    (HUImageHeight + HUHistogramArea - 1 != mask_image.GetHeight()) ||
-    (mask_image.GetLayers() != 1))
-  {
-    mask_image.Realloc(HUImageWidth + HUHistogramArea - 1,
-      HUImageHeight + HUHistogramArea - 1, 1);
-  }
-  mask_image.Clear();
-  // Generate the mask image
-  unsigned char* MaskImgData = mask_image.GetImageData();
-  int RowStart = (mask_image.GetHeight() - HUHistogramArea / 2)*mask_image.GetRowWidth();
-  int RowWidth = mask_image.GetRowWidth();
-
-  // Generate a graph about the histogram data
-  Graph::node_id **Nodes = new Graph::node_id*[HUImageWidth / 2];
-  for (int i = 0; i < HUImageWidth / 2; ++i)
-    Nodes[i] = new Graph::node_id[HUImageHeight];
-  Graph *LBPGraph = new Graph();
-
-  for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
-  {
-    for (int y = HUImageHeight - 1; y >= 0; --y)
-    {
-      Nodes[x][y] = LBPGraph->add_node();
-    }
-  }
-
-  for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
-  {
-    for (int y = HUImageHeight - 1; y >= 0; --y)
-    {
-      LBPGraph->set_tweights(Nodes[x][y], 1,
-        (short int)(HUMinCutWeight*(1 - HULBPPixelData[x][y]->BackgroundRate)));
-
-      if (x > 0 && y > 0)
-      {
-        LBPGraph->add_edge(Nodes[x][y], Nodes[x - 1][y], 1, 1);
-        LBPGraph->add_edge(Nodes[x][y], Nodes[x][y - 1], 1, 1);
-      }
-    }
-  }
-
-  LBPGraph->maxflow();
-
-  for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
-  {
-    for (int y = HUImageHeight - 1; y >= 0; --y)
-    {
-      if (LBPGraph->what_segment(Nodes[x][y]) == Graph::SINK)
-        HULBPPixelData[x][y]->BackgroundRate = 0.0;
-      else
-        HULBPPixelData[x][y]->BackgroundRate = 1.0;
-    }
-  }
-
-  delete LBPGraph;
-  LBPGraph = NULL;
-  for (int y = HUImageHeight - 1; y >= 0; --y)
-  {
-    for (int x = HUImageWidth - 1; x >= 0; --x)
-    {
-      if (y % 2 == (x + 1) % 2)
-        MaskImgData[RowStart + x + (HUHistogramArea / 2)] =
-        (HULBPPixelData[x / 2][y]->BackgroundRate == 0.0) ? 255 : 0;
-      else
-      {
-        MaskImgData[RowStart + x + (HUHistogramArea / 2)] =
-          ((int)(x > 1 && HULBPPixelData[(x / 2) - 1][y]->BackgroundRate == 0.0) +
-          (int)(x < mask_image.GetWidth() - HUHistogramArea - 1 &&
-            HULBPPixelData[(x / 2) + 1][y]->BackgroundRate == 0.0) +
-            (int)(y > 0 && HULBPPixelData[x / 2][y - 1]->BackgroundRate == 0.0) +
-            (int)(y < mask_image.GetHeight() - HUHistogramArea &&
-              HULBPPixelData[x / 2][y + 1]->BackgroundRate == 0.0) > 1)
-          ? 255 : 0;
-      }
-    }
-    RowStart -= RowWidth;
-  }
-
-  cvFloodFill(mask_image.GetIplImage(), cvPoint(0, 0), cvScalar(128, 128, 128, 128),
-    cvScalar(0, 0, 0, 0), cvScalar(0, 0, 0, 0));
-  for (int i = ((IplImage*)mask_image.GetIplImage())->widthStep*((IplImage*)mask_image.GetIplImage())->height - 1; i >= 0; --i)
-  {
-    if (MaskImgData[i] == 128)
-    {
-      MaskImgData[i] = 0;
-    }
-    else
-    {
-      if (MaskImgData[i] == 0)
-      {
-        MaskImgData[i] = 255;
-      }
-    }
-  }
-  // Apply an erode operator
-  mask_image.Erode(1);
-
-  for (int i = 0; i < HUImageWidth / 2; ++i)
-    delete[] Nodes[i];
-  delete[] Nodes;
-}
-
-
-void MotionDetection::SetSampleMaskHU(SampleMaskType mask_type, int desiredarea)
-{
-  if (HUMaskColumnAddDel == NULL || HUMaskRowAddDel == NULL)
-  {
-    printf("Auxiliary variables are NULL\n");
-    return;
-  }
-
-  // Generate a mask for computing the histograms
-  IplImage *MaskImage = cvCreateImage(cvSize(HUHistogramArea, HUHistogramArea), 8, 1);
-  int DesiredArea = desiredarea <= 0 ? HUHistogramBins * 2 : desiredarea;
-
-  int **CalculationMask = new int*[HUHistogramArea];
-  for (int i = 0; i < HUHistogramArea; ++i)
-    CalculationMask[i] = new int[HUHistogramArea];
-
-  int SquareSide = (int)MERound(sqrt((float)DesiredArea));
-  int CircleRadius = (int)MERound(sqrt((float)DesiredArea / ME_PI_VALUE));
-  int EllipseA = (int)MERound(HUHistogramArea / 2 + 1);
-  int EllipseB = (int)MERound(DesiredArea / (EllipseA*1.2*ME_PI_VALUE));
-
-  cvSetZero(MaskImage);
-
-  switch (mask_type)
-  {
-  case sm_Circle:
-    cvCircle(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
-      CircleRadius, CV_RGB(1, 1, 1), -1);
-    break;
-
-  case sm_Square:
-    cvRectangle(MaskImage,
-      cvPoint(HUHistogramArea / 2 - SquareSide / 2, HUHistogramArea / 2 - SquareSide / 2),
-      cvPoint(HUHistogramArea / 2 + SquareSide / 2, HUHistogramArea / 2 + SquareSide / 2),
-      CV_RGB(1, 1, 1), -1);
-    break;
-
-  case sm_Ellipse:
-    cvEllipse(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
-      cvSize(EllipseA, EllipseB), 45, 0, 360,
-      CV_RGB(1, 1, 1), -1);
-    break;
-
-  case sm_RandomPixels:
-    HUSamplePixels = 0;
-    while (HUSamplePixels != DesiredArea)
-    {
-      int i = rand() % HUHistogramArea;
-      int j = rand() % HUHistogramArea;
-
-      if (MaskImage->imageData[i*MaskImage->widthStep + j] == 0)
-      {
-        MaskImage->imageData[i*MaskImage->widthStep + j] = 1;
-        HUSamplePixels++;
-      }
-    }
-    break;
-
-  default:
-    cvCircle(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
-      (int)MERound(sqrt((float)DesiredArea / ME_PI_VALUE)), CV_RGB(1, 1, 1), -1);
-    break;
-  }
-
-  HUSamplePixels = 0;
-  //memset(CalculationMask, 0, sizeof(CalculationMask));
-
-  for (int i = 0; i < HUHistogramArea; ++i)
-  {
-    for (int i1 = 0; i1 < HUHistogramArea; ++i1)
-    {
-      if (MaskImage->imageData[i*MaskImage->widthStep + i1] != 0)
-      {
-        HUSamplePixels++;
-        CalculationMask[i][i1] = 1;
-      }
-      else {
-        CalculationMask[i][i1] = 0;
-      }
-    }
-  }
-
-  // Fill an auxiliary variable for fast computing with data
-  for (int i = 0; i < HUHistogramArea; ++i)
-  {
-    HUMaskColumnAddDel[i][0] = -1;
-    for (int i1 = 0; i1 < HUHistogramArea; ++i1)
-    {
-      if (CalculationMask[i][i1] != 0)
-      {
-        HUMaskColumnAddDel[i][0] = i1;
-        break;
-      }
-    }
-    HUMaskColumnAddDel[i][1] = -1;
-    for (int i1 = HUHistogramArea - 1; i1 >= 0; --i1)
-    {
-      if (CalculationMask[i][i1] != 0)
-      {
-        HUMaskColumnAddDel[i][1] = i1 + 1;
-        break;
-      }
-    }
-  }
-
-  // Fill an auxiliary variable for fast computing with data
-  for (int i = 0; i < HUHistogramArea; ++i)
-  {
-    HUMaskRowAddDel[i][0] = -1;
-    for (int i1 = 0; i1 < HUHistogramArea; ++i1)
-    {
-      if (CalculationMask[i1][i] != 0)
-      {
-        HUMaskRowAddDel[i][0] = i1;
-        break;
-      }
-    }
-    HUMaskRowAddDel[i][1] = -1;
-    for (int i1 = HUHistogramArea - 1; i1 >= 0; --i1)
-    {
-      if (CalculationMask[i1][i] != 0)
-      {
-        HUMaskRowAddDel[i][1] = i1 + 1;
-        break;
-      }
-    }
-  }
-
-  // Freeing memory
-  cvReleaseImage(&MaskImage);
-
-  for (int i = 0; i < HUHistogramArea; ++i)
-    delete[] CalculationMask[i];
-  delete[] CalculationMask;
-}
diff --git a/package_bgs/LBP_MRF/MotionDetection.hpp b/package_bgs/LBP_MRF/MotionDetection.hpp
deleted file mode 100644
index e58c93c107f448d62b7cf2dd0c57c7e8eb8c0b78..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/MotionDetection.hpp
+++ /dev/null
@@ -1,413 +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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-#pragma once
-
- /**
-  *  @addtogroup mindeye
-  *  @{
-  */
-
-#include "MEDefs.hpp"
-#include "MEImage.hpp"
-
-class CvBGStatModel;
-class CvPoint2D32f;
-
-// Struct for histogram update data of a pixel
-struct MEPixelDataType;
-
-/**
- * MotionDetection
- * @brief Extract moving objects from image sequence
- */
-class MotionDetection
-{
-public:
-
-  /// Types of motion detection
-  typedef enum
-  {
-    md_Min = 0,               /*!< Minimum value */
-    md_NotDefined = md_Min,   /*!< Not defined */
-    md_DLBPHistograms,        /*!< Dynamic LBP */
-    md_LBPHistograms,         /*!< Normal LBP */
-    md_Max = md_LBPHistograms /*!< Maximum value */
-  } DetectorType;
-
-  /// Types of sample mask
-  typedef enum
-  {
-    sm_Min = 0,              /*!< Minimum value */
-    sm_Circle = sm_Min,      /*!< Circle */
-    sm_Square,               /*!< Square */
-    sm_Ellipse,              /*!< Ellipse */
-    sm_RandomPixels,         /*!< Random pixels */
-    sm_Max = sm_RandomPixels /*!< Maximum value */
-  } SampleMaskType;
-
-  /// Types of motion detection parameters
-  typedef enum
-  {
-    mdp_Min = 0,                         /*!< Minimum value */
-    mdp_HUProximityThreshold = mdp_Min,  /*!< Proximity threshold */
-    mdp_HUBackgroundThreshold,           /*!< Background threshold */
-    mdp_HUHistogramLearningRate,         /*!< Histogram learning rate */
-    mdp_HUWeightsLearningRate,           /*!< Weights learning rate */
-    mdp_HUMinCutWeight,                  /*!< Minimum cut weight */
-    mdp_HUDesiredSamplePixels,           /*!< Desired sample pixels */
-    mdp_HUHistogramsPerPixel,            /*!< Histogram per pixel */
-    mdp_HUHistogramArea,                 /*!< Histogram area */
-    mdp_HUHistogramBins,                 /*!< Histogram bins */
-    mdp_HUColorSpace,                    /*!< Color space */
-    mdp_HULBPMode,                       /*!< LBP mode */
-    mdp_Max = mdp_HULBPMode              /*!< Maximum value */
-  } ParametersType;
-
-  /*!
-   * @brief Class constructor
-   *
-   * @param mode Detection mode
-   *
-   * Class constructor with the possibility to specify the detection mode.
-   * The default is dynamic LBP.
-   *
-   */
-
-  MotionDetection(DetectorType mode = md_DLBPHistograms);
-  /// Destructor of class
-  ~MotionDetection();
-
-  /*
-  -------------------------------------------------------------------
-                           Motion methods
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Set the mode of the motion detection
-   *
-   * @param newmode New mode of detection
-   *
-   * Set the mode of the motion detection.
-   *
-   */
-
-  void SetMode(DetectorType newmode);
-
-  /*!
-   * @brief Get a parameter value of the motion detection
-   *
-   * @param param Parameter of the detection
-   *
-   * @return Queried value
-   *
-   * Get the value of a parameter of the motion detection.
-   *
-   */
-
-  float GetParameter(ParametersType param) const;
-
-  /*!
-   * @brief Set a parameter of the motion detection
-   *
-   * @param param Parameter of the detection
-   * @param value New value
-   *
-   * Set a new value to a parameter of the motion detection.
-   *
-   */
-
-  void SetParameter(ParametersType param, float value);
-
-  /*!
-   * @brief Detect the motions on an image
-   *
-   * @param image Image to process
-   *
-   * The function designed to search motions in image streams
-   * thus it needs to process the image sequence frame by frame.
-   * It processes an image from this sequence and searches moving blobs
-   * on that.
-   *
-   */
-
-  void DetectMotions(MEImage& image);
-
-  /*!
-   * @brief Get mask image with detected motions
-   *
-   * @param mask_image Result mask image
-   *
-   * The function creates a mask image on which the objects are
-   * indicated by white blobs.
-   *
-   */
-
-  void GetMotionsMask(MEImage& mask_image);
-
-  /*!
-   * @brief Calculate results of the motion detection
-   *
-   * @param referenceimage Reference mask image
-   * @param tnegatives True negative pixels
-   * @param tpositives True positive pixels
-   * @param ttnegatives Total true negative pixels
-   * @param ttpositives Total true positive pixels
-   *
-   * The function calculates the results of the motion detection
-   * between the current motion mask and a given reference mask
-   * image.
-   *
-   */
-
-  void CalculateResults(MEImage& referenceimage, int& tnegatives, int& tpositives,
-    int& ttnegatives, int& ttpositives);
-
-private:
-
-  /*!
-   * @brief Release data structures
-   *
-   * Function releases the data structures.
-   *
-   */
-
-  void ReleaseData();
-
-  /*
-  -------------------------------------------------------------------
-                    Histogram update methods
-  -------------------------------------------------------------------
-  */
-
-  /*!
-   * @brief Init HU data structures
-   *
-   * @param imagewidth Image width for HU to process
-   * @param imageheight Image height for HU to process
-   *
-   * Function allocates/re-allocates the HU data structures and they
-   * are cleared if needs be.
-   *
-   */
-
-  void InitHUData(int imagewidth, int imageheight);
-
-  /*!
-   * @brief Init HU optical flow data structures
-   *
-   * @param imagewidth Image width for HU to process
-   * @param imageheight Image height for HU to process
-   *
-   * Function allocates/re-allocates the HU optical flow
-   * data structures.
-   *
-   */
-
-  void InitHUOFData(int imagewidth, int imageheight);
-
-  /*!
-   * @brief Release HU data structures
-   *
-   * Function releases the HU data structures.
-   *
-   */
-
-  void ReleaseHUData();
-
-  /*!
-   * @brief Release HU optical flow data structures
-   *
-   * Function releases the HU optical flow data structures.
-   *
-   */
-
-  void ReleaseHUOFData();
-
-  /*!
-   * @brief Clear HU data structures
-   *
-   * Function clears the HU data structures.
-   *
-   */
-
-  void ClearHUData();
-
-  /*!
-   * @brief Get mask image with detected motions by histogram update
-   *
-   * @param mask_image Result mask image
-   *
-   * The function creates a mask image on which the objects are
-   * indicated by white blobs.
-   *
-   */
-
-  void GetMotionsMaskHU(MEImage& mask_image);
-
-  /*!
-   * @brief Set the sample mask
-   *
-   * @param mask_type Type of the mask
-   * @param desiredarea The desired area size of the mask
-   *
-   * The function creates a sample mask with a desired form
-   * (square, circle, ellipse, random pixels) and size.
-   *
-   */
-
-  void SetSampleMaskHU(SampleMaskType mask_type, int desiredarea);
-
-  /*!
-   * @brief Detect the motions on an image with histogram update
-   *
-   * @param image Image to process
-   *
-   * The function designed to search motions in image streams
-   * thus it needs to process the image sequence frame by frame.
-   * It processes an image from this sequence and searches moving blobs
-   * on that. It uses histogram update method.
-   *
-   */
-
-  void DetectMotionsHU(MEImage& image);
-
-  /*!
-   * @brief Update a model
-   *
-   * @param image Image to process
-   * @param model Model to update
-   *
-   * The function updates a histogram model of the image.
-   *
-   */
-
-  void UpdateModelHU(MEImage& image, MEPixelDataType*** model);
-
-  /*!
-   * @brief Update the HU data structure for one pixel
-   *
-   * @param pixeldata Pixel data
-   * @param histogram Current histogram
-   *
-   * This method updates the HU data for one pixel.
-   *
-   */
-
-  void UpdateHUPixelData(MEPixelDataType* pixeldata, const float *histogram);
-
-  /*!
-   * @brief Optical flow correction of the camera movements
-   *
-   * The function trackes some points on the scene if a camera movement is
-   * detected, then the LBP pixel data is corrected.
-   *
-   */
-
-  void OpticalFlowCorrection();
-
-private:
-  // GENERAL VARIABLES
-  /// Motion detection type
-  DetectorType MDMode;
-  /// State of the data structures
-  MEProcessStateType MDDataState;
-  /// Processed number in the image sequence
-  int Frames;
-  /// Store the current image
-  MEImage CurrentImage;
-  /// Store the previous image
-  MEImage PreviousImage;
-  /// Store the current mask image
-  MEImage MaskImage;
-  /// Store the current mask image
-  bool ReadyMask;
-  // HISTOGRAM UPDATE VARIABLES
-  /// Color space (-1 = no conversion)
-  int HUColorSpace;
-  /// LBP calculation mode (-1 = no conversion)
-  int HULBPMode;
-  /// Histograms per pixel
-  int HUHistogramsPerPixel;
-  /// Histogram area
-  int HUHistogramArea;
-  /// Histogram bins
-  int HUHistogramBins;
-  /// Image width for histogram update
-  int HUImageWidth;
-  /// Image height for histogram update
-  int HUImageHeight;
-  /// Data of the LBP histograms
-  MEPixelDataType ***HULBPPixelData;
-  /// Store the previous blue layer
-  MEImage PreviousBlueLayer;
-  /// Histogram proximity threshold
-  float HUPrThres;
-  /// Background selection threshold
-  float HUBackgrThres;
-  /// Histogram learning rate
-  float HUHistLRate;
-  /// Weights learning rate
-  float HUWeightsLRate;
-  /// Pixel number used to calculate the histograms
-  int HUSamplePixels;
-  /// The desired pixel number used to calculate the histograms (-1 = Auto)
-  int HUDesiredSamplePixels;
-  /// Min cut weight
-  float HUMinCutWeight;
-  /// Auxiliary variable for computing the histograms in a column
-  int **HUMaskColumnAddDel;
-  /// Auxiliary variable for computing the histograms in a row
-  int **HUMaskRowAddDel;
-  // OPTICAL FLOW VARIABLES
-  /// State of the optical flow
-  MEProcessStateType HUOFDataState;
-  /// Number of the tracked points with optical flow
-  int HUOFPointsNumber;
-  /// Tracked points
-  CvPoint2D32f* HUOFPoints[2];
-  /// The rest x component of previous camera movement
-  int HUOFCamMovementX;
-  /// Maximum tracked points detected in one cycle
-  int MaxTrackedPoints;
-  /// Processed frame number with optical flow in the image sequence
-  int HUOFFrames;
-  /// Indicator of a new camera movement
-  bool HUOFCamMovement;
-};
-
-/** @} */
diff --git a/package_bgs/LBP_MRF/block.h b/package_bgs/LBP_MRF/block.h
deleted file mode 100644
index bd1ab67ee703ea826d3debddd5eb4978bcf4e185..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/block.h
+++ /dev/null
@@ -1,297 +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/>.
-*/
-/* block.h */
-/*
-    Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-    */
-/*
-  Template classes Block and DBlock
-  Implement adding and deleting items of the same type in blocks.
-
-  If there there are many items then using Block or DBlock
-  is more efficient than using 'new' and 'delete' both in terms
-  of memory and time since
-  (1) On some systems there is some minimum amount of memory
-  that 'new' can allocate (e.g., 64), so if items are
-  small that a lot of memory is wasted.
-  (2) 'new' and 'delete' are designed for items of varying size.
-  If all items has the same size, then an algorithm for
-  adding and deleting can be made more efficient.
-  (3) All Block and DBlock functions are inline, so there are
-  no extra function calls.
-
-  Differences between Block and DBlock:
-  (1) DBlock allows both adding and deleting items,
-  whereas Block allows only adding items.
-  (2) Block has an additional operation of scanning
-  items added so far (in the order in which they were added).
-  (3) Block allows to allocate several consecutive
-  items at a time, whereas DBlock can add only a single item.
-
-  Note that no constructors or destructors are called for items.
-
-  Example usage for items of type 'MyType':
-
-  ///////////////////////////////////////////////////
-  #include "block.h"
-  #define BLOCK_SIZE 1024
-  typedef struct { int a, b; } MyType;
-  MyType *ptr, *array[10000];
-
-  ...
-
-  Block<MyType> *block = new Block<MyType>(BLOCK_SIZE);
-
-  // adding items
-  for (int i=0; i<sizeof(array); i++)
-  {
-  ptr = block -> New();
-  ptr -> a = ptr -> b = rand();
-  }
-
-  // reading items
-  for (ptr=block->ScanFirst(); ptr; ptr=block->ScanNext())
-  {
-  printf("%d %d\n", ptr->a, ptr->b);
-  }
-
-  delete block;
-
-  ...
-
-  DBlock<MyType> *dblock = new DBlock<MyType>(BLOCK_SIZE);
-
-  // adding items
-  for (int i=0; i<sizeof(array); i++)
-  {
-  array[i] = dblock -> New();
-  }
-
-  // deleting items
-  for (int i=0; i<sizeof(array); i+=2)
-  {
-  dblock -> Delete(array[i]);
-  }
-
-  // adding items
-  for (int i=0; i<sizeof(array); i++)
-  {
-  array[i] = dblock -> New();
-  }
-
-  delete dblock;
-
-  ///////////////////////////////////////////////////
-
-  Note that DBlock deletes items by marking them as
-  empty (i.e., by adding them to the list of free items),
-  so that this memory could be used for subsequently
-  added items. Thus, at each moment the memory allocated
-  is determined by the maximum number of items allocated
-  simultaneously at earlier moments. All memory is
-  deallocated only when the destructor is called.
-  */
-#pragma once
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-namespace ck
-{
-template <class Type> class Block
-{
-public:
-  /* Constructor. Arguments are the block size and
-       (optionally) the pointer to the function which
-       will be called if allocation failed; the message
-       passed to this function is "Not enough memory!" */
-  Block(int size, void(*err_function)(char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; }
-
-  /* Destructor. Deallocates all items added so far */
-  ~Block() { while (first) { block *next = first->next; delete first; first = next; } }
-
-  /* Allocates 'num' consecutive items; returns pointer
-       to the first item. 'num' cannot be greater than the
-       block size since items must fit in one block */
-  Type *New(int num = 1)
-  {
-    Type *t;
-
-    if (!last || last->current + num > last->last)
-    {
-      if (last && last->next) last = last->next;
-      else
-      {
-        block *next = (block *) new char[sizeof(block) + (block_size - 1)*sizeof(Type)];
-        if (!next) { fprintf(stderr, "Not enough memory!"); exit(1); }
-        if (last) last->next = next;
-        else first = next;
-        last = next;
-        last->current = &(last->data[0]);
-        last->last = last->current + block_size;
-        last->next = NULL;
-      }
-    }
-
-    t = last->current;
-    last->current += num;
-    return t;
-  }
-
-  /* Returns the first item (or NULL, if no items were added) */
-  Type *ScanFirst()
-  {
-    scan_current_block = first;
-    if (!scan_current_block) return NULL;
-    scan_current_data = &(scan_current_block->data[0]);
-    return scan_current_data++;
-  }
-
-  /* Returns the next item (or NULL, if all items have been read)
-       Can be called only if previous ScanFirst() or ScanNext()
-       call returned not NULL. */
-  Type *ScanNext()
-  {
-    if (scan_current_data >= scan_current_block->current)
-    {
-      scan_current_block = scan_current_block->next;
-      if (!scan_current_block) return NULL;
-      scan_current_data = &(scan_current_block->data[0]);
-    }
-    return scan_current_data++;
-  }
-
-  /* Marks all elements as empty */
-  void Reset()
-  {
-    block *b;
-    if (!first) return;
-    for (b = first;; b = b->next)
-    {
-      b->current = &(b->data[0]);
-      if (b == last) break;
-    }
-    last = first;
-  }
-
-  /***********************************************************************/
-
-private:
-
-  typedef struct block_st
-  {
-    Type					*current, *last;
-    struct block_st			*next;
-    Type					data[1];
-  } block;
-
-  int		block_size;
-  block	*first;
-  block	*last;
-
-  block	*scan_current_block;
-  Type	*scan_current_data;
-
-  void(*error_function)(char *);
-};
-
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-template <class Type> class DBlock
-{
-public:
-  /* Constructor. Arguments are the block size and
-       (optionally) the pointer to the function which
-       will be called if allocation failed; the message
-       passed to this function is "Not enough memory!" */
-  DBlock(int size, void(*err_function)(char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; }
-
-  /* Destructor. Deallocates all items added so far */
-  ~DBlock() { while (first) { block *next = first->next; delete first; first = next; } }
-
-  /* Allocates one item */
-  Type *New()
-  {
-    block_item *item;
-
-    if (!first_free)
-    {
-      block *next = first;
-      first = (block *) new char[sizeof(block) + (block_size - 1)*sizeof(block_item)];
-      if (!first) { fprintf(stderr, "Not enough memory!"); exit(1); }
-      first_free = &(first->data[0]);
-      for (item = first_free; item < first_free + block_size - 1; item++)
-        item->next_free = item + 1;
-      item->next_free = NULL;
-      first->next = next;
-    }
-
-    item = first_free;
-    first_free = item->next_free;
-    return (Type *)item;
-  }
-
-  /* Deletes an item allocated previously */
-  void Delete(Type *t)
-  {
-    ((block_item *)t)->next_free = first_free;
-    first_free = (block_item *)t;
-  }
-
-  /***********************************************************************/
-
-private:
-
-  typedef union block_item_st
-  {
-    Type			t;
-    block_item_st	*next_free;
-  } block_item;
-
-  typedef struct block_st
-  {
-    struct block_st			*next;
-    block_item				data[1];
-  } block;
-
-  int			block_size;
-  block		*first;
-  block_item	*first_free;
-
-  void(*error_function)(char *);
-};
-}
diff --git a/package_bgs/LBP_MRF/graph.cpp b/package_bgs/LBP_MRF/graph.cpp
deleted file mode 100644
index 9301250f051381b1489a6365027da61548a5e5e9..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/graph.cpp
+++ /dev/null
@@ -1,99 +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/>.
-*/
-/* graph.cpp */
-/*
-    Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-    */
-
-
-#include <stdio.h>
-#include "graph.h"
-
-namespace ck
-{
-  Graph::Graph(void(*err_function)(char *))
-  {
-    error_function = err_function;
-    node_block = new Block<node>(NODE_BLOCK_SIZE, error_function);
-    arc_block = new Block<arc>(NODE_BLOCK_SIZE, error_function);
-    flow = 0;
-  }
-
-  Graph::~Graph()
-  {
-    delete node_block;
-    delete arc_block;
-  }
-
-  Graph::node_id Graph::add_node()
-  {
-    node *i = node_block->New();
-
-    i->first = NULL;
-    i->tr_cap = 0;
-
-    return (node_id)i;
-  }
-
-  void Graph::add_edge(node_id from, node_id to, captype cap, captype rev_cap)
-  {
-    arc *a, *a_rev;
-
-    a = arc_block->New(2);
-    a_rev = a + 1;
-
-    a->sister = a_rev;
-    a_rev->sister = a;
-    a->next = ((node*)from)->first;
-    ((node*)from)->first = a;
-    a_rev->next = ((node*)to)->first;
-    ((node*)to)->first = a_rev;
-    a->head = (node*)to;
-    a_rev->head = (node*)from;
-    a->r_cap = cap;
-    a_rev->r_cap = rev_cap;
-  }
-
-  void Graph::set_tweights(node_id i, captype cap_source, captype cap_sink)
-  {
-    flow += (cap_source < cap_sink) ? cap_source : cap_sink;
-    ((node*)i)->tr_cap = cap_source - cap_sink;
-  }
-
-  void Graph::add_tweights(node_id i, captype cap_source, captype cap_sink)
-  {
-    register captype delta = ((node*)i)->tr_cap;
-    if (delta > 0) cap_source += delta;
-    else           cap_sink -= delta;
-    flow += (cap_source < cap_sink) ? cap_source : cap_sink;
-    ((node*)i)->tr_cap = cap_source - cap_sink;
-  }
-}
diff --git a/package_bgs/LBP_MRF/graph.h b/package_bgs/LBP_MRF/graph.h
deleted file mode 100644
index e7b83c7e2c956cbc97777160086c502a6cf918dc..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/graph.h
+++ /dev/null
@@ -1,192 +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/>.
-*/
-/* graph.h */
-/*
-  This software library implements the maxflow algorithm
-  described in
-
-  An Experimental Comparison of Min-Cut/Max-Flow Algorithms
-  for Energy Minimization in Vision.
-  Yuri Boykov and Vladimir Kolmogorov.
-  In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI),
-  September 2004
-
-  This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov
-  at Siemens Corporate Research. To make it available for public use,
-  it was later reimplemented by Vladimir Kolmogorov based on open publications.
-
-  If you use this software for research purposes, you should cite
-  the aforementioned paper in any resulting publication.
-  */
-  /*
-    Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-    */
-    /*
-      For description, example usage, discussion of graph representation
-      and memory usage see README.TXT.
-      */
-#pragma once
-
-#include "block.h"
-
-      /*
-        Nodes, arcs and pointers to nodes are
-        added in blocks for memory and time efficiency.
-        Below are numbers of items in blocks
-        */
-#define NODE_BLOCK_SIZE 512
-#define ARC_BLOCK_SIZE 1024
-#define NODEPTR_BLOCK_SIZE 128
-
-namespace ck
-{
-  class Graph
-  {
-  public:
-    typedef enum
-    {
-      SOURCE = 0,
-      SINK = 1
-    } termtype; /* terminals */
-
-    /* Type of edge weights.
-         Can be changed to char, int, float, double, ... */
-    typedef short captype;
-    /* Type of total flow */
-    typedef int flowtype;
-
-    typedef void * node_id;
-
-    /* interface functions */
-
-    /* Constructor. Optional argument is the pointer to the
-         function which will be called if an error occurs;
-         an error message is passed to this function. If this
-         argument is omitted, exit(1) will be called. */
-    Graph(void(*err_function)(char *) = NULL);
-
-    /* Destructor */
-    ~Graph();
-
-    /* Adds a node to the graph */
-    node_id add_node();
-
-    /* Adds a bidirectional edge between 'from' and 'to'
-         with the weights 'cap' and 'rev_cap' */
-    void add_edge(node_id from, node_id to, captype cap, captype rev_cap);
-
-    /* Sets the weights of the edges 'SOURCE->i' and 'i->SINK'
-         Can be called at most once for each node before any call to 'add_tweights'.
-         Weights can be negative */
-    void set_tweights(node_id i, captype cap_source, captype cap_sink);
-
-    /* Adds new edges 'SOURCE->i' and 'i->SINK' with corresponding weights
-         Can be called multiple times for each node.
-         Weights can be negative */
-    void add_tweights(node_id i, captype cap_source, captype cap_sink);
-
-    /* After the maxflow is computed, this function returns to which
-         segment the node 'i' belongs (Graph::SOURCE or Graph::SINK) */
-    termtype what_segment(node_id i);
-
-    /* Computes the maxflow. Can be called only once. */
-    flowtype maxflow();
-
-    /***********************************************************************/
-    /***********************************************************************/
-    /***********************************************************************/
-
-  private:
-    /* internal variables and functions */
-
-    struct arc_st;
-
-    /* node structure */
-    typedef struct node_st
-    {
-      arc_st			*first;		/* first outcoming arc */
-
-      arc_st			*parent;	/* node's parent */
-      node_st			*next;		/* pointer to the next active node
-                         (or to itself if it is the last node in the list) */
-      int				TS;			/* timestamp showing when DIST was computed */
-      int				DIST;		/* distance to the terminal */
-      short			is_sink;	/* flag showing whether the node is in the source or in the sink tree */
-
-      captype			tr_cap;		/* if tr_cap > 0 then tr_cap is residual capacity of the arc SOURCE->node
-                         otherwise         -tr_cap is residual capacity of the arc node->SINK */
-    } node;
-
-    /* arc structure */
-    typedef struct arc_st
-    {
-      node_st			*head;		/* node the arc points to */
-      arc_st			*next;		/* next arc with the same originating node */
-      arc_st			*sister;	/* reverse arc */
-
-      captype			r_cap;		/* residual capacity */
-    } arc;
-
-    /* 'pointer to node' structure */
-    typedef struct nodeptr_st
-    {
-      node_st			*ptr;
-      nodeptr_st		*next;
-    } nodeptr;
-
-    Block<node>			*node_block;
-    Block<arc>			*arc_block;
-    DBlock<nodeptr>		*nodeptr_block;
-
-    void(*error_function)(char *);	/* this function is called if a error occurs,
-                           with a corresponding error message
-                           (or exit(1) is called if it's NULL) */
-
-    flowtype			flow;		/* total flow */
-
-    /***********************************************************************/
-
-    node				*queue_first[2], *queue_last[2];	/* list of active nodes */
-    nodeptr				*orphan_first, *orphan_last;		/* list of pointers to orphans */
-    int					TIME;								/* monotonically increasing global counter */
-
-    /***********************************************************************/
-
-    /* functions for processing active list */
-    void set_active(node *i);
-    node *next_active();
-
-    void maxflow_init();
-    void augment(arc *middle_arc);
-    void process_source_orphan(node *i);
-    void process_sink_orphan(node *i);
-  };
-}
diff --git a/package_bgs/LBP_MRF/maxflow.cpp b/package_bgs/LBP_MRF/maxflow.cpp
deleted file mode 100644
index 6ddec507db47d3dbe0e7fdf1c69d63e3277d133f..0000000000000000000000000000000000000000
--- a/package_bgs/LBP_MRF/maxflow.cpp
+++ /dev/null
@@ -1,530 +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/>.
-*/
-/* maxflow.cpp */
-/*
-    Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-    */
-#include <stdio.h>
-#include "graph.h"
-
-    /*
-      special constants for node->parent
-      */
-#define TERMINAL ( (arc *) 1 )		/* to terminal */
-#define ORPHAN   ( (arc *) 2 )		/* orphan */
-
-#define INFINITE_D 1000000000		/* infinite distance to the terminal */
-
-      /***********************************************************************/
-
-      /*
-        Functions for processing active list.
-        i->next points to the next node in the list
-        (or to i, if i is the last node in the list).
-        If i->next is NULL iff i is not in the list.
-
-        There are two queues. Active nodes are added
-        to the end of the second queue and read from
-        the front of the first queue. If the first queue
-        is empty, it is replaced by the second queue
-        (and the second queue becomes empty).
-        */
-namespace ck
-{
-  inline void Graph::set_active(node *i)
-  {
-    if (!i->next)
-    {
-      /* it's not in the list yet */
-      if (queue_last[1]) queue_last[1]->next = i;
-      else               queue_first[1] = i;
-      queue_last[1] = i;
-      i->next = i;
-    }
-  }
-
-  /*
-      Returns the next active node.
-      If it is connected to the sink, it stays in the list,
-      otherwise it is removed from the list
-      */
-  inline Graph::node * Graph::next_active()
-  {
-    node *i;
-
-    while (1)
-    {
-      if (!(i = queue_first[0]))
-      {
-        queue_first[0] = i = queue_first[1];
-        queue_last[0] = queue_last[1];
-        queue_first[1] = NULL;
-        queue_last[1] = NULL;
-        if (!i) return NULL;
-      }
-
-      /* remove it from the active list */
-      if (i->next == i) queue_first[0] = queue_last[0] = NULL;
-      else              queue_first[0] = i->next;
-      i->next = NULL;
-
-      /* a node in the list is active iff it has a parent */
-      if (i->parent) return i;
-    }
-  }
-
-  /***********************************************************************/
-
-  void Graph::maxflow_init()
-  {
-    node *i;
-
-    queue_first[0] = queue_last[0] = NULL;
-    queue_first[1] = queue_last[1] = NULL;
-    orphan_first = NULL;
-
-    for (i = node_block->ScanFirst(); i; i = node_block->ScanNext())
-    {
-      i->next = NULL;
-      i->TS = 0;
-      if (i->tr_cap > 0)
-      {
-        /* i is connected to the source */
-        i->is_sink = 0;
-        i->parent = TERMINAL;
-        set_active(i);
-        i->TS = 0;
-        i->DIST = 1;
-      }
-      else if (i->tr_cap < 0)
-      {
-        /* i is connected to the sink */
-        i->is_sink = 1;
-        i->parent = TERMINAL;
-        set_active(i);
-        i->TS = 0;
-        i->DIST = 1;
-      }
-      else
-      {
-        i->parent = NULL;
-      }
-    }
-    TIME = 0;
-  }
-
-  /***********************************************************************/
-
-  void Graph::augment(arc *middle_arc)
-  {
-    node *i;
-    arc *a;
-    captype bottleneck;
-    nodeptr *np;
-
-
-    /* 1. Finding bottleneck capacity */
-    /* 1a - the source tree */
-    bottleneck = middle_arc->r_cap;
-    for (i = middle_arc->sister->head;; i = a->head)
-    {
-      a = i->parent;
-      if (a == TERMINAL) break;
-      if (bottleneck > a->sister->r_cap) bottleneck = a->sister->r_cap;
-    }
-    if (bottleneck > i->tr_cap) bottleneck = i->tr_cap;
-    /* 1b - the sink tree */
-    for (i = middle_arc->head;; i = a->head)
-    {
-      a = i->parent;
-      if (a == TERMINAL) break;
-      if (bottleneck > a->r_cap) bottleneck = a->r_cap;
-    }
-    if (bottleneck > -i->tr_cap) bottleneck = -i->tr_cap;
-
-
-    /* 2. Augmenting */
-    /* 2a - the source tree */
-    middle_arc->sister->r_cap += bottleneck;
-    middle_arc->r_cap -= bottleneck;
-    for (i = middle_arc->sister->head;; i = a->head)
-    {
-      a = i->parent;
-      if (a == TERMINAL) break;
-      a->r_cap += bottleneck;
-      a->sister->r_cap -= bottleneck;
-      if (!a->sister->r_cap)
-      {
-        /* add i to the adoption list */
-        i->parent = ORPHAN;
-        np = nodeptr_block->New();
-        np->ptr = i;
-        np->next = orphan_first;
-        orphan_first = np;
-      }
-    }
-    i->tr_cap -= bottleneck;
-    if (!i->tr_cap)
-    {
-      /* add i to the adoption list */
-      i->parent = ORPHAN;
-      np = nodeptr_block->New();
-      np->ptr = i;
-      np->next = orphan_first;
-      orphan_first = np;
-    }
-    /* 2b - the sink tree */
-    for (i = middle_arc->head;; i = a->head)
-    {
-      a = i->parent;
-      if (a == TERMINAL) break;
-      a->sister->r_cap += bottleneck;
-      a->r_cap -= bottleneck;
-      if (!a->r_cap)
-      {
-        /* add i to the adoption list */
-        i->parent = ORPHAN;
-        np = nodeptr_block->New();
-        np->ptr = i;
-        np->next = orphan_first;
-        orphan_first = np;
-      }
-    }
-    i->tr_cap += bottleneck;
-    if (!i->tr_cap)
-    {
-      /* add i to the adoption list */
-      i->parent = ORPHAN;
-      np = nodeptr_block->New();
-      np->ptr = i;
-      np->next = orphan_first;
-      orphan_first = np;
-    }
-
-
-    flow += bottleneck;
-  }
-
-  /***********************************************************************/
-
-  void Graph::process_source_orphan(node *i)
-  {
-    node *j;
-    arc *a0, *a0_min = NULL, *a;
-    nodeptr *np;
-    int d, d_min = INFINITE_D;
-
-    /* trying to find a new parent */
-    for (a0 = i->first; a0; a0 = a0->next)
-      if (a0->sister->r_cap)
-      {
-        j = a0->head;
-        if (!j->is_sink && (a = j->parent))
-        {
-          /* checking the origin of j */
-          d = 0;
-          while (1)
-          {
-            if (j->TS == TIME)
-            {
-              d += j->DIST;
-              break;
-            }
-            a = j->parent;
-            d++;
-            if (a == TERMINAL)
-            {
-              j->TS = TIME;
-              j->DIST = 1;
-              break;
-            }
-            if (a == ORPHAN) { d = INFINITE_D; break; }
-            j = a->head;
-          }
-          if (d < INFINITE_D) /* j originates from the source - done */
-          {
-            if (d < d_min)
-            {
-              a0_min = a0;
-              d_min = d;
-            }
-            /* set marks along the path */
-            for (j = a0->head; j->TS != TIME; j = j->parent->head)
-            {
-              j->TS = TIME;
-              j->DIST = d--;
-            }
-          }
-        }
-      }
-
-    if ((i->parent = a0_min))
-    {
-      i->TS = TIME;
-      i->DIST = d_min + 1;
-    }
-    else
-    {
-      /* no parent is found */
-      i->TS = 0;
-
-      /* process neighbors */
-      for (a0 = i->first; a0; a0 = a0->next)
-      {
-        j = a0->head;
-        if (!j->is_sink && (a = j->parent))
-        {
-          if (a0->sister->r_cap) set_active(j);
-          if (a != TERMINAL && a != ORPHAN && a->head == i)
-          {
-            /* add j to the adoption list */
-            j->parent = ORPHAN;
-            np = nodeptr_block->New();
-            np->ptr = j;
-            if (orphan_last) orphan_last->next = np;
-            else             orphan_first = np;
-            orphan_last = np;
-            np->next = NULL;
-          }
-        }
-      }
-    }
-  }
-
-  void Graph::process_sink_orphan(node *i)
-  {
-    node *j;
-    arc *a0, *a0_min = NULL, *a;
-    nodeptr *np;
-    int d, d_min = INFINITE_D;
-
-    /* trying to find a new parent */
-    for (a0 = i->first; a0; a0 = a0->next)
-      if (a0->r_cap)
-      {
-        j = a0->head;
-        if (j->is_sink && (a = j->parent))
-        {
-          /* checking the origin of j */
-          d = 0;
-          while (1)
-          {
-            if (j->TS == TIME)
-            {
-              d += j->DIST;
-              break;
-            }
-            a = j->parent;
-            d++;
-            if (a == TERMINAL)
-            {
-              j->TS = TIME;
-              j->DIST = 1;
-              break;
-            }
-            if (a == ORPHAN) { d = INFINITE_D; break; }
-            j = a->head;
-          }
-          if (d < INFINITE_D) /* j originates from the sink - done */
-          {
-            if (d < d_min)
-            {
-              a0_min = a0;
-              d_min = d;
-            }
-            /* set marks along the path */
-            for (j = a0->head; j->TS != TIME; j = j->parent->head)
-            {
-              j->TS = TIME;
-              j->DIST = d--;
-            }
-          }
-        }
-      }
-
-    if ((i->parent = a0_min))
-    {
-      i->TS = TIME;
-      i->DIST = d_min + 1;
-    }
-    else
-    {
-      /* no parent is found */
-      i->TS = 0;
-
-      /* process neighbors */
-      for (a0 = i->first; a0; a0 = a0->next)
-      {
-        j = a0->head;
-        if (j->is_sink && (a = j->parent))
-        {
-          if (a0->r_cap) set_active(j);
-          if (a != TERMINAL && a != ORPHAN && a->head == i)
-          {
-            /* add j to the adoption list */
-            j->parent = ORPHAN;
-            np = nodeptr_block->New();
-            np->ptr = j;
-            if (orphan_last) orphan_last->next = np;
-            else             orphan_first = np;
-            orphan_last = np;
-            np->next = NULL;
-          }
-        }
-      }
-    }
-  }
-
-  /***********************************************************************/
-
-  Graph::flowtype Graph::maxflow()
-  {
-    node *i, *j, *current_node = NULL;
-    arc *a;
-    nodeptr *np, *np_next;
-
-    maxflow_init();
-    nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);
-
-    while (1)
-    {
-      if ((i = current_node))
-      {
-        i->next = NULL; /* remove active flag */
-        if (!i->parent) i = NULL;
-      }
-      if (!i)
-      {
-        if (!(i = next_active())) break;
-      }
-
-      /* growth */
-      if (!i->is_sink)
-      {
-        /* grow source tree */
-        for (a = i->first; a; a = a->next)
-          if (a->r_cap)
-          {
-            j = a->head;
-            if (!j->parent)
-            {
-              j->is_sink = 0;
-              j->parent = a->sister;
-              j->TS = i->TS;
-              j->DIST = i->DIST + 1;
-              set_active(j);
-            }
-            else if (j->is_sink) break;
-            else if (j->TS <= i->TS &&
-              j->DIST > i->DIST)
-            {
-              /* heuristic - trying to make the distance from j to the source shorter */
-              j->parent = a->sister;
-              j->TS = i->TS;
-              j->DIST = i->DIST + 1;
-            }
-          }
-      }
-      else
-      {
-        /* grow sink tree */
-        for (a = i->first; a; a = a->next)
-          if (a->sister->r_cap)
-          {
-            j = a->head;
-            if (!j->parent)
-            {
-              j->is_sink = 1;
-              j->parent = a->sister;
-              j->TS = i->TS;
-              j->DIST = i->DIST + 1;
-              set_active(j);
-            }
-            else if (!j->is_sink) { a = a->sister; break; }
-            else if (j->TS <= i->TS &&
-              j->DIST > i->DIST)
-            {
-              /* heuristic - trying to make the distance from j to the sink shorter */
-              j->parent = a->sister;
-              j->TS = i->TS;
-              j->DIST = i->DIST + 1;
-            }
-          }
-      }
-
-      TIME++;
-
-      if (a)
-      {
-        i->next = i; /* set active flag */
-        current_node = i;
-
-        /* augmentation */
-        augment(a);
-        /* augmentation end */
-
-        /* adoption */
-        while ((np = orphan_first))
-        {
-          np_next = np->next;
-          np->next = NULL;
-
-          while ((np = orphan_first))
-          {
-            orphan_first = np->next;
-            i = np->ptr;
-            nodeptr_block->Delete(np);
-            if (!orphan_first) orphan_last = NULL;
-            if (i->is_sink) process_sink_orphan(i);
-            else            process_source_orphan(i);
-          }
-
-          orphan_first = np_next;
-        }
-        /* adoption end */
-      }
-      else current_node = NULL;
-    }
-
-    delete nodeptr_block;
-
-    return flow;
-  }
-
-  /***********************************************************************/
-
-  Graph::termtype Graph::what_segment(node_id i)
-  {
-    if (((node*)i)->parent && !((node*)i)->is_sink) return SOURCE;
-    return SINK;
-  }
-
-}
diff --git a/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp b/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp
deleted file mode 100644
index 2865a30709751b16a06e8a4be0d6354d93dd0eb0..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp
+++ /dev/null
@@ -1,85 +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 "BackgroundSubtractorLBSP.h"
-#include "DistanceUtils.h"
-#include "RandUtils.h"
-#include <iostream>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <iomanip>
-#include <exception>
-
-#ifndef SIZE_MAX
-# if __WORDSIZE == 64
-#  define SIZE_MAX		(18446744073709551615UL)
-# else
-#  define SIZE_MAX		(4294967295U)
-# endif
-#endif
-
-// local define used to determine the default median blur kernel size
-#define DEFAULT_MEDIAN_BLUR_KERNEL_SIZE (9)
-
-BackgroundSubtractorLBSP::BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nLBSPThresholdOffset)
-  : m_nImgChannels(0)
-  , m_nImgType(0)
-  , m_nLBSPThresholdOffset(nLBSPThresholdOffset)
-  , m_fRelLBSPThreshold(fRelLBSPThreshold)
-  , m_nTotPxCount(0)
-  , m_nTotRelevantPxCount(0)
-  , m_nFrameIndex(SIZE_MAX)
-  , m_nFramesSinceLastReset(0)
-  , m_nModelResetCooldown(0)
-  , m_aPxIdxLUT(nullptr)
-  , m_aPxInfoLUT(nullptr)
-  , m_nDefaultMedianBlurKernelSize(DEFAULT_MEDIAN_BLUR_KERNEL_SIZE)
-  , m_bInitialized(false)
-  , m_bAutoModelResetEnabled(true)
-  , m_bUsingMovingCamera(false)
-  , nDebugCoordX(0), nDebugCoordY(0) {
-  CV_Assert(m_fRelLBSPThreshold >= 0);
-}
-
-BackgroundSubtractorLBSP::~BackgroundSubtractorLBSP() {}
-
-void BackgroundSubtractorLBSP::initialize(const cv::Mat& oInitImg) {
-  this->initialize(oInitImg, cv::Mat());
-}
-
-/*cv::AlgorithmInfo* BackgroundSubtractorLBSP::info() const {
-  return nullptr;
-}*/
-
-cv::Mat BackgroundSubtractorLBSP::getROICopy() const {
-  return m_oROI.clone();
-}
-
-void BackgroundSubtractorLBSP::setROI(cv::Mat& oROI) {
-  LBSP::validateROI(oROI);
-  CV_Assert(cv::countNonZero(oROI) > 0);
-  if (m_bInitialized) {
-    cv::Mat oLatestBackgroundImage;
-    getBackgroundImage(oLatestBackgroundImage);
-    initialize(oLatestBackgroundImage, oROI);
-  }
-  else
-    m_oROI = oROI.clone();
-}
-
-void BackgroundSubtractorLBSP::setAutomaticModelReset(bool bVal) {
-  m_bAutoModelResetEnabled = bVal;
-}
diff --git a/package_bgs/LBSP/BackgroundSubtractorLBSP.h b/package_bgs/LBSP/BackgroundSubtractorLBSP.h
deleted file mode 100644
index ef0576c9149a4be20ea8cfb2b24f9fd48c65e4ba..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorLBSP.h
+++ /dev/null
@@ -1,101 +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
-
-#include <opencv2/features2d/features2d.hpp>
-#include <opencv2/video/background_segm.hpp>
-#include "LBSP.h"
-
-/*!
-  Local Binary Similarity Pattern (LBSP)-based change detection algorithm (abstract version/base class).
-
-  For more details on the different parameters, see P.-L. St-Charles and G.-A. Bilodeau, "Improving Background
-  Subtraction using Local Binary Similarity Patterns", in WACV 2014, or G.-A. Bilodeau et al, "Change Detection
-  in Feature Space Using Local Binary Similarity Patterns", in CRV 2013.
-
-  This algorithm is currently NOT thread-safe.
- */
-class BackgroundSubtractorLBSP : public cv::BackgroundSubtractor {
-public:
-  //! full constructor
-  BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nLBSPThresholdOffset = 0);
-  //! default destructor
-  virtual ~BackgroundSubtractorLBSP();
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg);
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) = 0;
-  //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
-  virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = 0) = 0;
-  //! unused, always returns nullptr
-  //virtual cv::AlgorithmInfo* info() const;
-  //! returns a copy of the ROI used for descriptor extraction
-  virtual cv::Mat getROICopy() const;
-  //! sets the ROI to be used for descriptor extraction (note: this function will reinit the model and return the usable ROI)
-  virtual void setROI(cv::Mat& oROI);
-  //! turns automatic model reset on or off
-  void setAutomaticModelReset(bool);
-
-protected:
-  struct PxInfoBase {
-    int nImgCoord_Y;
-    int nImgCoord_X;
-    size_t nModelIdx;
-  };
-  //! background model ROI used for LBSP descriptor extraction (specific to the input image size)
-  cv::Mat m_oROI;
-  //! input image size
-  cv::Size m_oImgSize;
-  //! input image channel size
-  size_t m_nImgChannels;
-  //! input image type
-  int m_nImgType;
-  //! LBSP internal threshold offset value, used to reduce texture noise in dark regions
-  const size_t m_nLBSPThresholdOffset;
-  //! LBSP relative internal threshold (kept here since we don't keep an LBSP object)
-  const float m_fRelLBSPThreshold;
-  //! total number of pixels (depends on the input frame size) & total number of relevant pixels
-  size_t m_nTotPxCount, m_nTotRelevantPxCount;
-  //! current frame index, frame count since last model reset & model reset cooldown counters
-  size_t m_nFrameIndex, m_nFramesSinceLastReset, m_nModelResetCooldown;
-  //! pre-allocated internal LBSP threshold values LUT for all possible 8-bit intensities
-  size_t m_anLBSPThreshold_8bitLUT[UCHAR_MAX + 1];
-  //! internal pixel index LUT for all relevant analysis regions (based on the provided ROI)
-  size_t* m_aPxIdxLUT;
-  //! internal pixel info LUT for all possible pixel indexes
-  PxInfoBase* m_aPxInfoLUT;
-  //! default kernel size for median blur post-proc filtering
-  const int m_nDefaultMedianBlurKernelSize;
-  //! specifies whether the algorithm is fully initialized or not
-  bool m_bInitialized;
-  //! specifies whether automatic model resets are enabled or not
-  bool m_bAutoModelResetEnabled;
-  //! specifies whether the camera is considered moving or not
-  bool m_bUsingMovingCamera;
-  //! copy of latest pixel intensities (used when refreshing model)
-  cv::Mat m_oLastColorFrame;
-  //! copy of latest descriptors (used when refreshing model)
-  cv::Mat m_oLastDescFrame;
-  //! the foreground mask generated by the method at [t-1]
-  cv::Mat m_oLastFGMask;
-
-public:
-  // ######## DEBUG PURPOSES ONLY ##########
-  int nDebugCoordX, nDebugCoordY;
-  std::string sDebugName;
-};
-
diff --git a/package_bgs/LBSP/BackgroundSubtractorLBSP_.cpp b/package_bgs/LBSP/BackgroundSubtractorLBSP_.cpp
deleted file mode 100644
index 4e5d4a6fad9bcc75476b3d598e05d44fca07cdd0..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorLBSP_.cpp
+++ /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/>.
-*/
-#include "BackgroundSubtractorLBSP_.h"
-#include "DistanceUtils.h"
-#include "RandUtils.h"
-#include <iostream>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <iomanip>
-#include <exception>
-
-// local define used to determine the default median blur kernel size
-#define DEFAULT_MEDIAN_BLUR_KERNEL_SIZE (9)
-
-BackgroundSubtractorLBSP_::BackgroundSubtractorLBSP_(float fRelLBSPThreshold, size_t nLBSPThresholdOffset)
-  : m_nImgChannels(0)
-  , m_nImgType(0)
-  , m_nLBSPThresholdOffset(nLBSPThresholdOffset)
-  , m_fRelLBSPThreshold(fRelLBSPThreshold)
-  , m_nTotPxCount(0)
-  , m_nTotRelevantPxCount(0)
-  , m_nFrameIndex(SIZE_MAX)
-  , m_nFramesSinceLastReset(0)
-  , m_nModelResetCooldown(0)
-  , m_aPxIdxLUT(nullptr)
-  , m_aPxInfoLUT(nullptr)
-  , m_nDefaultMedianBlurKernelSize(DEFAULT_MEDIAN_BLUR_KERNEL_SIZE)
-  , m_bInitialized(false)
-  , m_bAutoModelResetEnabled(true)
-  , m_bUsingMovingCamera(false)
-  , m_nDebugCoordX(0)
-  , m_nDebugCoordY(0)
-  , m_pDebugFS(nullptr) {
-  CV_Assert(m_fRelLBSPThreshold >= 0);
-}
-
-BackgroundSubtractorLBSP_::~BackgroundSubtractorLBSP_() {}
-
-void BackgroundSubtractorLBSP_::initialize(const cv::Mat& oInitImg) {
-  this->initialize(oInitImg, cv::Mat());
-}
-/*
-cv::AlgorithmInfo* BackgroundSubtractorLBSP_::info() const {
-    return nullptr;
-}
-*/
-cv::Mat BackgroundSubtractorLBSP_::getROICopy() const {
-  return m_oROI.clone();
-}
-
-void BackgroundSubtractorLBSP_::setROI(cv::Mat& oROI) {
-  LBSP_::validateROI(oROI);
-  CV_Assert(cv::countNonZero(oROI) > 0);
-  if (m_bInitialized) {
-    cv::Mat oLatestBackgroundImage;
-    getBackgroundImage(oLatestBackgroundImage);
-    initialize(oLatestBackgroundImage, oROI);
-  }
-  else
-    m_oROI = oROI.clone();
-}
-
-void BackgroundSubtractorLBSP_::setAutomaticModelReset(bool bVal) {
-  m_bAutoModelResetEnabled = bVal;
-}
diff --git a/package_bgs/LBSP/BackgroundSubtractorLBSP_.h b/package_bgs/LBSP/BackgroundSubtractorLBSP_.h
deleted file mode 100644
index 861f78a7bd15a9e84a23e4f69f3fc1d9b88c6692..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorLBSP_.h
+++ /dev/null
@@ -1,107 +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
-
-#include <opencv2/features2d/features2d.hpp>
-#include <opencv2/video/background_segm.hpp>
-#include "LBSP_.h"
-
-/*!
-    Local Binary Similarity Pattern (LBSP)-based change detection algorithm (abstract version/base class).
-
-    For more details on the different parameters, see P.-L. St-Charles and G.-A. Bilodeau, "Improving Background
-    Subtraction using Local Binary Similarity Patterns", in WACV 2014, or G.-A. Bilodeau et al, "Change Detection
-    in Feature Space Using Local Binary Similarity Patterns", in CRV 2013.
-
-    This algorithm is currently NOT thread-safe.
- */
-class BackgroundSubtractorLBSP_ : public cv::BackgroundSubtractor {
-public:
-  //! full constructor
-  BackgroundSubtractorLBSP_(float fRelLBSPThreshold, size_t nLBSPThresholdOffset = 0);
-  //! default destructor
-  virtual ~BackgroundSubtractorLBSP_();
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg);
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) = 0;
-  //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
-  virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = 0) = 0;
-  //! unused, always returns nullptr
-  //virtual cv::AlgorithmInfo* info() const;
-  //! returns a copy of the ROI used for descriptor extraction
-  virtual cv::Mat getROICopy() const;
-  //! sets the ROI to be used for descriptor extraction (note: this function will reinit the model and return the usable ROI)
-  virtual void setROI(cv::Mat& oROI);
-  //! turns automatic model reset on or off
-  void setAutomaticModelReset(bool);
-
-protected:
-  struct PxInfoBase {
-    int nImgCoord_Y;
-    int nImgCoord_X;
-    size_t nModelIdx;
-  };
-  //! background model ROI used for LBSP descriptor extraction (specific to the input image size)
-  cv::Mat m_oROI;
-  //! input image size
-  cv::Size m_oImgSize;
-  //! input image channel size
-  size_t m_nImgChannels;
-  //! input image type
-  int m_nImgType;
-  //! LBSP internal threshold offset value, used to reduce texture noise in dark regions
-  const size_t m_nLBSPThresholdOffset;
-  //! LBSP relative internal threshold (kept here since we don't keep an LBSP object)
-  const float m_fRelLBSPThreshold;
-  //! total number of pixels (depends on the input frame size) & total number of relevant pixels
-  size_t m_nTotPxCount, m_nTotRelevantPxCount;
-  //! current frame index, frame count since last model reset & model reset cooldown counters
-  size_t m_nFrameIndex, m_nFramesSinceLastReset, m_nModelResetCooldown;
-  //! pre-allocated internal LBSP threshold values LUT for all possible 8-bit intensities
-  size_t m_anLBSPThreshold_8bitLUT[UCHAR_MAX + 1];
-  //! internal pixel index LUT for all relevant analysis regions (based on the provided ROI)
-  size_t* m_aPxIdxLUT;
-  //! internal pixel info LUT for all possible pixel indexes
-  PxInfoBase* m_aPxInfoLUT;
-  //! default kernel size for median blur post-proc filtering
-  const int m_nDefaultMedianBlurKernelSize;
-  //! specifies whether the algorithm is fully initialized or not
-  bool m_bInitialized;
-  //! specifies whether automatic model resets are enabled or not
-  bool m_bAutoModelResetEnabled;
-  //! specifies whether the camera is considered moving or not
-  bool m_bUsingMovingCamera;
-  //! copy of latest pixel intensities (used when refreshing model)
-  cv::Mat m_oLastColorFrame;
-  //! copy of latest descriptors (used when refreshing model)
-  cv::Mat m_oLastDescFrame;
-  //! the foreground mask generated by the method at [t-1]
-  cv::Mat m_oLastFGMask;
-
-private:
-  //! copy constructor -- disabled since this class (and its children) use lots of dynamic structs based on raw pointers
-  BackgroundSubtractorLBSP_(const BackgroundSubtractorLBSP_&);
-  //! assignment operator -- disabled since this class (and its children) use lots of dynamic structs based on raw pointers
-  BackgroundSubtractorLBSP_& operator=(const BackgroundSubtractorLBSP_&);
-
-public:
-  // ######## DEBUG PURPOSES ONLY ##########
-  int m_nDebugCoordX, m_nDebugCoordY;
-  std::string m_sDebugName;
-  cv::FileStorage* m_pDebugFS;
-};
diff --git a/package_bgs/LBSP/BackgroundSubtractorLOBSTER.h b/package_bgs/LBSP/BackgroundSubtractorLOBSTER.h
deleted file mode 100644
index d69fd1c3e8d1ff6d9f7a3f7ea807b92dcc94f7e4..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorLOBSTER.h
+++ /dev/null
@@ -1,83 +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
-
-#include "BackgroundSubtractorLBSP.h"
-
-//! defines the default value for BackgroundSubtractorLBSP::m_fRelLBSPThreshold
-#define BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD (0.365f)
-//! defines the default value for BackgroundSubtractorLBSP::m_nLBSPThresholdOffset
-#define BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD (0)
-//! defines the default value for BackgroundSubtractorLOBSTER::m_nDescDistThreshold
-#define BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD (4)
-//! defines the default value for BackgroundSubtractorLOBSTER::m_nColorDistThreshold
-#define BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD (30)
-//! defines the default value for BackgroundSubtractorLOBSTER::m_nBGSamples
-#define BGSLOBSTER_DEFAULT_NB_BG_SAMPLES (35)
-//! defines the default value for BackgroundSubtractorLOBSTER::m_nRequiredBGSamples
-#define BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES (2)
-//! defines the default value for the learning rate passed to BackgroundSubtractorLOBSTER::operator()
-#define BGSLOBSTER_DEFAULT_LEARNING_RATE (16)
-
-/*!
-  LOcal Binary Similarity segmenTER (LOBSTER) change detection algorithm.
-
-  Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
-  For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
-
-  For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles and
-  G.-A. Bilodeau, "Improving Background Subtraction using Local Binary Similarity Patterns", in WACV 2014.
-
-  This algorithm is currently NOT thread-safe.
- */
-class BackgroundSubtractorLOBSTER : public BackgroundSubtractorLBSP {
-public:
-  //! full constructor
-  BackgroundSubtractorLOBSTER(float fRelLBSPThreshold = BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
-    size_t nLBSPThresholdOffset = BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD,
-    size_t nDescDistThreshold = BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD,
-    size_t nColorDistThreshold = BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD,
-    size_t nBGSamples = BGSLOBSTER_DEFAULT_NB_BG_SAMPLES,
-    size_t nRequiredBGSamples = BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES);
-  //! default destructor
-  virtual ~BackgroundSubtractorLOBSTER();
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
-  //! refreshes all samples based on the last analyzed frame
-  virtual void refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate = false);
-  //! primary model update function; the learning param is reinterpreted as an integer and should be > 0 (smaller values == faster adaptation)
-  virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = BGSLOBSTER_DEFAULT_LEARNING_RATE);
-  //! returns a copy of the latest reconstructed background image
-  void getBackgroundImage(cv::OutputArray backgroundImage) const;
-  //! returns a copy of the latest reconstructed background descriptors image
-  virtual void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
-
-protected:
-  //! absolute color distance threshold
-  const size_t m_nColorDistThreshold;
-  //! absolute descriptor distance threshold
-  const size_t m_nDescDistThreshold;
-  //! number of different samples per pixel/block to be taken from input frames to build the background model
-  const size_t m_nBGSamples;
-  //! number of similar samples needed to consider the current pixel/block as 'background'
-  const size_t m_nRequiredBGSamples;
-  //! background model pixel intensity samples
-  std::vector<cv::Mat> m_voBGColorSamples;
-  //! background model descriptors samples
-  std::vector<cv::Mat> m_voBGDescSamples;
-};
-
diff --git a/package_bgs/LBSP/BackgroundSubtractorPAWCS.cpp b/package_bgs/LBSP/BackgroundSubtractorPAWCS.cpp
deleted file mode 100644
index 6c48df3b91115c25be8aff64e6d30c9f21865208..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorPAWCS.cpp
+++ /dev/null
@@ -1,1349 +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 "BackgroundSubtractorPAWCS.h"
-#include "DistanceUtils.h"
-#include "RandUtils.h"
-#include <iostream>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <iomanip>
-
-/*
- *
- * Intrinsic configuration parameters are defined here; tuning these for better
- * performance should not be required in most cases -- although improvements in
- * very specific scenarios are always possible.
- *
- */
- //! parameter used for dynamic distance threshold adjustments ('R(x)')
-#define FEEDBACK_R_VAR (0.01f)
-//! parameters used to adjust the variation step size of 'v(x)'
-#define FEEDBACK_V_INCR  (1.000f)
-#define FEEDBACK_V_DECR  (0.100f)
-//! parameters used to scale dynamic learning rate adjustments  ('T(x)')
-#define FEEDBACK_T_DECR  (0.2500f)
-#define FEEDBACK_T_INCR  (0.5000f)
-#define FEEDBACK_T_LOWER (1.0000f)
-#define FEEDBACK_T_UPPER (256.00f)
-//! parameters used to define 'unstable' regions, based on segm noise/bg dynamics and local dist threshold values
-#define UNSTABLE_REG_RATIO_MIN (0.100f)
-#define UNSTABLE_REG_RDIST_MIN (3.000f)
-//! parameters used to scale the relative LBSP intensity threshold used for internal comparisons
-#define LBSPDESC_RATIO_MIN (0.100f)
-#define LBSPDESC_RATIO_MAX (0.500f)
-//! parameters used to trigger auto model resets in our frame-level component
-#define FRAMELEVEL_MIN_L1DIST_THRES (45)
-#define FRAMELEVEL_MIN_CDIST_THRES (FRAMELEVEL_MIN_L1DIST_THRES/10)
-#define FRAMELEVEL_DOWNSAMPLE_RATIO (8)
-//! parameters used to downscale gword maps & scale thresholds to make comparisons easier
-#define GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO (2)
-#define GWORD_DEFAULT_NB_INIT_SAMPL_PASSES (2)
-#define GWORD_DESC_THRES_BITS_MATCH_FACTOR (4)
-
-// local define used to specify the default frame size (320x240 = QVGA)
-#define DEFAULT_FRAME_SIZE cv::Size(320,240)
-// local define used to specify the default lword/gword update rate (16 = like vibe)
-#define DEFAULT_RESAMPLING_RATE (16)
-// local define used to specify the bootstrap window size for faster model stabilization
-#define DEFAULT_BOOTSTRAP_WIN_SIZE (500)
-// local define for the amount of weight offset to apply to words, making sure new words aren't always better than old ones
-#define DEFAULT_LWORD_WEIGHT_OFFSET (DEFAULT_BOOTSTRAP_WIN_SIZE*2)
-// local define used to set the default local word occurrence increment
-#define DEFAULT_LWORD_OCC_INCR 1
-// local define for the maximum weight a word can achieve before cutting off occ incr (used to make sure model stays good for long-term uses)
-#define DEFAULT_LWORD_MAX_WEIGHT (1.0f)
-// local define for the initial weight of a new word (used to make sure old words aren't worse off than new seeds)
-#define DEFAULT_LWORD_INIT_WEIGHT (1.0f/m_nLocalWordWeightOffset)
-// local define used to specify the desc dist threshold offset used for unstable regions
-#define UNSTAB_DESC_DIST_OFFSET (m_nDescDistThresholdOffset)
-// local define used to specify the min descriptor bit count for flat regions
-#define FLAT_REGION_BIT_COUNT (s_nDescMaxDataRange_1ch/8)
-
-static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX;
-static const size_t s_nDescMaxDataRange_1ch = LBSP_::DESC_SIZE * 8;
-static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch * 3;
-static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch * 3;
-
-BackgroundSubtractorPAWCS::BackgroundSubtractorPAWCS(float fRelLBSPThreshold
-  , size_t nDescDistThresholdOffset
-  , size_t nMinColorDistThreshold
-  , size_t nMaxNbWords
-  , size_t nSamplesForMovingAvgs)
-  : BackgroundSubtractorLBSP_(fRelLBSPThreshold)
-  , m_nMinColorDistThreshold(nMinColorDistThreshold)
-  , m_nDescDistThresholdOffset(nDescDistThresholdOffset)
-  , m_nMaxLocalWords(nMaxNbWords)
-  , m_nCurrLocalWords(0)
-  , m_nMaxGlobalWords(nMaxNbWords / 2)
-  , m_nCurrGlobalWords(0)
-  , m_nSamplesForMovingAvgs(nSamplesForMovingAvgs)
-  , m_fLastNonFlatRegionRatio(0.0f)
-  , m_nMedianBlurKernelSize(m_nDefaultMedianBlurKernelSize)
-  , m_nDownSampledROIPxCount(0)
-  , m_nLocalWordWeightOffset(DEFAULT_LWORD_WEIGHT_OFFSET)
-  , m_apLocalWordDict(nullptr)
-  , m_aLocalWordList_1ch(nullptr)
-  , m_pLocalWordListIter_1ch(nullptr)
-  , m_aLocalWordList_3ch(nullptr)
-  , m_pLocalWordListIter_3ch(nullptr)
-  , m_apGlobalWordDict(nullptr)
-  , m_aGlobalWordList_1ch(nullptr)
-  , m_pGlobalWordListIter_1ch(nullptr)
-  , m_aGlobalWordList_3ch(nullptr)
-  , m_pGlobalWordListIter_3ch(nullptr)
-  , m_aPxInfoLUT_PAWCS(nullptr) {
-  CV_Assert(m_nMaxLocalWords > 0 && m_nMaxGlobalWords > 0);
-}
-
-BackgroundSubtractorPAWCS::~BackgroundSubtractorPAWCS() {
-  CleanupDictionaries();
-}
-
-void BackgroundSubtractorPAWCS::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) {
-  // == init
-  CV_Assert(!oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0);
-  CV_Assert(oInitImg.isContinuous());
-  CV_Assert(oInitImg.type() == CV_8UC3 || oInitImg.type() == CV_8UC1);
-  if (oInitImg.type() == CV_8UC3) {
-    std::vector<cv::Mat> voInitImgChannels;
-    cv::split(oInitImg, voInitImgChannels);
-    if (!cv::countNonZero((voInitImgChannels[0] != voInitImgChannels[1]) | (voInitImgChannels[2] != voInitImgChannels[1])))
-      std::cout << std::endl << "\tBackgroundSubtractorPAWCS : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance." << std::endl;
-  }
-  cv::Mat oNewBGROI;
-  if (oROI.empty() && (m_oROI.empty() || oROI.size() != oInitImg.size())) {
-    oNewBGROI.create(oInitImg.size(), CV_8UC1);
-    oNewBGROI = cv::Scalar_<uchar>(UCHAR_MAX);
-  }
-  else if (oROI.empty())
-    oNewBGROI = m_oROI;
-  else {
-    CV_Assert(oROI.size() == oInitImg.size() && oROI.type() == CV_8UC1);
-    CV_Assert(cv::countNonZero((oROI < UCHAR_MAX)&(oROI > 0)) == 0);
-    oNewBGROI = oROI.clone();
-    cv::Mat oTempROI;
-    cv::dilate(oNewBGROI, oTempROI, cv::Mat(), cv::Point(-1, -1), LBSP_::PATCH_SIZE / 2);
-    cv::bitwise_or(oNewBGROI, oTempROI / 2, oNewBGROI);
-  }
-  const size_t nOrigROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
-  CV_Assert(nOrigROIPxCount > 0);
-  LBSP_::validateROI(oNewBGROI);
-  const size_t nFinalROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
-  CV_Assert(nFinalROIPxCount > 0);
-  CleanupDictionaries();
-  m_oROI = oNewBGROI;
-  m_oImgSize = oInitImg.size();
-  m_nImgType = oInitImg.type();
-  m_nImgChannels = oInitImg.channels();
-  m_nTotPxCount = m_oImgSize.area();
-  m_nTotRelevantPxCount = nFinalROIPxCount;
-  m_nFrameIndex = 0;
-  m_nFramesSinceLastReset = 0;
-  m_nModelResetCooldown = 0;
-  m_bUsingMovingCamera = false;
-  m_oDownSampledFrameSize_MotionAnalysis = cv::Size(m_oImgSize.width / FRAMELEVEL_DOWNSAMPLE_RATIO, m_oImgSize.height / FRAMELEVEL_DOWNSAMPLE_RATIO);
-  m_oDownSampledFrameSize_GlobalWordLookup = cv::Size(m_oImgSize.width / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO, m_oImgSize.height / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO);
-  cv::resize(m_oROI, m_oDownSampledROI_MotionAnalysis, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
-  m_fLastNonFlatRegionRatio = 0.0f;
-  m_nCurrLocalWords = m_nMaxLocalWords;
-  if (nOrigROIPxCount >= m_nTotPxCount / 2 && (int)m_nTotPxCount >= DEFAULT_FRAME_SIZE.area()) {
-    const float fRegionSizeScaleFactor = (float)m_nTotPxCount / DEFAULT_FRAME_SIZE.area();
-    const int nRawMedianBlurKernelSize = std::min((int)floor(0.5f + fRegionSizeScaleFactor) + m_nDefaultMedianBlurKernelSize, m_nDefaultMedianBlurKernelSize + 4);
-    m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
-    m_nCurrGlobalWords = m_nMaxGlobalWords;
-    m_oDownSampledROI_MotionAnalysis |= UCHAR_MAX / 2;
-  }
-  else {
-    const float fRegionSizeScaleFactor = (float)nOrigROIPxCount / DEFAULT_FRAME_SIZE.area();
-    const int nRawMedianBlurKernelSize = std::min((int)floor(0.5f + m_nDefaultMedianBlurKernelSize*fRegionSizeScaleFactor * 2) + (m_nDefaultMedianBlurKernelSize - 4), m_nDefaultMedianBlurKernelSize);
-    m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
-    m_nCurrGlobalWords = std::min((size_t)std::pow(m_nMaxGlobalWords*fRegionSizeScaleFactor, 2) + 1, m_nMaxGlobalWords);
-  }
-  if (m_nImgChannels == 1) {
-    m_nCurrLocalWords = std::max(m_nCurrLocalWords / 2, (size_t)1);
-    m_nCurrGlobalWords = std::max(m_nCurrGlobalWords / 2, (size_t)1);
-  }
-  m_nDownSampledROIPxCount = (size_t)cv::countNonZero(m_oDownSampledROI_MotionAnalysis);
-  m_nLocalWordWeightOffset = DEFAULT_LWORD_WEIGHT_OFFSET;
-  m_oIllumUpdtRegionMask.create(m_oImgSize, CV_8UC1);
-  m_oIllumUpdtRegionMask = cv::Scalar_<uchar>(0);
-  m_oUpdateRateFrame.create(m_oImgSize, CV_32FC1);
-  m_oUpdateRateFrame = cv::Scalar(FEEDBACK_T_LOWER);
-  m_oDistThresholdFrame.create(m_oImgSize, CV_32FC1);
-  m_oDistThresholdFrame = cv::Scalar(2.0f);
-  m_oDistThresholdVariationFrame.create(m_oImgSize, CV_32FC1);
-  m_oDistThresholdVariationFrame = cv::Scalar(FEEDBACK_V_INCR * 10);
-  m_oMeanMinDistFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanMinDistFrame_LT = cv::Scalar(0.0f);
-  m_oMeanMinDistFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanMinDistFrame_ST = cv::Scalar(0.0f);
-  m_oMeanDownSampledLastDistFrame_LT.create(m_oDownSampledFrameSize_MotionAnalysis, CV_32FC((int)m_nImgChannels));
-  m_oMeanDownSampledLastDistFrame_LT = cv::Scalar(0.0f);
-  m_oMeanDownSampledLastDistFrame_ST.create(m_oDownSampledFrameSize_MotionAnalysis, CV_32FC((int)m_nImgChannels));
-  m_oMeanDownSampledLastDistFrame_ST = cv::Scalar(0.0f);
-  m_oMeanRawSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanRawSegmResFrame_LT = cv::Scalar(0.0f);
-  m_oMeanRawSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanRawSegmResFrame_ST = cv::Scalar(0.0f);
-  m_oMeanFinalSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanFinalSegmResFrame_LT = cv::Scalar(0.0f);
-  m_oMeanFinalSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanFinalSegmResFrame_ST = cv::Scalar(0.0f);
-  m_oUnstableRegionMask.create(m_oImgSize, CV_8UC1);
-  m_oUnstableRegionMask = cv::Scalar_<uchar>(0);
-  m_oBlinksFrame.create(m_oImgSize, CV_8UC1);
-  m_oBlinksFrame = cv::Scalar_<uchar>(0);
-  m_oDownSampledFrame_MotionAnalysis.create(m_oDownSampledFrameSize_MotionAnalysis, CV_8UC((int)m_nImgChannels));
-  m_oDownSampledFrame_MotionAnalysis = cv::Scalar_<uchar>::all(0);
-  m_oLastColorFrame.create(m_oImgSize, CV_8UC((int)m_nImgChannels));
-  m_oLastColorFrame = cv::Scalar_<uchar>::all(0);
-  m_oLastDescFrame.create(m_oImgSize, CV_16UC((int)m_nImgChannels));
-  m_oLastDescFrame = cv::Scalar_<ushort>::all(0);
-  m_oLastRawFGMask.create(m_oImgSize, CV_8UC1);
-  m_oLastRawFGMask = cv::Scalar_<uchar>(0);
-  m_oLastFGMask.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask = cv::Scalar_<uchar>(0);
-  m_oLastFGMask_dilated.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask_dilated = cv::Scalar_<uchar>(0);
-  m_oLastFGMask_dilated_inverted.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask_dilated_inverted = cv::Scalar_<uchar>(0);
-  m_oFGMask_FloodedHoles.create(m_oImgSize, CV_8UC1);
-  m_oFGMask_FloodedHoles = cv::Scalar_<uchar>(0);
-  m_oFGMask_PreFlood.create(m_oImgSize, CV_8UC1);
-  m_oFGMask_PreFlood = cv::Scalar_<uchar>(0);
-  m_oCurrRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
-  m_oCurrRawFGBlinkMask = cv::Scalar_<uchar>(0);
-  m_oLastRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
-  m_oLastRawFGBlinkMask = cv::Scalar_<uchar>(0);
-  m_oTempGlobalWordWeightDiffFactor.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
-  m_oTempGlobalWordWeightDiffFactor = cv::Scalar(-0.1f);
-  m_oMorphExStructElement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
-  m_aPxIdxLUT = new size_t[m_nTotRelevantPxCount];
-  memset(m_aPxIdxLUT, 0, sizeof(size_t)*m_nTotRelevantPxCount);
-  m_aPxInfoLUT_PAWCS = new PxInfo_PAWCS[m_nTotPxCount];
-  memset(m_aPxInfoLUT_PAWCS, 0, sizeof(PxInfo_PAWCS)*m_nTotPxCount);
-  m_aPxInfoLUT = m_aPxInfoLUT_PAWCS;
-  m_apLocalWordDict = new LocalWordBase*[m_nTotRelevantPxCount*m_nCurrLocalWords];
-  memset(m_apLocalWordDict, 0, sizeof(LocalWordBase*)*m_nTotRelevantPxCount*m_nCurrLocalWords);
-  m_apGlobalWordDict = new GlobalWordBase*[m_nCurrGlobalWords];
-  memset(m_apGlobalWordDict, 0, sizeof(GlobalWordBase*)*m_nCurrGlobalWords);
-  if (m_nImgChannels == 1) {
-    CV_DbgAssert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width && m_oLastColorFrame.step.p[1] == 1);
-    CV_DbgAssert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
-    m_aLocalWordList_1ch = new LocalWord_1ch[m_nTotRelevantPxCount*m_nCurrLocalWords];
-    memset(m_aLocalWordList_1ch, 0, sizeof(LocalWord_1ch)*m_nTotRelevantPxCount*m_nCurrLocalWords);
-    m_pLocalWordListIter_1ch = m_aLocalWordList_1ch;
-    m_aGlobalWordList_1ch = new GlobalWord_1ch[m_nCurrGlobalWords];
-    m_pGlobalWordListIter_1ch = m_aGlobalWordList_1ch;
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 3);
-    for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
-      if (m_oROI.data[nPxIter]) {
-        m_aPxIdxLUT[nModelIter] = nPxIter;
-        m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
-        m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
-        m_aPxInfoLUT_PAWCS[nPxIter].nModelIdx = nModelIter;
-        m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx = (size_t)((m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)*m_oDownSampledFrameSize_GlobalWordLookup.width + (m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)) * 4;
-        m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT = new GlobalWordBase*[m_nCurrGlobalWords];
-        for (size_t nGlobalWordIdxIter = 0; nGlobalWordIdxIter < m_nCurrGlobalWords; ++nGlobalWordIdxIter)
-          m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordIdxIter] = &(m_aGlobalWordList_1ch[nGlobalWordIdxIter]);
-        m_oLastColorFrame.data[nPxIter] = oInitImg.data[nPxIter];
-        const size_t nDescIter = nPxIter * 2;
-        LBSP_::computeGrayscaleDescriptor(oInitImg, oInitImg.data[nPxIter], m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxIter]], *((ushort*)(m_oLastDescFrame.data + nDescIter)));
-        ++nModelIter;
-      }
-    }
-  }
-  else { //m_nImgChannels==3
-    CV_DbgAssert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width * 3 && m_oLastColorFrame.step.p[1] == 3);
-    CV_DbgAssert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
-    m_aLocalWordList_3ch = new LocalWord_3ch[m_nTotRelevantPxCount*m_nCurrLocalWords];
-    memset(m_aLocalWordList_3ch, 0, sizeof(LocalWord_3ch)*m_nTotRelevantPxCount*m_nCurrLocalWords);
-    m_pLocalWordListIter_3ch = m_aLocalWordList_3ch;
-    m_aGlobalWordList_3ch = new GlobalWord_3ch[m_nCurrGlobalWords];
-    m_pGlobalWordListIter_3ch = m_aGlobalWordList_3ch;
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold);
-    for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
-      if (m_oROI.data[nPxIter]) {
-        m_aPxIdxLUT[nModelIter] = nPxIter;
-        m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
-        m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
-        m_aPxInfoLUT_PAWCS[nPxIter].nModelIdx = nModelIter;
-        m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx = (size_t)((m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)*m_oDownSampledFrameSize_GlobalWordLookup.width + (m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)) * 4;
-        m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT = new GlobalWordBase*[m_nCurrGlobalWords];
-        for (size_t nGlobalWordIdxIter = 0; nGlobalWordIdxIter < m_nCurrGlobalWords; ++nGlobalWordIdxIter)
-          m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordIdxIter] = &(m_aGlobalWordList_3ch[nGlobalWordIdxIter]);
-        const size_t nPxRGBIter = nPxIter * 3;
-        const size_t nDescRGBIter = nPxRGBIter * 2;
-        for (size_t c = 0; c < 3; ++c) {
-          m_oLastColorFrame.data[nPxRGBIter + c] = oInitImg.data[nPxRGBIter + c];
-          LBSP_::computeSingleRGBDescriptor(oInitImg, oInitImg.data[nPxRGBIter + c], m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxRGBIter + c]], ((ushort*)(m_oLastDescFrame.data + nDescRGBIter))[c]);
-        }
-        ++nModelIter;
-      }
-    }
-  }
-  m_bInitialized = true;
-  refreshModel(1, 0);
-}
-
-void BackgroundSubtractorPAWCS::refreshModel(size_t nBaseOccCount, float fOccDecrFrac, bool bForceFGUpdate) {
-  // == refresh
-  CV_Assert(m_bInitialized);
-  CV_Assert(fOccDecrFrac >= 0.0f && fOccDecrFrac <= 1.0f);
-  if (m_nImgChannels == 1) {
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
-        const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-        const size_t nFloatIter = nPxIter * 4;
-        uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-        const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-        const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
-        const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
-        // == refresh: local decr
-        if (fOccDecrFrac > 0.0f) {
-          for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-            LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-            if (pCurrLocalWord)
-              pCurrLocalWord->nOccurrences -= (size_t)(fOccDecrFrac*pCurrLocalWord->nOccurrences);
-          }
-        }
-        const size_t nCurrWordOccIncr = DEFAULT_LWORD_OCC_INCR;
-        const size_t nTotLocalSamplingIterCount = (s_nSamplesInitPatternWidth*s_nSamplesInitPatternHeight) * 2;
-        for (size_t nLocalSamplingIter = 0; nLocalSamplingIter < nTotLocalSamplingIterCount; ++nLocalSamplingIter) {
-          // == refresh: local resampling
-          int nSampleImgCoord_Y, nSampleImgCoord_X;
-          getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-          const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-          if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nSamplePxIdx]) {
-            const uchar nSampleColor = m_oLastColorFrame.data[nSamplePxIdx];
-            const size_t nSampleDescIdx = nSamplePxIdx * 2;
-            const ushort nSampleIntraDesc = *((ushort*)(m_oLastDescFrame.data + nSampleDescIdx));
-            bool bFoundUninitd = false;
-            size_t nLocalWordIdx;
-            for (nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-              LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-              if (pCurrLocalWord
-                && L1dist(nSampleColor, pCurrLocalWord->oFeature.anColor[0]) <= nCurrColorDistThreshold
-                && hdist(nSampleIntraDesc, pCurrLocalWord->oFeature.anDesc[0]) <= nCurrDescDistThreshold) {
-                pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
-                pCurrLocalWord->nLastOcc = m_nFrameIndex;
-                break;
-              }
-              else if (!pCurrLocalWord)
-                bFoundUninitd = true;
-            }
-            if (nLocalWordIdx == m_nCurrLocalWords) {
-              nLocalWordIdx = m_nCurrLocalWords - 1;
-              LocalWord_1ch* pCurrLocalWord = bFoundUninitd ? m_pLocalWordListIter_1ch++ : (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-              pCurrLocalWord->oFeature.anColor[0] = nSampleColor;
-              pCurrLocalWord->oFeature.anDesc[0] = nSampleIntraDesc;
-              pCurrLocalWord->nOccurrences = nBaseOccCount;
-              pCurrLocalWord->nFirstOcc = m_nFrameIndex;
-              pCurrLocalWord->nLastOcc = m_nFrameIndex;
-              m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
-            }
-            while (nLocalWordIdx > 0 && (!m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1] || GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset) > GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1], m_nFrameIndex, m_nLocalWordWeightOffset))) {
-              std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-              --nLocalWordIdx;
-            }
-          }
-        }
-        CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
-        for (size_t nLocalWordIdx = 1; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-          // == refresh: local random resampling
-          LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-          if (!pCurrLocalWord) {
-            const size_t nRandLocalWordIdx = (rand() % nLocalWordIdx);
-            const LocalWord_1ch* pRefLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nRandLocalWordIdx];
-            const int nRandColorOffset = (rand() % (nCurrColorDistThreshold + 1)) - (int)nCurrColorDistThreshold / 2;
-            pCurrLocalWord = m_pLocalWordListIter_1ch++;
-            pCurrLocalWord->oFeature.anColor[0] = cv::saturate_cast<uchar>((int)pRefLocalWord->oFeature.anColor[0] + nRandColorOffset);
-            pCurrLocalWord->oFeature.anDesc[0] = pRefLocalWord->oFeature.anDesc[0];
-            pCurrLocalWord->nOccurrences = std::max((size_t)(pRefLocalWord->nOccurrences*((float)(m_nCurrLocalWords - nLocalWordIdx) / m_nCurrLocalWords)), (size_t)1);
-            pCurrLocalWord->nFirstOcc = m_nFrameIndex;
-            pCurrLocalWord->nLastOcc = m_nFrameIndex;
-            m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
-          }
-        }
-      }
-    }
-    CV_Assert(m_aLocalWordList_1ch == (m_pLocalWordListIter_1ch - m_nTotRelevantPxCount*m_nCurrLocalWords));
-    cv::Mat oGlobalDictPresenceLookupMap(m_oImgSize, CV_8UC1, cv::Scalar_<uchar>(0));
-    size_t nPxIterIncr = std::max(m_nTotPxCount / m_nCurrGlobalWords, (size_t)1);
-    for (size_t nSamplingPasses = 0; nSamplingPasses < GWORD_DEFAULT_NB_INIT_SAMPL_PASSES; ++nSamplingPasses) {
-      for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-        // == refresh: global resampling
-        const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-        if ((nPxIter%nPxIterIncr) == 0) { // <=(m_nCurrGlobalWords) gwords from (m_nCurrGlobalWords) equally spaced pixels
-          if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
-            const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-            const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-            const size_t nFloatIter = nPxIter * 4;
-            uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-            const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-            const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
-            const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
-            CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
-            const LocalWord_1ch* pRefBestLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx];
-            const float fRefBestLocalWordWeight = GetLocalWordWeight(pRefBestLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-            const uchar nRefBestLocalWordDescBITS = (uchar)popcount(pRefBestLocalWord->oFeature.anDesc[0]);
-            bool bFoundUninitd = false;
-            size_t nGlobalWordIdx;
-            for (nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
-              GlobalWord_1ch* pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
-              if (pCurrGlobalWord
-                && L1dist(pCurrGlobalWord->oFeature.anColor[0], pRefBestLocalWord->oFeature.anColor[0]) <= nCurrColorDistThreshold
-                && L1dist(nRefBestLocalWordDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
-                break;
-              else if (!pCurrGlobalWord)
-                bFoundUninitd = true;
-            }
-            if (nGlobalWordIdx == m_nCurrGlobalWords) {
-              nGlobalWordIdx = m_nCurrGlobalWords - 1;
-              GlobalWord_1ch* pCurrGlobalWord = bFoundUninitd ? m_pGlobalWordListIter_1ch++ : (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
-              pCurrGlobalWord->oFeature.anColor[0] = pRefBestLocalWord->oFeature.anColor[0];
-              pCurrGlobalWord->oFeature.anDesc[0] = pRefBestLocalWord->oFeature.anDesc[0];
-              pCurrGlobalWord->nDescBITS = nRefBestLocalWordDescBITS;
-              pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
-              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-              pCurrGlobalWord->fLatestWeight = 0.0f;
-              m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
-            }
-            float& fCurrGlobalWordLocalWeight = *(float*)(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fCurrGlobalWordLocalWeight < fRefBestLocalWordWeight) {
-              m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight += fRefBestLocalWordWeight;
-              fCurrGlobalWordLocalWeight += fRefBestLocalWordWeight;
-            }
-            oGlobalDictPresenceLookupMap.data[nPxIter] = UCHAR_MAX;
-            while (nGlobalWordIdx > 0 && (!m_apGlobalWordDict[nGlobalWordIdx - 1] || m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)) {
-              std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
-              --nGlobalWordIdx;
-            }
-          }
-        }
-      }
-      nPxIterIncr = std::max(nPxIterIncr / 3, (size_t)1);
-    }
-    for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
-      GlobalWord_1ch* pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
-      if (!pCurrGlobalWord) {
-        pCurrGlobalWord = m_pGlobalWordListIter_1ch++;
-        pCurrGlobalWord->oFeature.anColor[0] = 0;
-        pCurrGlobalWord->oFeature.anDesc[0] = 0;
-        pCurrGlobalWord->nDescBITS = 0;
-        pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
-        pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-        pCurrGlobalWord->fLatestWeight = 0.0f;
-        m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
-      }
-    }
-    CV_Assert((size_t)(m_pGlobalWordListIter_1ch - m_aGlobalWordList_1ch) == m_nCurrGlobalWords && m_aGlobalWordList_1ch == (m_pGlobalWordListIter_1ch - m_nCurrGlobalWords));
-  }
-  else { //m_nImgChannels==3
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
-        const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-        const size_t nFloatIter = nPxIter * 4;
-        uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-        const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-        const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
-        const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
-        // == refresh: local decr
-        if (fOccDecrFrac > 0.0f) {
-          for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-            LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-            if (pCurrLocalWord)
-              pCurrLocalWord->nOccurrences -= (size_t)(fOccDecrFrac*pCurrLocalWord->nOccurrences);
-          }
-        }
-        const size_t nCurrWordOccIncr = DEFAULT_LWORD_OCC_INCR;
-        const size_t nTotLocalSamplingIterCount = (s_nSamplesInitPatternWidth*s_nSamplesInitPatternHeight) * 2;
-        for (size_t nLocalSamplingIter = 0; nLocalSamplingIter < nTotLocalSamplingIterCount; ++nLocalSamplingIter) {
-          // == refresh: local resampling
-          int nSampleImgCoord_Y, nSampleImgCoord_X;
-          getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-          const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-          if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nSamplePxIdx]) {
-            const size_t nSamplePxRGBIdx = nSamplePxIdx * 3;
-            const size_t nSampleDescRGBIdx = nSamplePxRGBIdx * 2;
-            const uchar* const anSampleColor = m_oLastColorFrame.data + nSamplePxRGBIdx;
-            const ushort* const anSampleIntraDesc = ((ushort*)(m_oLastDescFrame.data + nSampleDescRGBIdx));
-            bool bFoundUninitd = false;
-            size_t nLocalWordIdx;
-            for (nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-              LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-              if (pCurrLocalWord
-                && cmixdist<3>(anSampleColor, pCurrLocalWord->oFeature.anColor) <= nCurrTotColorDistThreshold
-                && hdist<3>(anSampleIntraDesc, pCurrLocalWord->oFeature.anDesc) <= nCurrTotDescDistThreshold) {
-                pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
-                pCurrLocalWord->nLastOcc = m_nFrameIndex;
-                break;
-              }
-              else if (!pCurrLocalWord)
-                bFoundUninitd = true;
-            }
-            if (nLocalWordIdx == m_nCurrLocalWords) {
-              nLocalWordIdx = m_nCurrLocalWords - 1;
-              LocalWord_3ch* pCurrLocalWord = bFoundUninitd ? m_pLocalWordListIter_3ch++ : (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-              for (size_t c = 0; c < 3; ++c) {
-                pCurrLocalWord->oFeature.anColor[c] = anSampleColor[c];
-                pCurrLocalWord->oFeature.anDesc[c] = anSampleIntraDesc[c];
-              }
-              pCurrLocalWord->nOccurrences = nBaseOccCount;
-              pCurrLocalWord->nFirstOcc = m_nFrameIndex;
-              pCurrLocalWord->nLastOcc = m_nFrameIndex;
-              m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
-            }
-            while (nLocalWordIdx > 0 && (!m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1] || GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset) > GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1], m_nFrameIndex, m_nLocalWordWeightOffset))) {
-              std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-              --nLocalWordIdx;
-            }
-          }
-        }
-        CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
-        for (size_t nLocalWordIdx = 1; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-          // == refresh: local random resampling
-          LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-          if (!pCurrLocalWord) {
-            const size_t nRandLocalWordIdx = (rand() % nLocalWordIdx);
-            const LocalWord_3ch* pRefLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nRandLocalWordIdx];
-            const int nRandColorOffset = (rand() % (nCurrTotColorDistThreshold / 3 + 1)) - (int)(nCurrTotColorDistThreshold / 6);
-            pCurrLocalWord = m_pLocalWordListIter_3ch++;
-            for (size_t c = 0; c < 3; ++c) {
-              pCurrLocalWord->oFeature.anColor[c] = cv::saturate_cast<uchar>((int)pRefLocalWord->oFeature.anColor[c] + nRandColorOffset);
-              pCurrLocalWord->oFeature.anDesc[c] = pRefLocalWord->oFeature.anDesc[c];
-            }
-            pCurrLocalWord->nOccurrences = std::max((size_t)(pRefLocalWord->nOccurrences*((float)(m_nCurrLocalWords - nLocalWordIdx) / m_nCurrLocalWords)), (size_t)1);
-            pCurrLocalWord->nFirstOcc = m_nFrameIndex;
-            pCurrLocalWord->nLastOcc = m_nFrameIndex;
-            m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
-          }
-        }
-      }
-    }
-    CV_Assert(m_aLocalWordList_3ch == (m_pLocalWordListIter_3ch - m_nTotRelevantPxCount*m_nCurrLocalWords));
-    cv::Mat oGlobalDictPresenceLookupMap(m_oImgSize, CV_8UC1, cv::Scalar_<uchar>(0));
-    size_t nPxIterIncr = std::max(m_nTotPxCount / m_nCurrGlobalWords, (size_t)1);
-    for (size_t nSamplingPasses = 0; nSamplingPasses < GWORD_DEFAULT_NB_INIT_SAMPL_PASSES; ++nSamplingPasses) {
-      for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-        // == refresh: global resampling
-        const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-        if ((nPxIter%nPxIterIncr) == 0) { // <=(m_nCurrGlobalWords) gwords from (m_nCurrGlobalWords) equally spaced pixels
-          if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
-            const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-            const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-            const size_t nFloatIter = nPxIter * 4;
-            uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-            const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-            const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
-            const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
-            CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
-            const LocalWord_3ch* pRefBestLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx];
-            const float fRefBestLocalWordWeight = GetLocalWordWeight(pRefBestLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-            const uchar nRefBestLocalWordDescBITS = (uchar)popcount<3>(pRefBestLocalWord->oFeature.anDesc);
-            bool bFoundUninitd = false;
-            size_t nGlobalWordIdx;
-            for (nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
-              GlobalWord_3ch* pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
-              if (pCurrGlobalWord
-                && L1dist(nRefBestLocalWordDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
-                && cmixdist<3>(pRefBestLocalWord->oFeature.anColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
-                break;
-              else if (!pCurrGlobalWord)
-                bFoundUninitd = true;
-            }
-            if (nGlobalWordIdx == m_nCurrGlobalWords) {
-              nGlobalWordIdx = m_nCurrGlobalWords - 1;
-              GlobalWord_3ch* pCurrGlobalWord = bFoundUninitd ? m_pGlobalWordListIter_3ch++ : (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
-              for (size_t c = 0; c < 3; ++c) {
-                pCurrGlobalWord->oFeature.anColor[c] = pRefBestLocalWord->oFeature.anColor[c];
-                pCurrGlobalWord->oFeature.anDesc[c] = pRefBestLocalWord->oFeature.anDesc[c];
-              }
-              pCurrGlobalWord->nDescBITS = nRefBestLocalWordDescBITS;
-              pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
-              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-              pCurrGlobalWord->fLatestWeight = 0.0f;
-              m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
-            }
-            float& fCurrGlobalWordLocalWeight = *(float*)(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fCurrGlobalWordLocalWeight < fRefBestLocalWordWeight) {
-              m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight += fRefBestLocalWordWeight;
-              fCurrGlobalWordLocalWeight += fRefBestLocalWordWeight;
-            }
-            oGlobalDictPresenceLookupMap.data[nPxIter] = UCHAR_MAX;
-            while (nGlobalWordIdx > 0 && (!m_apGlobalWordDict[nGlobalWordIdx - 1] || m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)) {
-              std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
-              --nGlobalWordIdx;
-            }
-          }
-        }
-      }
-      nPxIterIncr = std::max(nPxIterIncr / 3, (size_t)1);
-    }
-    for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
-      GlobalWord_3ch* pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
-      if (!pCurrGlobalWord) {
-        pCurrGlobalWord = m_pGlobalWordListIter_3ch++;
-        for (size_t c = 0; c < 3; ++c) {
-          pCurrGlobalWord->oFeature.anColor[c] = 0;
-          pCurrGlobalWord->oFeature.anDesc[c] = 0;
-        }
-        pCurrGlobalWord->nDescBITS = 0;
-        pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
-        pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-        pCurrGlobalWord->fLatestWeight = 0.0f;
-        m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
-      }
-    }
-    CV_Assert((size_t)(m_pGlobalWordListIter_3ch - m_aGlobalWordList_3ch) == m_nCurrGlobalWords && m_aGlobalWordList_3ch == (m_pGlobalWordListIter_3ch - m_nCurrGlobalWords));
-  }
-  for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-    // == refresh: per-px global word sort
-    const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-    const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-    float fLastGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[0]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-    for (size_t nGlobalWordLUTIdx = 1; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-      const float fCurrGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-      if (fCurrGlobalWordLocalWeight > fLastGlobalWordLocalWeight)
-        std::swap(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx], m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx - 1]);
-      else
-        fLastGlobalWordLocalWeight = fCurrGlobalWordLocalWeight;
-    }
-  }
-}
-
-void BackgroundSubtractorPAWCS::apply(cv::InputArray _image, cv::OutputArray _fgmask, double learningRateOverride) {
-  // == process
-  CV_Assert(m_bInitialized);
-  cv::Mat oInputImg = _image.getMat();
-  CV_Assert(oInputImg.type() == m_nImgType && oInputImg.size() == m_oImgSize);
-  CV_Assert(oInputImg.isContinuous());
-  _fgmask.create(m_oImgSize, CV_8UC1);
-  cv::Mat oCurrFGMask = _fgmask.getMat();
-  memset(oCurrFGMask.data, 0, oCurrFGMask.cols*oCurrFGMask.rows);
-  const bool bBootstrapping = ++m_nFrameIndex <= DEFAULT_BOOTSTRAP_WIN_SIZE;
-  const size_t nCurrSamplesForMovingAvg_LT = bBootstrapping ? m_nSamplesForMovingAvgs / 2 : m_nSamplesForMovingAvgs;
-  const size_t nCurrSamplesForMovingAvg_ST = nCurrSamplesForMovingAvg_LT / 4;
-  const float fRollAvgFactor_LT = 1.0f / std::min(m_nFrameIndex, nCurrSamplesForMovingAvg_LT);
-  const float fRollAvgFactor_ST = 1.0f / std::min(m_nFrameIndex, nCurrSamplesForMovingAvg_ST);
-  const size_t nCurrGlobalWordUpdateRate = bBootstrapping ? DEFAULT_RESAMPLING_RATE / 2 : DEFAULT_RESAMPLING_RATE;
-  size_t nFlatRegionCount = 0;
-  if (m_nImgChannels == 1) {
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      const size_t nDescIter = nPxIter * 2;
-      const size_t nFloatIter = nPxIter * 4;
-      const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-      const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-      const uchar nCurrColor = oInputImg.data[nPxIter];
-      uchar& nLastColor = m_oLastColorFrame.data[nPxIter];
-      ushort& nLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nDescIter));
-      size_t nMinColorDist = s_nColorMaxDataRange_1ch;
-      size_t nMinDescDist = s_nDescMaxDataRange_1ch;
-      float& fCurrMeanRawSegmRes_LT = *(float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter);
-      float& fCurrMeanRawSegmRes_ST = *(float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter);
-      float& fCurrMeanFinalSegmRes_LT = *(float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter);
-      float& fCurrMeanFinalSegmRes_ST = *(float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter);
-      float& fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-      float& fCurrDistThresholdVariationFactor = *(float*)(m_oDistThresholdVariationFrame.data + nFloatIter);
-      float& fCurrLearningRate = *(float*)(m_oUpdateRateFrame.data + nFloatIter);
-      float& fCurrMeanMinDist_LT = *(float*)(m_oMeanMinDistFrame_LT.data + nFloatIter);
-      float& fCurrMeanMinDist_ST = *(float*)(m_oMeanMinDistFrame_ST.data + nFloatIter);
-      const float fBestLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
-      const float fLocalWordsWeightSumThreshold = fBestLocalWordWeight / (fCurrDistThresholdFactor * 2);
-      uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-      uchar& nCurrRegionIllumUpdtVal = m_oIllumUpdtRegionMask.data[nPxIter];
-      uchar& nCurrRegionSegmVal = oCurrFGMask.data[nPxIter];
-      const bool bCurrRegionIsROIBorder = m_oROI.data[nPxIter] < UCHAR_MAX;
-      const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
-      const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
-      ushort nCurrInterDesc, nCurrIntraDesc;
-      LBSP_::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nCurrIntraDesc);
-      const uchar nCurrIntraDescBITS = (uchar)popcount(nCurrIntraDesc);
-      const bool bCurrRegionIsFlat = nCurrIntraDescBITS < FLAT_REGION_BIT_COUNT;
-      if (bCurrRegionIsFlat)
-        ++nFlatRegionCount;
-      const size_t nCurrWordOccIncr = (DEFAULT_LWORD_OCC_INCR + m_nModelResetCooldown) << int(bCurrRegionIsFlat || bBootstrapping);
-      const size_t nCurrLocalWordUpdateRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : bCurrRegionIsFlat ? (size_t)ceil(fCurrLearningRate + FEEDBACK_T_LOWER) / 2 : (size_t)ceil(fCurrLearningRate);
-      const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
-      const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
-      size_t nLocalWordIdx = 0;
-      float fPotentialLocalWordsWeightSum = 0.0f;
-      float fLastLocalWordWeight = FLT_MAX;
-      while (nLocalWordIdx < m_nCurrLocalWords && fPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
-        LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-        const float fCurrLocalWordWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-        {
-          const size_t nColorDist = L1dist(nCurrColor, pCurrLocalWord->oFeature.anColor[0]);
-          const size_t nIntraDescDist = hdist(nCurrIntraDesc, pCurrLocalWord->oFeature.anDesc[0]);
-          LBSP_::computeGrayscaleDescriptor(oInputImg, pCurrLocalWord->oFeature.anColor[0], nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[0]], nCurrInterDesc);
-          const size_t nInterDescDist = hdist(nCurrInterDesc, pCurrLocalWord->oFeature.anDesc[0]);
-          const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
-          if ((!bCurrRegionIsUnstable || bCurrRegionIsFlat || bCurrRegionIsROIBorder)
-            && nColorDist <= nCurrColorDistThreshold
-            && nColorDist >= nCurrColorDistThreshold / 2
-            && nIntraDescDist <= nCurrDescDistThreshold / 2
-            && (rand() % (nCurrRegionIllumUpdtVal ? (nCurrLocalWordUpdateRate / 2 + 1) : nCurrLocalWordUpdateRate)) == 0) {
-            // == illum updt
-            pCurrLocalWord->oFeature.anColor[0] = nCurrColor;
-            pCurrLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
-            m_oIllumUpdtRegionMask.data[nPxIter - 1] = 1 & m_oROI.data[nPxIter - 1];
-            m_oIllumUpdtRegionMask.data[nPxIter + 1] = 1 & m_oROI.data[nPxIter + 1];
-            m_oIllumUpdtRegionMask.data[nPxIter] = 2;
-          }
-          if (nDescDist <= nCurrDescDistThreshold && nColorDist <= nCurrColorDistThreshold) {
-            fPotentialLocalWordsWeightSum += fCurrLocalWordWeight;
-            pCurrLocalWord->nLastOcc = m_nFrameIndex;
-            if ((!m_oLastFGMask.data[nPxIter] || m_bUsingMovingCamera) && fCurrLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-              pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
-            nMinColorDist = std::min(nMinColorDist, nColorDist);
-            nMinDescDist = std::min(nMinDescDist, nDescDist);
-          }
-        }
-        if (fCurrLocalWordWeight > fLastLocalWordWeight) {
-          std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-        }
-        else
-          fLastLocalWordWeight = fCurrLocalWordWeight;
-        ++nLocalWordIdx;
-      }
-      while (nLocalWordIdx < m_nCurrLocalWords) {
-        const float fCurrLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
-        if (fCurrLocalWordWeight > fLastLocalWordWeight) {
-          std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-        }
-        else
-          fLastLocalWordWeight = fCurrLocalWordWeight;
-        ++nLocalWordIdx;
-      }
-      if (fPotentialLocalWordsWeightSum >= fLocalWordsWeightSumThreshold || bCurrRegionIsROIBorder) {
-        // == background
-        const float fNormalizedMinDist = std::max((float)nMinColorDist / s_nColorMaxDataRange_1ch, (float)nMinDescDist / s_nDescMaxDataRange_1ch);
-        fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT);
-        fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST);
-        if ((rand() % nCurrLocalWordUpdateRate) == 0) {
-          size_t nGlobalWordLUTIdx;
-          GlobalWord_1ch* pCurrGlobalWord = nullptr;
-          for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-            pCurrGlobalWord = (GlobalWord_1ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
-            if (L1dist(pCurrGlobalWord->oFeature.anColor[0], nCurrColor) <= nCurrColorDistThreshold
-              && L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
-              break;
-          }
-          if (nGlobalWordLUTIdx != m_nCurrGlobalWords || (rand() % (nCurrLocalWordUpdateRate * 2)) == 0) {
-            if (nGlobalWordLUTIdx == m_nCurrGlobalWords) {
-              pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[m_nCurrGlobalWords - 1];
-              pCurrGlobalWord->oFeature.anColor[0] = nCurrColor;
-              pCurrGlobalWord->oFeature.anDesc[0] = nCurrIntraDesc;
-              pCurrGlobalWord->nDescBITS = nCurrIntraDescBITS;
-              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-              pCurrGlobalWord->fLatestWeight = 0.0f;
-            }
-            float& fCurrGlobalWordLocalWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fCurrGlobalWordLocalWeight < fPotentialLocalWordsWeightSum) {
-              pCurrGlobalWord->fLatestWeight += fPotentialLocalWordsWeightSum;
-              fCurrGlobalWordLocalWeight += fPotentialLocalWordsWeightSum;
-            }
-          }
-        }
-      }
-      else {
-        // == foreground
-        const float fNormalizedMinDist = std::max(std::max((float)nMinColorDist / s_nColorMaxDataRange_1ch, (float)nMinDescDist / s_nDescMaxDataRange_1ch), (fLocalWordsWeightSumThreshold - fPotentialLocalWordsWeightSum) / fLocalWordsWeightSumThreshold);
-        fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
-        fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
-        if (bCurrRegionIsFlat || (rand() % nCurrLocalWordUpdateRate) == 0) {
-          size_t nGlobalWordLUTIdx;
-          GlobalWord_1ch* pCurrGlobalWord;
-          for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-            pCurrGlobalWord = (GlobalWord_1ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
-            if (L1dist(pCurrGlobalWord->oFeature.anColor[0], nCurrColor) <= nCurrColorDistThreshold
-              && L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
-              break;
-          }
-          if (nGlobalWordLUTIdx == m_nCurrGlobalWords)
-            nCurrRegionSegmVal = UCHAR_MAX;
-          else {
-            const float fGlobalWordLocalizedWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fPotentialLocalWordsWeightSum + fGlobalWordLocalizedWeight / (bCurrRegionIsFlat ? 2 : 4) < fLocalWordsWeightSumThreshold)
-              nCurrRegionSegmVal = UCHAR_MAX;
-          }
-        }
-        else
-          nCurrRegionSegmVal = UCHAR_MAX;
-        if (fPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
-          const size_t nNewLocalWordIdx = m_nCurrLocalWords - 1;
-          LocalWord_1ch* pNewLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nNewLocalWordIdx];
-          pNewLocalWord->oFeature.anColor[0] = nCurrColor;
-          pNewLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
-          pNewLocalWord->nOccurrences = nCurrWordOccIncr;
-          pNewLocalWord->nFirstOcc = m_nFrameIndex;
-          pNewLocalWord->nLastOcc = m_nFrameIndex;
-        }
-      }
-      // == neighb updt
-      if ((!nCurrRegionSegmVal && (rand() % nCurrLocalWordUpdateRate) == 0) || bCurrRegionIsROIBorder || m_bUsingMovingCamera) {
-        //if((!nCurrRegionSegmVal && (rand()%(nCurrRegionIllumUpdtVal?(nCurrLocalWordUpdateRate/2+1):nCurrLocalWordUpdateRate))==0) || bCurrRegionIsROIBorder) {
-        int nSampleImgCoord_Y, nSampleImgCoord_X;
-        if (bCurrRegionIsFlat || bCurrRegionIsROIBorder || m_bUsingMovingCamera)
-          getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-        else
-          getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-        const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-        if (m_oROI.data[nSamplePxIdx]) {
-          const size_t nNeighborLocalDictIdx = m_aPxInfoLUT_PAWCS[nSamplePxIdx].nModelIdx*m_nCurrLocalWords;
-          size_t nNeighborLocalWordIdx = 0;
-          float fNeighborPotentialLocalWordsWeightSum = 0.0f;
-          while (nNeighborLocalWordIdx < m_nCurrLocalWords && fNeighborPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
-            LocalWord_1ch* pNeighborLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
-            const size_t nNeighborColorDist = L1dist(nCurrColor, pNeighborLocalWord->oFeature.anColor[0]);
-            const size_t nNeighborIntraDescDist = hdist(nCurrIntraDesc, pNeighborLocalWord->oFeature.anDesc[0]);
-            const bool bNeighborRegionIsFlat = popcount(pNeighborLocalWord->oFeature.anDesc[0]) < FLAT_REGION_BIT_COUNT;
-            const size_t nNeighborWordOccIncr = bNeighborRegionIsFlat ? nCurrWordOccIncr * 2 : nCurrWordOccIncr;
-            if (nNeighborColorDist <= nCurrColorDistThreshold && nNeighborIntraDescDist <= nCurrDescDistThreshold) {
-              const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-              fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
-              pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-              if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-                pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
-            }
-            else if (!oCurrFGMask.data[nSamplePxIdx] && bCurrRegionIsFlat && (bBootstrapping || (rand() % nCurrLocalWordUpdateRate) == 0)) {
-              const size_t nSampleDescIdx = nSamplePxIdx * 2;
-              ushort& nNeighborLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nSampleDescIdx));
-              const size_t nNeighborLastIntraDescDist = hdist(nCurrIntraDesc, nNeighborLastIntraDesc);
-              if (nNeighborColorDist <= nCurrColorDistThreshold && nNeighborLastIntraDescDist <= nCurrDescDistThreshold / 2) {
-                const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-                fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
-                pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-                if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-                  pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
-                pNeighborLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
-              }
-            }
-            ++nNeighborLocalWordIdx;
-          }
-          if (fNeighborPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
-            nNeighborLocalWordIdx = m_nCurrLocalWords - 1;
-            LocalWord_1ch* pNeighborLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
-            pNeighborLocalWord->oFeature.anColor[0] = nCurrColor;
-            pNeighborLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
-            pNeighborLocalWord->nOccurrences = nCurrWordOccIncr;
-            pNeighborLocalWord->nFirstOcc = m_nFrameIndex;
-            pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-          }
-        }
-      }
-      if (nCurrRegionIllumUpdtVal)
-        nCurrRegionIllumUpdtVal -= 1;
-      // == feedback adj
-      bCurrRegionIsUnstable = fCurrDistThresholdFactor > UNSTABLE_REG_RDIST_MIN || (fCurrMeanRawSegmRes_LT - fCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (fCurrMeanRawSegmRes_ST - fCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN;
-      if (m_oLastFGMask.data[nPxIter] || (std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && nCurrRegionSegmVal))
-        fCurrLearningRate = std::min(fCurrLearningRate + FEEDBACK_T_INCR / (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST)*fCurrDistThresholdVariationFactor), FEEDBACK_T_UPPER);
-      else
-        fCurrLearningRate = std::max(fCurrLearningRate - FEEDBACK_T_DECR*fCurrDistThresholdVariationFactor / std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST), FEEDBACK_T_LOWER);
-      if (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
-        (fCurrDistThresholdVariationFactor) += bBootstrapping ? FEEDBACK_V_INCR * 2 : FEEDBACK_V_INCR;
-      else
-        fCurrDistThresholdVariationFactor = std::max(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR*((bBootstrapping || bCurrRegionIsFlat) ? 2 : m_oLastFGMask.data[nPxIter] ? 0.5f : 1), FEEDBACK_V_DECR);
-      if (fCurrDistThresholdFactor < std::pow(1.0f + std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) * 2, 2))
-        fCurrDistThresholdFactor += FEEDBACK_R_VAR*(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR);
-      else
-        fCurrDistThresholdFactor = std::max(fCurrDistThresholdFactor - FEEDBACK_R_VAR / fCurrDistThresholdVariationFactor, 1.0f);
-      nLastIntraDesc = nCurrIntraDesc;
-      nLastColor = nCurrColor;
-    }
-  }
-  else { //m_nImgChannels==3
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      const size_t nPxRGBIter = nPxIter * 3;
-      const size_t nDescRGBIter = nPxRGBIter * 2;
-      const size_t nFloatIter = nPxIter * 4;
-      const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-      const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-      const uchar* const anCurrColor = oInputImg.data + nPxRGBIter;
-      uchar* anLastColor = m_oLastColorFrame.data + nPxRGBIter;
-      ushort* anLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nDescRGBIter));
-      size_t nMinTotColorDist = s_nColorMaxDataRange_3ch;
-      size_t nMinTotDescDist = s_nDescMaxDataRange_3ch;
-      float& fCurrMeanRawSegmRes_LT = *(float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter);
-      float& fCurrMeanRawSegmRes_ST = *(float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter);
-      float& fCurrMeanFinalSegmRes_LT = *(float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter);
-      float& fCurrMeanFinalSegmRes_ST = *(float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter);
-      float& fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
-      float& fCurrDistThresholdVariationFactor = *(float*)(m_oDistThresholdVariationFrame.data + nFloatIter);
-      float& fCurrLearningRate = *(float*)(m_oUpdateRateFrame.data + nFloatIter);
-      float& fCurrMeanMinDist_LT = *(float*)(m_oMeanMinDistFrame_LT.data + nFloatIter);
-      float& fCurrMeanMinDist_ST = *(float*)(m_oMeanMinDistFrame_ST.data + nFloatIter);
-      const float fBestLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
-      const float fLocalWordsWeightSumThreshold = fBestLocalWordWeight / (fCurrDistThresholdFactor * 2);
-      uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
-      uchar& nCurrRegionIllumUpdtVal = m_oIllumUpdtRegionMask.data[nPxIter];
-      uchar& nCurrRegionSegmVal = oCurrFGMask.data[nPxIter];
-      const bool bCurrRegionIsROIBorder = m_oROI.data[nPxIter] < UCHAR_MAX;
-      const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
-      const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
-      ushort anCurrInterDesc[3], anCurrIntraDesc[3];
-      const size_t anCurrIntraLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]] };
-      LBSP_::computeRGBDescriptor(oInputImg, anCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrIntraLBSPThresholds, anCurrIntraDesc);
-      const uchar nCurrIntraDescBITS = (uchar)popcount<3>(anCurrIntraDesc);
-      const bool bCurrRegionIsFlat = nCurrIntraDescBITS < FLAT_REGION_BIT_COUNT * 2;
-      if (bCurrRegionIsFlat)
-        ++nFlatRegionCount;
-      const size_t nCurrWordOccIncr = (DEFAULT_LWORD_OCC_INCR + m_nModelResetCooldown) << int(bCurrRegionIsFlat || bBootstrapping);
-      const size_t nCurrLocalWordUpdateRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : bCurrRegionIsFlat ? (size_t)ceil(fCurrLearningRate + FEEDBACK_T_LOWER) / 2 : (size_t)ceil(fCurrLearningRate);
-      const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
-      const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
-      size_t nLocalWordIdx = 0;
-      float fPotentialLocalWordsWeightSum = 0.0f;
-      float fLastLocalWordWeight = FLT_MAX;
-      while (nLocalWordIdx < m_nCurrLocalWords && fPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
-        LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-        const float fCurrLocalWordWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-        {
-          const size_t nTotColorL1Dist = L1dist<3>(anCurrColor, pCurrLocalWord->oFeature.anColor);
-          const size_t nColorDistortion = cdist<3>(anCurrColor, pCurrLocalWord->oFeature.anColor);
-          const size_t nTotColorMixDist = cmixdist(nTotColorL1Dist, nColorDistortion);
-          const size_t nTotIntraDescDist = hdist<3>(anCurrIntraDesc, pCurrLocalWord->oFeature.anDesc);
-          const size_t anCurrInterLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[0]],m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[1]],m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[2]] };
-          LBSP_::computeRGBDescriptor(oInputImg, pCurrLocalWord->oFeature.anColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrInterLBSPThresholds, anCurrInterDesc);
-          const size_t nTotInterDescDist = hdist<3>(anCurrInterDesc, pCurrLocalWord->oFeature.anDesc);
-          const size_t nTotDescDist = (nTotIntraDescDist + nTotInterDescDist) / 2;
-          if ((!bCurrRegionIsUnstable || bCurrRegionIsFlat || bCurrRegionIsROIBorder)
-            && nTotColorMixDist <= nCurrTotColorDistThreshold
-            && nTotColorL1Dist >= nCurrTotColorDistThreshold / 2
-            && nTotIntraDescDist <= nCurrTotDescDistThreshold / 2
-            && (rand() % (nCurrRegionIllumUpdtVal ? (nCurrLocalWordUpdateRate / 2 + 1) : nCurrLocalWordUpdateRate)) == 0) {
-            // == illum updt
-            for (size_t c = 0; c < 3; ++c) {
-              pCurrLocalWord->oFeature.anColor[c] = anCurrColor[c];
-              pCurrLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
-            }
-            m_oIllumUpdtRegionMask.data[nPxIter - 1] = 1 & m_oROI.data[nPxIter - 1];
-            m_oIllumUpdtRegionMask.data[nPxIter + 1] = 1 & m_oROI.data[nPxIter + 1];
-            m_oIllumUpdtRegionMask.data[nPxIter] = 2;
-          }
-          if (nTotDescDist <= nCurrTotDescDistThreshold && nTotColorMixDist <= nCurrTotColorDistThreshold) {
-            fPotentialLocalWordsWeightSum += fCurrLocalWordWeight;
-            pCurrLocalWord->nLastOcc = m_nFrameIndex;
-            if ((!m_oLastFGMask.data[nPxIter] || m_bUsingMovingCamera) && fCurrLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-              pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
-            nMinTotColorDist = std::min(nMinTotColorDist, nTotColorMixDist);
-            nMinTotDescDist = std::min(nMinTotDescDist, nTotDescDist);
-          }
-        }
-        if (fCurrLocalWordWeight > fLastLocalWordWeight) {
-          std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-        }
-        else
-          fLastLocalWordWeight = fCurrLocalWordWeight;
-        ++nLocalWordIdx;
-      }
-      while (nLocalWordIdx < m_nCurrLocalWords) {
-        const float fCurrLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
-        if (fCurrLocalWordWeight > fLastLocalWordWeight) {
-          std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
-        }
-        else
-          fLastLocalWordWeight = fCurrLocalWordWeight;
-        ++nLocalWordIdx;
-      }
-      if (fPotentialLocalWordsWeightSum >= fLocalWordsWeightSumThreshold || bCurrRegionIsROIBorder) {
-        // == background
-        const float fNormalizedMinDist = std::max((float)nMinTotColorDist / s_nColorMaxDataRange_3ch, (float)nMinTotDescDist / s_nDescMaxDataRange_3ch);
-        fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT);
-        fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST);
-        if ((rand() % nCurrLocalWordUpdateRate) == 0) {
-          size_t nGlobalWordLUTIdx;
-          GlobalWord_3ch* pCurrGlobalWord = nullptr;
-          for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-            pCurrGlobalWord = (GlobalWord_3ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
-            if (L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
-              && cmixdist<3>(anCurrColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
-              break;
-          }
-          if (nGlobalWordLUTIdx != m_nCurrGlobalWords || (rand() % (nCurrLocalWordUpdateRate * 2)) == 0) {
-            if (nGlobalWordLUTIdx == m_nCurrGlobalWords) {
-              pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[m_nCurrGlobalWords - 1];
-              for (size_t c = 0; c < 3; ++c) {
-                pCurrGlobalWord->oFeature.anColor[c] = anCurrColor[c];
-                pCurrGlobalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
-              }
-              pCurrGlobalWord->nDescBITS = nCurrIntraDescBITS;
-              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
-              pCurrGlobalWord->fLatestWeight = 0.0f;
-            }
-            float& fCurrGlobalWordLocalWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fCurrGlobalWordLocalWeight < fPotentialLocalWordsWeightSum) {
-              pCurrGlobalWord->fLatestWeight += fPotentialLocalWordsWeightSum;
-              fCurrGlobalWordLocalWeight += fPotentialLocalWordsWeightSum;
-            }
-          }
-        }
-      }
-      else {
-        // == foreground
-        const float fNormalizedMinDist = std::max(std::max((float)nMinTotColorDist / s_nColorMaxDataRange_3ch, (float)nMinTotDescDist / s_nDescMaxDataRange_3ch), (fLocalWordsWeightSumThreshold - fPotentialLocalWordsWeightSum) / fLocalWordsWeightSumThreshold);
-        fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
-        fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
-        if (bCurrRegionIsFlat || (rand() % nCurrLocalWordUpdateRate) == 0) {
-          size_t nGlobalWordLUTIdx;
-          GlobalWord_3ch* pCurrGlobalWord;
-          for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-            pCurrGlobalWord = (GlobalWord_3ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
-            if (L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
-              && cmixdist<3>(anCurrColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
-              break;
-          }
-          if (nGlobalWordLUTIdx == m_nCurrGlobalWords)
-            nCurrRegionSegmVal = UCHAR_MAX;
-          else {
-            const float fGlobalWordLocalizedWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-            if (fPotentialLocalWordsWeightSum + fGlobalWordLocalizedWeight / (bCurrRegionIsFlat ? 2 : 4) < fLocalWordsWeightSumThreshold)
-              nCurrRegionSegmVal = UCHAR_MAX;
-          }
-        }
-        else
-          nCurrRegionSegmVal = UCHAR_MAX;
-        if (fPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
-          const size_t nNewLocalWordIdx = m_nCurrLocalWords - 1;
-          LocalWord_3ch* pNewLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nNewLocalWordIdx];
-          for (size_t c = 0; c < 3; ++c) {
-            pNewLocalWord->oFeature.anColor[c] = anCurrColor[c];
-            pNewLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
-          }
-          pNewLocalWord->nOccurrences = nCurrWordOccIncr;
-          pNewLocalWord->nFirstOcc = m_nFrameIndex;
-          pNewLocalWord->nLastOcc = m_nFrameIndex;
-        }
-      }
-      // == neighb updt
-      if ((!nCurrRegionSegmVal && (rand() % nCurrLocalWordUpdateRate) == 0) || bCurrRegionIsROIBorder || m_bUsingMovingCamera) {
-        //if((!nCurrRegionSegmVal && (rand()%(nCurrRegionIllumUpdtVal?(nCurrLocalWordUpdateRate/2+1):nCurrLocalWordUpdateRate))==0) || bCurrRegionIsROIBorder) {
-        int nSampleImgCoord_Y, nSampleImgCoord_X;
-        if (bCurrRegionIsFlat || bCurrRegionIsROIBorder || m_bUsingMovingCamera)
-          getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-        else
-          getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
-        const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-        if (m_oROI.data[nSamplePxIdx]) {
-          const size_t nNeighborLocalDictIdx = m_aPxInfoLUT_PAWCS[nSamplePxIdx].nModelIdx*m_nCurrLocalWords;
-          size_t nNeighborLocalWordIdx = 0;
-          float fNeighborPotentialLocalWordsWeightSum = 0.0f;
-          while (nNeighborLocalWordIdx < m_nCurrLocalWords && fNeighborPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
-            LocalWord_3ch* pNeighborLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
-            const size_t nNeighborTotColorL1Dist = L1dist<3>(anCurrColor, pNeighborLocalWord->oFeature.anColor);
-            const size_t nNeighborColorDistortion = cdist<3>(anCurrColor, pNeighborLocalWord->oFeature.anColor);
-            const size_t nNeighborTotColorMixDist = cmixdist(nNeighborTotColorL1Dist, nNeighborColorDistortion);
-            const size_t nNeighborTotIntraDescDist = hdist<3>(anCurrIntraDesc, pNeighborLocalWord->oFeature.anDesc);
-            const bool bNeighborRegionIsFlat = popcount<3>(pNeighborLocalWord->oFeature.anDesc) < FLAT_REGION_BIT_COUNT * 2;
-            const size_t nNeighborWordOccIncr = bNeighborRegionIsFlat ? nCurrWordOccIncr * 2 : nCurrWordOccIncr;
-            if (nNeighborTotColorMixDist <= nCurrTotColorDistThreshold && nNeighborTotIntraDescDist <= nCurrTotDescDistThreshold) {
-              const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-              fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
-              pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-              if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-                pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
-            }
-            else if (!oCurrFGMask.data[nSamplePxIdx] && bCurrRegionIsFlat && (bBootstrapping || (rand() % nCurrLocalWordUpdateRate) == 0)) {
-              const size_t nSamplePxRGBIdx = nSamplePxIdx * 3;
-              const size_t nSampleDescRGBIdx = nSamplePxRGBIdx * 2;
-              ushort* anNeighborLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nSampleDescRGBIdx));
-              const size_t nNeighborTotLastIntraDescDist = hdist<3>(anCurrIntraDesc, anNeighborLastIntraDesc);
-              if (nNeighborTotColorMixDist <= nCurrTotColorDistThreshold && nNeighborTotLastIntraDescDist <= nCurrTotDescDistThreshold / 2) {
-                const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-                fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
-                pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-                if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-                  pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
-                for (size_t c = 0; c < 3; ++c)
-                  pNeighborLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
-              }
-              else {
-                const bool bNeighborLastRegionIsFlat = popcount<3>(anNeighborLastIntraDesc) < FLAT_REGION_BIT_COUNT * 2;
-                if (bNeighborLastRegionIsFlat && bCurrRegionIsFlat &&
-                  nNeighborTotLastIntraDescDist + nNeighborTotIntraDescDist <= nCurrTotDescDistThreshold &&
-                  nNeighborColorDistortion <= nCurrTotColorDistThreshold / 4) {
-                  const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-                  fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
-                  pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-                  if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
-                    pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
-                  for (size_t c = 0; c < 3; ++c)
-                    pNeighborLocalWord->oFeature.anColor[c] = anCurrColor[c];
-                }
-              }
-            }
-            ++nNeighborLocalWordIdx;
-          }
-          if (fNeighborPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
-            nNeighborLocalWordIdx = m_nCurrLocalWords - 1;
-            LocalWord_3ch* pNeighborLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
-            for (size_t c = 0; c < 3; ++c) {
-              pNeighborLocalWord->oFeature.anColor[c] = anCurrColor[c];
-              pNeighborLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
-            }
-            pNeighborLocalWord->nOccurrences = nCurrWordOccIncr;
-            pNeighborLocalWord->nFirstOcc = m_nFrameIndex;
-            pNeighborLocalWord->nLastOcc = m_nFrameIndex;
-          }
-        }
-      }
-      if (nCurrRegionIllumUpdtVal)
-        nCurrRegionIllumUpdtVal -= 1;
-      // == feedback adj
-      bCurrRegionIsUnstable = fCurrDistThresholdFactor > UNSTABLE_REG_RDIST_MIN || (fCurrMeanRawSegmRes_LT - fCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (fCurrMeanRawSegmRes_ST - fCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN;
-      if (m_oLastFGMask.data[nPxIter] || (std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && nCurrRegionSegmVal))
-        fCurrLearningRate = std::min(fCurrLearningRate + FEEDBACK_T_INCR / (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST)*fCurrDistThresholdVariationFactor), FEEDBACK_T_UPPER);
-      else
-        fCurrLearningRate = std::max(fCurrLearningRate - FEEDBACK_T_DECR*fCurrDistThresholdVariationFactor / std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST), FEEDBACK_T_LOWER);
-      if (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
-        (fCurrDistThresholdVariationFactor) += bBootstrapping ? FEEDBACK_V_INCR * 2 : FEEDBACK_V_INCR;
-      else
-        fCurrDistThresholdVariationFactor = std::max(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR*((bBootstrapping || bCurrRegionIsFlat) ? 2 : m_oLastFGMask.data[nPxIter] ? 0.5f : 1), FEEDBACK_V_DECR);
-      if (fCurrDistThresholdFactor < std::pow(1.0f + std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) * 2, 2))
-        fCurrDistThresholdFactor += FEEDBACK_R_VAR*(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR);
-      else
-        fCurrDistThresholdFactor = std::max(fCurrDistThresholdFactor - FEEDBACK_R_VAR / fCurrDistThresholdVariationFactor, 1.0f);
-      for (size_t c = 0; c < 3; ++c) {
-        anLastIntraDesc[c] = anCurrIntraDesc[c];
-        anLastColor[c] = anCurrColor[c];
-      }
-    }
-  }
-  const bool bRecalcGlobalWords = !(m_nFrameIndex % (nCurrGlobalWordUpdateRate << 5));
-  const bool bUpdateGlobalWords = !(m_nFrameIndex % (nCurrGlobalWordUpdateRate));
-  cv::Mat oLastFGMask_dilated_inverted_downscaled;
-  if (bUpdateGlobalWords)
-    cv::resize(m_oLastFGMask_dilated_inverted, oLastFGMask_dilated_inverted_downscaled, m_oDownSampledFrameSize_GlobalWordLookup, 0, 0, cv::INTER_NEAREST);
-  for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
-    if (bRecalcGlobalWords && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > 0.0f) {
-      m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight = GetGlobalWordWeight(m_apGlobalWordDict[nGlobalWordIdx]);
-      if (m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight < 1.0f) {
-        m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight = 0.0f;
-        m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap = cv::Scalar(0.0f);
-      }
-    }
-    if (bUpdateGlobalWords && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > 0.0f) {
-      cv::accumulateProduct(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, m_oTempGlobalWordWeightDiffFactor, m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, oLastFGMask_dilated_inverted_downscaled);
-      m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight *= 0.9f;
-      cv::blur(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, cv::Size(3, 3), cv::Point(-1, -1), cv::BORDER_REPLICATE);
-    }
-    if (nGlobalWordIdx > 0 && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)
-      std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
-  }
-  if (bUpdateGlobalWords) {
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
-      float fLastGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[0]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-      for (size_t nGlobalWordLUTIdx = 1; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
-        const float fCurrGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
-        if (fCurrGlobalWordLocalWeight > fLastGlobalWordLocalWeight)
-          std::swap(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx], m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx - 1]);
-        else
-          fLastGlobalWordLocalWeight = fCurrGlobalWordLocalWeight;
-      }
-    }
-  }
-  cv::bitwise_xor(oCurrFGMask, m_oLastRawFGMask, m_oCurrRawFGBlinkMask);
-  cv::bitwise_or(m_oCurrRawFGBlinkMask, m_oLastRawFGBlinkMask, m_oBlinksFrame);
-  m_oCurrRawFGBlinkMask.copyTo(m_oLastRawFGBlinkMask);
-  oCurrFGMask.copyTo(m_oLastRawFGMask);
-  cv::morphologyEx(oCurrFGMask, m_oFGMask_PreFlood, cv::MORPH_CLOSE, m_oMorphExStructElement);
-  m_oFGMask_PreFlood.copyTo(m_oFGMask_FloodedHoles);
-  cv::floodFill(m_oFGMask_FloodedHoles, cv::Point(0, 0), UCHAR_MAX);
-  cv::bitwise_not(m_oFGMask_FloodedHoles, m_oFGMask_FloodedHoles);
-  cv::erode(m_oFGMask_PreFlood, m_oFGMask_PreFlood, cv::Mat(), cv::Point(-1, -1), 3);
-  cv::bitwise_or(oCurrFGMask, m_oFGMask_FloodedHoles, oCurrFGMask);
-  cv::bitwise_or(oCurrFGMask, m_oFGMask_PreFlood, oCurrFGMask);
-  cv::medianBlur(oCurrFGMask, m_oLastFGMask, m_nMedianBlurKernelSize);
-  cv::dilate(m_oLastFGMask, m_oLastFGMask_dilated, cv::Mat(), cv::Point(-1, -1), 3);
-  cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
-  cv::bitwise_not(m_oLastFGMask_dilated, m_oLastFGMask_dilated_inverted);
-  cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
-  m_oLastFGMask.copyTo(oCurrFGMask);
-  cv::addWeighted(m_oMeanFinalSegmResFrame_LT, (1.0f - fRollAvgFactor_LT), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_LT, 0, m_oMeanFinalSegmResFrame_LT, CV_32F);
-  cv::addWeighted(m_oMeanFinalSegmResFrame_ST, (1.0f - fRollAvgFactor_ST), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_ST, 0, m_oMeanFinalSegmResFrame_ST, CV_32F);
-  const float fCurrNonFlatRegionRatio = (float)(m_nTotRelevantPxCount - nFlatRegionCount) / m_nTotRelevantPxCount;
-  if (fCurrNonFlatRegionRatio < LBSPDESC_RATIO_MIN && m_fLastNonFlatRegionRatio < LBSPDESC_RATIO_MIN) {
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      if (m_anLBSPThreshold_8bitLUT[t] > cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 4))
-        --m_anLBSPThreshold_8bitLUT[t];
-  }
-  else if (fCurrNonFlatRegionRatio > LBSPDESC_RATIO_MAX && m_fLastNonFlatRegionRatio > LBSPDESC_RATIO_MAX) {
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      if (m_anLBSPThreshold_8bitLUT[t] < cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + UCHAR_MAX*m_fRelLBSPThreshold))
-        ++m_anLBSPThreshold_8bitLUT[t];
-  }
-  m_fLastNonFlatRegionRatio = fCurrNonFlatRegionRatio;
-  cv::resize(oInputImg, m_oDownSampledFrame_MotionAnalysis, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
-  cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_LT, fRollAvgFactor_LT);
-  cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_ST, fRollAvgFactor_ST);
-  const float fCurrMeanL1DistRatio = L1dist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)m_oMeanDownSampledLastDistFrame_ST.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, m_oDownSampledROI_MotionAnalysis.data) / m_nDownSampledROIPxCount;
-  if (!m_bAutoModelResetEnabled && fCurrMeanL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES * 2)
-    m_bAutoModelResetEnabled = true;
-  if (m_bAutoModelResetEnabled || m_bUsingMovingCamera) {
-    if ((m_nFrameIndex%DEFAULT_BOOTSTRAP_WIN_SIZE) == 0) {
-      cv::Mat oCurrBackgroundImg, oDownSampledBackgroundImg;
-      getBackgroundImage(oCurrBackgroundImg);
-      cv::resize(oCurrBackgroundImg, oDownSampledBackgroundImg, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
-      cv::Mat oDownSampledBackgroundImg_32F; oDownSampledBackgroundImg.convertTo(oDownSampledBackgroundImg_32F, CV_32F);
-      const float fCurrModelL1DistRatio = L1dist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)oDownSampledBackgroundImg_32F.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, cv::Mat(m_oDownSampledROI_MotionAnalysis == UCHAR_MAX).data) / m_nDownSampledROIPxCount;
-      const float fCurrModelCDistRatio = cdist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)oDownSampledBackgroundImg_32F.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, cv::Mat(m_oDownSampledROI_MotionAnalysis == UCHAR_MAX).data) / m_nDownSampledROIPxCount;
-      if (m_bUsingMovingCamera && fCurrModelL1DistRatio < FRAMELEVEL_MIN_L1DIST_THRES / 4 && fCurrModelCDistRatio < FRAMELEVEL_MIN_CDIST_THRES / 4) {
-        m_nLocalWordWeightOffset = DEFAULT_LWORD_WEIGHT_OFFSET;
-        m_bUsingMovingCamera = false;
-        refreshModel(1, 1, true);
-      }
-      else if (bBootstrapping && !m_bUsingMovingCamera && (fCurrModelL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES || fCurrModelCDistRatio >= FRAMELEVEL_MIN_CDIST_THRES)) {
-        m_nLocalWordWeightOffset = 5;
-        m_bUsingMovingCamera = true;
-        refreshModel(1, 1, true);
-      }
-    }
-    if (m_nFramesSinceLastReset > DEFAULT_BOOTSTRAP_WIN_SIZE * 2)
-      m_bAutoModelResetEnabled = false;
-    else if (fCurrMeanL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES && m_nModelResetCooldown == 0) {
-      m_nFramesSinceLastReset = 0;
-      refreshModel(m_nLocalWordWeightOffset / 8, 0, true);
-      m_nModelResetCooldown = nCurrSamplesForMovingAvg_ST;
-      m_oUpdateRateFrame = cv::Scalar(1.0f);
-    }
-    else if (!bBootstrapping)
-      ++m_nFramesSinceLastReset;
-  }
-  if (m_nModelResetCooldown > 0)
-    --m_nModelResetCooldown;
-}
-
-void BackgroundSubtractorPAWCS::getBackgroundImage(cv::OutputArray backgroundImage) const { // @@@ add option to reconstruct from gwords?
-  CV_Assert(m_bInitialized);
-  cv::Mat oAvgBGImg = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
-  for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-    const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-    const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
-    const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
-    const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
-    if (m_nImgChannels == 1) {
-      float fTotWeight = 0.0f;
-      float fTotColor = 0.0f;
-      for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-        LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-        float fCurrWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-        fTotColor += (float)pCurrLocalWord->oFeature.anColor[0] * fCurrWeight;
-        fTotWeight += fCurrWeight;
-      }
-      oAvgBGImg.at<float>(nCurrImgCoord_Y, nCurrImgCoord_X) = fTotColor / fTotWeight;
-    }
-    else { //m_nImgChannels==3
-      float fTotWeight = 0.0f;
-      float fTotColor[3] = { 0.0f,0.0f,0.0f };
-      for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
-        LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
-        float fCurrWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
-        for (size_t c = 0; c < 3; ++c)
-          fTotColor[c] += (float)pCurrLocalWord->oFeature.anColor[c] * fCurrWeight;
-        fTotWeight += fCurrWeight;
-      }
-      oAvgBGImg.at<cv::Vec3f>(nCurrImgCoord_Y, nCurrImgCoord_X) = cv::Vec3f(fTotColor[0] / fTotWeight, fTotColor[1] / fTotWeight, fTotColor[2] / fTotWeight);
-    }
-  }
-  oAvgBGImg.convertTo(backgroundImage, CV_8U);
-}
-
-void BackgroundSubtractorPAWCS::getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const {
-  CV_Assert(LBSP_::DESC_SIZE == 2);
-  CV_Assert(m_bInitialized);
-  cv::Mat oAvgBGDesc = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
-  // @@@@@@ TO BE REWRITTEN FOR WORD-BASED RECONSTRUCTION
-  /*for(size_t n=0; n<m_voBGDescSamples.size(); ++n) {
-        for(int y=0; y<m_oImgSize.height; ++y) {
-            for(int x=0; x<m_oImgSize.width; ++x) {
-                const size_t nDescIter = m_voBGDescSamples[n].step.p[0]*y + m_voBGDescSamples[n].step.p[1]*x;
-                const size_t nFloatIter = nDescIter*2;
-                float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data+nFloatIter);
-                const ushort* const oBGDescPtr = (ushort*)(m_voBGDescSamples[n].data+nDescIter);
-                for(size_t c=0; c<m_nImgChannels; ++c)
-                    oAvgBgDescPtr[c] += ((float)oBGDescPtr[c])/m_voBGDescSamples.size();
-            }
-        }
-    }*/
-  oAvgBGDesc.convertTo(backgroundDescImage, CV_16U);
-}
-
-void BackgroundSubtractorPAWCS::CleanupDictionaries() {
-  if (m_aLocalWordList_1ch) {
-    delete[] m_aLocalWordList_1ch;
-    m_aLocalWordList_1ch = nullptr;
-    m_pLocalWordListIter_1ch = nullptr;
-  }
-  else if (m_aLocalWordList_3ch) {
-    delete[] m_aLocalWordList_3ch;
-    m_aLocalWordList_3ch = nullptr;
-    m_pLocalWordListIter_3ch = nullptr;
-  }
-  if (m_apLocalWordDict) {
-    delete[] m_apLocalWordDict;
-    m_apLocalWordDict = nullptr;
-  }
-  if (m_aGlobalWordList_1ch) {
-    delete[] m_aGlobalWordList_1ch;
-    m_aGlobalWordList_1ch = nullptr;
-    m_pGlobalWordListIter_1ch = nullptr;
-  }
-  else if (m_aGlobalWordList_3ch) {
-    delete[] m_aGlobalWordList_3ch;
-    m_aGlobalWordList_3ch = nullptr;
-    m_pGlobalWordListIter_3ch = nullptr;
-  }
-  if (m_apGlobalWordDict) {
-    delete[] m_apGlobalWordDict;
-    m_apGlobalWordDict = nullptr;
-  }
-  if (m_aPxInfoLUT_PAWCS) {
-    for (size_t nPxIter = 0; nPxIter < m_nTotPxCount; ++nPxIter)
-      delete[] m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT;
-    delete[] m_aPxInfoLUT_PAWCS;
-    m_aPxInfoLUT = nullptr;
-    m_aPxInfoLUT_PAWCS = nullptr;
-  }
-  if (m_aPxIdxLUT) {
-    delete[] m_aPxIdxLUT;
-    m_aPxIdxLUT = nullptr;
-  }
-}
-
-float BackgroundSubtractorPAWCS::GetLocalWordWeight(const LocalWordBase* w, size_t nCurrFrame, size_t nOffset) {
-  return (float)(w->nOccurrences) / ((w->nLastOcc - w->nFirstOcc) + (nCurrFrame - w->nLastOcc) * 2 + nOffset);
-}
-
-float BackgroundSubtractorPAWCS::GetGlobalWordWeight(const GlobalWordBase* w) {
-  return (float)cv::sum(w->oSpatioOccMap).val[0];
-}
diff --git a/package_bgs/LBSP/BackgroundSubtractorPAWCS.h b/package_bgs/LBSP/BackgroundSubtractorPAWCS.h
deleted file mode 100644
index cafa48c55a0993ca6ec76024e17ad57f8bfdca78..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorPAWCS.h
+++ /dev/null
@@ -1,169 +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
-
-#include "BackgroundSubtractorLBSP_.h"
-
-//! defines the default value for BackgroundSubtractorLBSP_::m_fRelLBSPThreshold
-#define BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD (0.333f)
-//! defines the default value for BackgroundSubtractorPAWCS::m_nDescDistThresholdOffset
-#define BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET (2)
-//! defines the default value for BackgroundSubtractorPAWCS::m_nMinColorDistThreshold
-#define BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD (20)
-//! defines the default value for BackgroundSubtractorPAWCS::m_nMaxLocalWords and m_nMaxGlobalWords
-#define BGSPAWCS_DEFAULT_MAX_NB_WORDS (50)
-//! defines the default value for BackgroundSubtractorPAWCS::m_nSamplesForMovingAvgs
-#define BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS (100)
-
-/*!
-    Pixel-based Adaptive Word Consensus Segmenter (PAWCS) change detection algorithm.
-
-    Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
-    For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
-
-    For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles et al.,
-    "A Self-Adjusting Approach to Change Detection Based on Background Word Consensus", in WACV 2015.
-
-    This algorithm is currently NOT thread-safe.
- */
-class BackgroundSubtractorPAWCS : public BackgroundSubtractorLBSP_ {
-public:
-  //! full constructor
-  BackgroundSubtractorPAWCS(float fRelLBSPThreshold = BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
-    size_t nDescDistThresholdOffset = BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET,
-    size_t nMinColorDistThreshold = BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD,
-    size_t nMaxNbWords = BGSPAWCS_DEFAULT_MAX_NB_WORDS,
-    size_t nSamplesForMovingAvgs = BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
-  //! default destructor
-  virtual ~BackgroundSubtractorPAWCS();
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
-  //! refreshes all local (+ global) dictionaries based on the last analyzed frame
-  virtual void refreshModel(size_t nBaseOccCount, float fOccDecrFrac, bool bForceFGUpdate = false);
-  //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
-  virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = 0);
-  //! returns a copy of the latest reconstructed background image
-  virtual void getBackgroundImage(cv::OutputArray backgroundImage) const;
-  //! returns a copy of the latest reconstructed background descriptors image
-  virtual void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
-
-protected:
-  template<size_t nChannels>
-  struct ColorLBSPFeature {
-    uchar anColor[nChannels];
-    ushort anDesc[nChannels];
-  };
-  struct LocalWordBase {
-    size_t nFirstOcc;
-    size_t nLastOcc;
-    size_t nOccurrences;
-  };
-  template<typename T>
-  struct LocalWord : LocalWordBase {
-    T oFeature;
-  };
-  struct GlobalWordBase {
-    float fLatestWeight;
-    cv::Mat oSpatioOccMap;
-    uchar nDescBITS;
-  };
-  template<typename T>
-  struct GlobalWord : GlobalWordBase {
-    T oFeature;
-  };
-  typedef LocalWord<ColorLBSPFeature<1>> LocalWord_1ch;
-  typedef LocalWord<ColorLBSPFeature<3>> LocalWord_3ch;
-  typedef GlobalWord<ColorLBSPFeature<1>> GlobalWord_1ch;
-  typedef GlobalWord<ColorLBSPFeature<3>> GlobalWord_3ch;
-  struct PxInfo_PAWCS : PxInfoBase {
-    size_t nGlobalWordMapLookupIdx;
-    GlobalWordBase** apGlobalDictSortLUT;
-  };
-  //! absolute minimal color distance threshold ('R' or 'radius' in the original ViBe paper, used as the default/initial 'R(x)' value here)
-  const size_t m_nMinColorDistThreshold;
-  //! absolute descriptor distance threshold offset
-  const size_t m_nDescDistThresholdOffset;
-  //! max/curr number of local words used to build background submodels (for a single pixel, similar to 'N' in ViBe/PBAS, may vary based on img/channel size)
-  size_t m_nMaxLocalWords, m_nCurrLocalWords;
-  //! max/curr number of global words used to build the global background model (may vary based on img/channel size)
-  size_t m_nMaxGlobalWords, m_nCurrGlobalWords;
-  //! number of samples to use to compute the learning rate of moving averages
-  const size_t m_nSamplesForMovingAvgs;
-  //! last calculated non-flat region ratio
-  float m_fLastNonFlatRegionRatio;
-  //! current kernel size for median blur post-proc filtering
-  int m_nMedianBlurKernelSize;
-  //! specifies the downsampled frame size used for cam motion analysis & gword lookup maps
-  cv::Size m_oDownSampledFrameSize_MotionAnalysis, m_oDownSampledFrameSize_GlobalWordLookup;
-  //! downsampled version of the ROI used for cam motion analysis
-  cv::Mat m_oDownSampledROI_MotionAnalysis;
-  //! total pixel count for the downsampled ROIs
-  size_t m_nDownSampledROIPxCount;
-  //! current local word weight offset
-  size_t m_nLocalWordWeightOffset;
-
-  //! word lists & dictionaries
-  LocalWordBase** m_apLocalWordDict;
-  LocalWord_1ch* m_aLocalWordList_1ch, *m_pLocalWordListIter_1ch;
-  LocalWord_3ch* m_aLocalWordList_3ch, *m_pLocalWordListIter_3ch;
-  GlobalWordBase** m_apGlobalWordDict;
-  GlobalWord_1ch* m_aGlobalWordList_1ch, *m_pGlobalWordListIter_1ch;
-  GlobalWord_3ch* m_aGlobalWordList_3ch, *m_pGlobalWordListIter_3ch;
-  PxInfo_PAWCS* m_aPxInfoLUT_PAWCS;
-
-  //! a lookup map used to keep track of regions where illumination recently changed
-  cv::Mat m_oIllumUpdtRegionMask;
-  //! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe)
-  cv::Mat m_oUpdateRateFrame;
-  //! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds)
-  cv::Mat m_oDistThresholdFrame;
-  //! per-pixel distance threshold variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations)
-  cv::Mat m_oDistThresholdVariationFrame;
-  //! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)')
-  cv::Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST;
-  //! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and force global model resets automatically)
-  cv::Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST;
-  //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
-  cv::Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST;
-  //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
-  cv::Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST;
-  //! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds)
-  cv::Mat m_oUnstableRegionMask;
-  //! per-pixel blink detection map ('Z(x)')
-  cv::Mat m_oBlinksFrame;
-  //! pre-allocated matrix used to downsample the input frame when needed
-  cv::Mat m_oDownSampledFrame_MotionAnalysis;
-  //! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection)
-  cv::Mat m_oLastRawFGMask;
-
-  //! pre-allocated CV_8UC1 matrices used to speed up morph ops
-  cv::Mat m_oFGMask_PreFlood;
-  cv::Mat m_oFGMask_FloodedHoles;
-  cv::Mat m_oLastFGMask_dilated;
-  cv::Mat m_oLastFGMask_dilated_inverted;
-  cv::Mat m_oCurrRawFGBlinkMask;
-  cv::Mat m_oLastRawFGBlinkMask;
-  cv::Mat m_oTempGlobalWordWeightDiffFactor;
-  cv::Mat m_oMorphExStructElement;
-
-  //! internal cleanup function for the dictionary structures
-  void CleanupDictionaries();
-  //! internal weight lookup function for local words
-  static float GetLocalWordWeight(const LocalWordBase* w, size_t nCurrFrame, size_t nOffset);
-  //! internal weight lookup function for global words
-  static float GetGlobalWordWeight(const GlobalWordBase* w);
-};
diff --git a/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.cpp b/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.cpp
deleted file mode 100644
index 3dcc1b86e231fe83fded922cab432aed5fc53862..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.cpp
+++ /dev/null
@@ -1,753 +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 "BackgroundSubtractorSuBSENSE.h"
-#include "DistanceUtils.h"
-#include "RandUtils.h"
-#include <iostream>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <iomanip>
-
-/*
- *
- * Intrinsic parameters for our method are defined here; tuning these for better
- * performance should not be required in most cases -- although improvements in
- * very specific scenarios are always possible.
- *
- */
- //! defines the threshold value(s) used to detect long-term ghosting and trigger the fast edge-based absorption heuristic
-#define GHOSTDET_D_MAX (0.010f) // defines 'negligible' change here
-#define GHOSTDET_S_MIN (0.995f) // defines the required minimum local foreground saturation value
-//! parameter used to scale dynamic distance threshold adjustments ('R(x)')
-#define FEEDBACK_R_VAR (0.01f)
-//! parameters used to adjust the variation step size of 'v(x)'
-#define FEEDBACK_V_INCR  (1.000f)
-#define FEEDBACK_V_DECR  (0.100f)
-//! parameters used to scale dynamic learning rate adjustments  ('T(x)')
-#define FEEDBACK_T_DECR  (0.2500f)
-#define FEEDBACK_T_INCR  (0.5000f)
-#define FEEDBACK_T_LOWER (2.0000f)
-#define FEEDBACK_T_UPPER (256.00f)
-//! parameters used to define 'unstable' regions, based on segm noise/bg dynamics and local dist threshold values
-#define UNSTABLE_REG_RATIO_MIN (0.100f)
-#define UNSTABLE_REG_RDIST_MIN (3.000f)
-//! parameters used to scale the relative LBSP intensity threshold used for internal comparisons
-#define LBSPDESC_NONZERO_RATIO_MIN (0.100f)
-#define LBSPDESC_NONZERO_RATIO_MAX (0.500f)
-//! parameters used to define model reset/learning rate boosts in our frame-level component
-#define FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD  (m_nMinColorDistThreshold/2)
-#define FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO (8)
-
-// local define used to display debug information
-#define DISPLAY_SUBSENSE_DEBUG_INFO 0
-// local define used to specify the default frame size (320x240 = QVGA)
-#define DEFAULT_FRAME_SIZE cv::Size(320,240)
-// local define used to specify the color dist threshold offset used for unstable regions
-#define STAB_COLOR_DIST_OFFSET (m_nMinColorDistThreshold/5)
-// local define used to specify the desc dist threshold offset used for unstable regions
-#define UNSTAB_DESC_DIST_OFFSET (m_nDescDistThresholdOffset)
-
-static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX;
-static const size_t s_nDescMaxDataRange_1ch = LBSP::DESC_SIZE * 8;
-static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch * 3;
-static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch * 3;
-
-BackgroundSubtractorSuBSENSE::BackgroundSubtractorSuBSENSE(float fRelLBSPThreshold
-  , size_t nDescDistThresholdOffset
-  , size_t nMinColorDistThreshold
-  , size_t nBGSamples
-  , size_t nRequiredBGSamples
-  , size_t nSamplesForMovingAvgs)
-  : BackgroundSubtractorLBSP(fRelLBSPThreshold)
-  , m_nMinColorDistThreshold(nMinColorDistThreshold)
-  , m_nDescDistThresholdOffset(nDescDistThresholdOffset)
-  , m_nBGSamples(nBGSamples)
-  , m_nRequiredBGSamples(nRequiredBGSamples)
-  , m_nSamplesForMovingAvgs(nSamplesForMovingAvgs)
-  , m_fLastNonZeroDescRatio(0.0f)
-  , m_bLearningRateScalingEnabled(true)
-  , m_fCurrLearningRateLowerCap(FEEDBACK_T_LOWER)
-  , m_fCurrLearningRateUpperCap(FEEDBACK_T_UPPER)
-  , m_nMedianBlurKernelSize(m_nDefaultMedianBlurKernelSize)
-  , m_bUse3x3Spread(true) {
-  CV_Assert(m_nBGSamples > 0 && m_nRequiredBGSamples <= m_nBGSamples);
-  CV_Assert(m_nMinColorDistThreshold >= STAB_COLOR_DIST_OFFSET);
-}
-
-BackgroundSubtractorSuBSENSE::~BackgroundSubtractorSuBSENSE() {
-  if (m_aPxIdxLUT)
-    delete[] m_aPxIdxLUT;
-  if (m_aPxInfoLUT)
-    delete[] m_aPxInfoLUT;
-}
-
-void BackgroundSubtractorSuBSENSE::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) {
-  // == init
-  CV_Assert(!oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0);
-  CV_Assert(oInitImg.isContinuous());
-  CV_Assert(oInitImg.type() == CV_8UC3 || oInitImg.type() == CV_8UC1);
-  if (oInitImg.type() == CV_8UC3) {
-    std::vector<cv::Mat> voInitImgChannels;
-    cv::split(oInitImg, voInitImgChannels);
-    if (!cv::countNonZero((voInitImgChannels[0] != voInitImgChannels[1]) | (voInitImgChannels[2] != voInitImgChannels[1])))
-      std::cout << std::endl << "\tBackgroundSubtractorSuBSENSE : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance." << std::endl;
-  }
-  cv::Mat oNewBGROI;
-  if (oROI.empty() && (m_oROI.empty() || oROI.size() != oInitImg.size())) {
-    oNewBGROI.create(oInitImg.size(), CV_8UC1);
-    oNewBGROI = cv::Scalar_<uchar>(UCHAR_MAX);
-  }
-  else if (oROI.empty())
-    oNewBGROI = m_oROI;
-  else {
-    CV_Assert(oROI.size() == oInitImg.size() && oROI.type() == CV_8UC1);
-    CV_Assert(cv::countNonZero((oROI < UCHAR_MAX)&(oROI > 0)) == 0);
-    oNewBGROI = oROI.clone();
-    cv::Mat oTempROI;
-    cv::dilate(oNewBGROI, oTempROI, cv::Mat(), cv::Point(-1, -1), LBSP::PATCH_SIZE / 2);
-    cv::bitwise_or(oNewBGROI, oTempROI / 2, oNewBGROI);
-  }
-  const size_t nOrigROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
-  CV_Assert(nOrigROIPxCount > 0);
-  LBSP::validateROI(oNewBGROI);
-  const size_t nFinalROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
-  CV_Assert(nFinalROIPxCount > 0);
-  m_oROI = oNewBGROI;
-  m_oImgSize = oInitImg.size();
-  m_nImgType = oInitImg.type();
-  m_nImgChannels = oInitImg.channels();
-  m_nTotPxCount = m_oImgSize.area();
-  m_nTotRelevantPxCount = nFinalROIPxCount;
-  m_nFrameIndex = 0;
-  m_nFramesSinceLastReset = 0;
-  m_nModelResetCooldown = 0;
-  m_fLastNonZeroDescRatio = 0.0f;
-  const int nTotImgPixels = m_oImgSize.height*m_oImgSize.width;
-  if (nOrigROIPxCount >= m_nTotPxCount / 2 && (int)m_nTotPxCount >= DEFAULT_FRAME_SIZE.area()) {
-    m_bLearningRateScalingEnabled = true;
-    m_bAutoModelResetEnabled = true;
-    m_bUse3x3Spread = !(nTotImgPixels > DEFAULT_FRAME_SIZE.area() * 2);
-    const int nRawMedianBlurKernelSize = std::min((int)floor((float)nTotImgPixels / DEFAULT_FRAME_SIZE.area() + 0.5f) + m_nDefaultMedianBlurKernelSize, 14);
-    m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
-    m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
-    m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
-  }
-  else {
-    m_bLearningRateScalingEnabled = false;
-    m_bAutoModelResetEnabled = false;
-    m_bUse3x3Spread = true;
-    m_nMedianBlurKernelSize = m_nDefaultMedianBlurKernelSize;
-    m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER * 2;
-    m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER * 2;
-  }
-  m_oUpdateRateFrame.create(m_oImgSize, CV_32FC1);
-  m_oUpdateRateFrame = cv::Scalar(m_fCurrLearningRateLowerCap);
-  m_oDistThresholdFrame.create(m_oImgSize, CV_32FC1);
-  m_oDistThresholdFrame = cv::Scalar(1.0f);
-  m_oVariationModulatorFrame.create(m_oImgSize, CV_32FC1);
-  m_oVariationModulatorFrame = cv::Scalar(10.0f); // should always be >= FEEDBACK_V_DECR
-  m_oMeanLastDistFrame.create(m_oImgSize, CV_32FC1);
-  m_oMeanLastDistFrame = cv::Scalar(0.0f);
-  m_oMeanMinDistFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanMinDistFrame_LT = cv::Scalar(0.0f);
-  m_oMeanMinDistFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanMinDistFrame_ST = cv::Scalar(0.0f);
-  m_oDownSampledFrameSize = cv::Size(m_oImgSize.width / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO, m_oImgSize.height / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO);
-  m_oMeanDownSampledLastDistFrame_LT.create(m_oDownSampledFrameSize, CV_32FC((int)m_nImgChannels));
-  m_oMeanDownSampledLastDistFrame_LT = cv::Scalar(0.0f);
-  m_oMeanDownSampledLastDistFrame_ST.create(m_oDownSampledFrameSize, CV_32FC((int)m_nImgChannels));
-  m_oMeanDownSampledLastDistFrame_ST = cv::Scalar(0.0f);
-  m_oMeanRawSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanRawSegmResFrame_LT = cv::Scalar(0.0f);
-  m_oMeanRawSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanRawSegmResFrame_ST = cv::Scalar(0.0f);
-  m_oMeanFinalSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
-  m_oMeanFinalSegmResFrame_LT = cv::Scalar(0.0f);
-  m_oMeanFinalSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
-  m_oMeanFinalSegmResFrame_ST = cv::Scalar(0.0f);
-  m_oUnstableRegionMask.create(m_oImgSize, CV_8UC1);
-  m_oUnstableRegionMask = cv::Scalar_<uchar>(0);
-  m_oBlinksFrame.create(m_oImgSize, CV_8UC1);
-  m_oBlinksFrame = cv::Scalar_<uchar>(0);
-  m_oDownSampledFrame_MotionAnalysis.create(m_oDownSampledFrameSize, CV_8UC((int)m_nImgChannels));
-  m_oDownSampledFrame_MotionAnalysis = cv::Scalar_<uchar>::all(0);
-  m_oLastColorFrame.create(m_oImgSize, CV_8UC((int)m_nImgChannels));
-  m_oLastColorFrame = cv::Scalar_<uchar>::all(0);
-  m_oLastDescFrame.create(m_oImgSize, CV_16UC((int)m_nImgChannels));
-  m_oLastDescFrame = cv::Scalar_<ushort>::all(0);
-  m_oLastRawFGMask.create(m_oImgSize, CV_8UC1);
-  m_oLastRawFGMask = cv::Scalar_<uchar>(0);
-  m_oLastFGMask.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask = cv::Scalar_<uchar>(0);
-  m_oLastFGMask_dilated.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask_dilated = cv::Scalar_<uchar>(0);
-  m_oLastFGMask_dilated_inverted.create(m_oImgSize, CV_8UC1);
-  m_oLastFGMask_dilated_inverted = cv::Scalar_<uchar>(0);
-  m_oFGMask_FloodedHoles.create(m_oImgSize, CV_8UC1);
-  m_oFGMask_FloodedHoles = cv::Scalar_<uchar>(0);
-  m_oFGMask_PreFlood.create(m_oImgSize, CV_8UC1);
-  m_oFGMask_PreFlood = cv::Scalar_<uchar>(0);
-  m_oCurrRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
-  m_oCurrRawFGBlinkMask = cv::Scalar_<uchar>(0);
-  m_oLastRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
-  m_oLastRawFGBlinkMask = cv::Scalar_<uchar>(0);
-  m_voBGColorSamples.resize(m_nBGSamples);
-  m_voBGDescSamples.resize(m_nBGSamples);
-  for (size_t s = 0; s < m_nBGSamples; ++s) {
-    m_voBGColorSamples[s].create(m_oImgSize, CV_8UC((int)m_nImgChannels));
-    m_voBGColorSamples[s] = cv::Scalar_<uchar>::all(0);
-    m_voBGDescSamples[s].create(m_oImgSize, CV_16UC((int)m_nImgChannels));
-    m_voBGDescSamples[s] = cv::Scalar_<ushort>::all(0);
-  }
-  if (m_aPxIdxLUT)
-    delete[] m_aPxIdxLUT;
-  if (m_aPxInfoLUT)
-    delete[] m_aPxInfoLUT;
-  m_aPxIdxLUT = new size_t[m_nTotRelevantPxCount];
-  m_aPxInfoLUT = new PxInfoBase[m_nTotPxCount];
-  if (m_nImgChannels == 1) {
-    CV_Assert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width && m_oLastColorFrame.step.p[1] == 1);
-    CV_Assert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 3);
-    for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
-      if (m_oROI.data[nPxIter]) {
-        m_aPxIdxLUT[nModelIter] = nPxIter;
-        m_aPxInfoLUT[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
-        m_aPxInfoLUT[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
-        m_aPxInfoLUT[nPxIter].nModelIdx = nModelIter;
-        m_oLastColorFrame.data[nPxIter] = oInitImg.data[nPxIter];
-        const size_t nDescIter = nPxIter * 2;
-        LBSP::computeGrayscaleDescriptor(oInitImg, oInitImg.data[nPxIter], m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxIter]], *((ushort*)(m_oLastDescFrame.data + nDescIter)));
-        ++nModelIter;
-      }
-    }
-  }
-  else { //m_nImgChannels==3
-    CV_Assert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width * 3 && m_oLastColorFrame.step.p[1] == 3);
-    CV_Assert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold);
-    for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
-      if (m_oROI.data[nPxIter]) {
-        m_aPxIdxLUT[nModelIter] = nPxIter;
-        m_aPxInfoLUT[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
-        m_aPxInfoLUT[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
-        m_aPxInfoLUT[nPxIter].nModelIdx = nModelIter;
-        const size_t nPxRGBIter = nPxIter * 3;
-        const size_t nDescRGBIter = nPxRGBIter * 2;
-        for (size_t c = 0; c < 3; ++c) {
-          m_oLastColorFrame.data[nPxRGBIter + c] = oInitImg.data[nPxRGBIter + c];
-          LBSP::computeSingleRGBDescriptor(oInitImg, oInitImg.data[nPxRGBIter + c], m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxRGBIter + c]], ((ushort*)(m_oLastDescFrame.data + nDescRGBIter))[c]);
-        }
-        ++nModelIter;
-      }
-    }
-  }
-  m_bInitialized = true;
-  refreshModel(1.0f);
-}
-
-void BackgroundSubtractorSuBSENSE::refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate) {
-  // == refresh
-  CV_Assert(m_bInitialized);
-  CV_Assert(fSamplesRefreshFrac > 0.0f && fSamplesRefreshFrac <= 1.0f);
-  const size_t nModelsToRefresh = fSamplesRefreshFrac < 1.0f ? (size_t)(fSamplesRefreshFrac*m_nBGSamples) : m_nBGSamples;
-  const size_t nRefreshStartPos = fSamplesRefreshFrac < 1.0f ? rand() % m_nBGSamples : 0;
-  if (m_nImgChannels == 1) {
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      if (bForceFGUpdate || !m_oLastFGMask.data[nPxIter]) {
-        for (size_t nCurrModelIdx = nRefreshStartPos; nCurrModelIdx < nRefreshStartPos + nModelsToRefresh; ++nCurrModelIdx) {
-          int nSampleImgCoord_Y, nSampleImgCoord_X;
-          getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-          const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-          if (bForceFGUpdate || !m_oLastFGMask.data[nSamplePxIdx]) {
-            const size_t nCurrRealModelIdx = nCurrModelIdx%m_nBGSamples;
-            m_voBGColorSamples[nCurrRealModelIdx].data[nPxIter] = m_oLastColorFrame.data[nSamplePxIdx];
-            *((ushort*)(m_voBGDescSamples[nCurrRealModelIdx].data + nPxIter * 2)) = *((ushort*)(m_oLastDescFrame.data + nSamplePxIdx * 2));
-          }
-        }
-      }
-    }
-  }
-  else { //m_nImgChannels==3
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      if (bForceFGUpdate || !m_oLastFGMask.data[nPxIter]) {
-        for (size_t nCurrModelIdx = nRefreshStartPos; nCurrModelIdx < nRefreshStartPos + nModelsToRefresh; ++nCurrModelIdx) {
-          int nSampleImgCoord_Y, nSampleImgCoord_X;
-          getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-          const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-          if (bForceFGUpdate || !m_oLastFGMask.data[nSamplePxIdx]) {
-            const size_t nCurrRealModelIdx = nCurrModelIdx%m_nBGSamples;
-            for (size_t c = 0; c < 3; ++c) {
-              m_voBGColorSamples[nCurrRealModelIdx].data[nPxIter * 3 + c] = m_oLastColorFrame.data[nSamplePxIdx * 3 + c];
-              *((ushort*)(m_voBGDescSamples[nCurrRealModelIdx].data + (nPxIter * 3 + c) * 2)) = *((ushort*)(m_oLastDescFrame.data + (nSamplePxIdx * 3 + c) * 2));
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-void BackgroundSubtractorSuBSENSE::apply(cv::InputArray _image, cv::OutputArray _fgmask, double learningRateOverride) {
-  // == process
-  CV_Assert(m_bInitialized);
-  cv::Mat oInputImg = _image.getMat();
-  CV_Assert(oInputImg.type() == m_nImgType && oInputImg.size() == m_oImgSize);
-  CV_Assert(oInputImg.isContinuous());
-  _fgmask.create(m_oImgSize, CV_8UC1);
-  cv::Mat oCurrFGMask = _fgmask.getMat();
-  memset(oCurrFGMask.data, 0, oCurrFGMask.cols*oCurrFGMask.rows);
-  size_t nNonZeroDescCount = 0;
-  const float fRollAvgFactor_LT = 1.0f / std::min(++m_nFrameIndex, m_nSamplesForMovingAvgs);
-  const float fRollAvgFactor_ST = 1.0f / std::min(m_nFrameIndex, m_nSamplesForMovingAvgs / 4);
-  if (m_nImgChannels == 1) {
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      const size_t nDescIter = nPxIter * 2;
-      const size_t nFloatIter = nPxIter * 4;
-      const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
-      const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
-      const uchar nCurrColor = oInputImg.data[nPxIter];
-      size_t nMinDescDist = s_nDescMaxDataRange_1ch;
-      size_t nMinSumDist = s_nColorMaxDataRange_1ch;
-      float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data + nFloatIter);
-      float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data + nFloatIter);
-      float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data + nFloatIter));
-      float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data + nFloatIter));
-      float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data + nFloatIter));
-      float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data + nFloatIter));
-      float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter));
-      float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter));
-      float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter));
-      float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter));
-      ushort& nLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nDescIter));
-      uchar& nLastColor = m_oLastColorFrame.data[nPxIter];
-      const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold) - ((!m_oUnstableRegionMask.data[nPxIter])*STAB_COLOR_DIST_OFFSET)) / 2;
-      const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(*pfCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (m_oUnstableRegionMask.data[nPxIter] * UNSTAB_DESC_DIST_OFFSET);
-      ushort nCurrInterDesc, nCurrIntraDesc;
-      LBSP::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nCurrIntraDesc);
-      m_oUnstableRegionMask.data[nPxIter] = ((*pfCurrDistThresholdFactor) > UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN) ? 1 : 0;
-      size_t nGoodSamplesCount = 0, nSampleIdx = 0;
-      while (nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples) {
-        const uchar& nBGColor = m_voBGColorSamples[nSampleIdx].data[nPxIter];
-        {
-          const size_t nColorDist = L1dist(nCurrColor, nBGColor);
-          if (nColorDist > nCurrColorDistThreshold)
-            goto failedcheck1ch;
-          const ushort& nBGIntraDesc = *((ushort*)(m_voBGDescSamples[nSampleIdx].data + nDescIter));
-          const size_t nIntraDescDist = hdist(nCurrIntraDesc, nBGIntraDesc);
-          LBSP::computeGrayscaleDescriptor(oInputImg, nBGColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nBGColor], nCurrInterDesc);
-          const size_t nInterDescDist = hdist(nCurrInterDesc, nBGIntraDesc);
-          const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
-          if (nDescDist > nCurrDescDistThreshold)
-            goto failedcheck1ch;
-          const size_t nSumDist = std::min((nDescDist / 4)*(s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch) + nColorDist, s_nColorMaxDataRange_1ch);
-          if (nSumDist > nCurrColorDistThreshold)
-            goto failedcheck1ch;
-          if (nMinDescDist > nDescDist)
-            nMinDescDist = nDescDist;
-          if (nMinSumDist > nSumDist)
-            nMinSumDist = nSumDist;
-          nGoodSamplesCount++;
-        }
-      failedcheck1ch:
-        nSampleIdx++;
-      }
-      const float fNormalizedLastDist = ((float)L1dist(nLastColor, nCurrColor) / s_nColorMaxDataRange_1ch + (float)hdist(nLastIntraDesc, nCurrIntraDesc) / s_nDescMaxDataRange_1ch) / 2;
-      *pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f - fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST;
-      if (nGoodSamplesCount < m_nRequiredBGSamples) {
-        // == foreground
-        const float fNormalizedMinDist = std::min(1.0f, ((float)nMinSumDist / s_nColorMaxDataRange_1ch + (float)nMinDescDist / s_nDescMaxDataRange_1ch) / 2 + (float)(m_nRequiredBGSamples - nGoodSamplesCount) / m_nRequiredBGSamples);
-        *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
-        *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
-        oCurrFGMask.data[nPxIter] = UCHAR_MAX;
-        if (m_nModelResetCooldown && (rand() % (size_t)FEEDBACK_T_LOWER) == 0) {
-          const size_t s_rand = rand() % m_nBGSamples;
-          *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIter)) = nCurrIntraDesc;
-          m_voBGColorSamples[s_rand].data[nPxIter] = nCurrColor;
-        }
-      }
-      else {
-        // == background
-        const float fNormalizedMinDist = ((float)nMinSumDist / s_nColorMaxDataRange_1ch + (float)nMinDescDist / s_nDescMaxDataRange_1ch) / 2;
-        *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT);
-        *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST);
-        const size_t nLearningRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : (size_t)ceil(*pfCurrLearningRate);
-        if ((rand() % nLearningRate) == 0) {
-          const size_t s_rand = rand() % m_nBGSamples;
-          *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIter)) = nCurrIntraDesc;
-          m_voBGColorSamples[s_rand].data[nPxIter] = nCurrColor;
-        }
-        int nSampleImgCoord_Y, nSampleImgCoord_X;
-        const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[nPxIter];
-        if (bCurrUsing3x3Spread)
-          getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-        else
-          getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-        const size_t n_rand = rand();
-        const size_t idx_rand_uchar = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-        const size_t idx_rand_flt32 = idx_rand_uchar * 4;
-        const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data + idx_rand_flt32));
-        const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32));
-        if ((n_rand % (bCurrUsing3x3Spread ? nLearningRate : (nLearningRate / 2 + 1))) == 0
-          || (fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX && (n_rand % ((size_t)m_fCurrLearningRateLowerCap)) == 0)) {
-          const size_t idx_rand_ushrt = idx_rand_uchar * 2;
-          const size_t s_rand = rand() % m_nBGSamples;
-          *((ushort*)(m_voBGDescSamples[s_rand].data + idx_rand_ushrt)) = nCurrIntraDesc;
-          m_voBGColorSamples[s_rand].data[idx_rand_uchar] = nCurrColor;
-        }
-      }
-      if (m_oLastFGMask.data[nPxIter] || (std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[nPxIter])) {
-        if ((*pfCurrLearningRate) < m_fCurrLearningRateUpperCap)
-          *pfCurrLearningRate += FEEDBACK_T_INCR / (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor));
-      }
-      else if ((*pfCurrLearningRate) > m_fCurrLearningRateLowerCap)
-        *pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor) / std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST);
-      if ((*pfCurrLearningRate) < m_fCurrLearningRateLowerCap)
-        *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
-      else if ((*pfCurrLearningRate) > m_fCurrLearningRateUpperCap)
-        *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
-      if (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
-        (*pfCurrVariationFactor) += FEEDBACK_V_INCR;
-      else if ((*pfCurrVariationFactor) > FEEDBACK_V_DECR) {
-        (*pfCurrVariationFactor) -= m_oLastFGMask.data[nPxIter] ? FEEDBACK_V_DECR / 4 : m_oUnstableRegionMask.data[nPxIter] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
-        if ((*pfCurrVariationFactor) < FEEDBACK_V_DECR)
-          (*pfCurrVariationFactor) = FEEDBACK_V_DECR;
-      }
-      if ((*pfCurrDistThresholdFactor) < std::pow(1.0f + std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) * 2, 2))
-        (*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor - FEEDBACK_V_DECR);
-      else {
-        (*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR / (*pfCurrVariationFactor);
-        if ((*pfCurrDistThresholdFactor) < 1.0f)
-          (*pfCurrDistThresholdFactor) = 1.0f;
-      }
-      if (popcount(nCurrIntraDesc) >= 2)
-        ++nNonZeroDescCount;
-      nLastIntraDesc = nCurrIntraDesc;
-      nLastColor = nCurrColor;
-    }
-  }
-  else { //m_nImgChannels==3
-    for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
-      const size_t nPxIter = m_aPxIdxLUT[nModelIter];
-      const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
-      const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
-      const size_t nPxIterRGB = nPxIter * 3;
-      const size_t nDescIterRGB = nPxIterRGB * 2;
-      const size_t nFloatIter = nPxIter * 4;
-      const uchar* const anCurrColor = oInputImg.data + nPxIterRGB;
-      size_t nMinTotDescDist = s_nDescMaxDataRange_3ch;
-      size_t nMinTotSumDist = s_nColorMaxDataRange_3ch;
-      float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data + nFloatIter);
-      float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data + nFloatIter);
-      float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data + nFloatIter));
-      float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data + nFloatIter));
-      float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data + nFloatIter));
-      float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data + nFloatIter));
-      float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter));
-      float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter));
-      float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter));
-      float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter));
-      ushort* anLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nDescIterRGB));
-      uchar* anLastColor = m_oLastColorFrame.data + nPxIterRGB;
-      const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold) - ((!m_oUnstableRegionMask.data[nPxIter])*STAB_COLOR_DIST_OFFSET));
-      const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(*pfCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (m_oUnstableRegionMask.data[nPxIter] * UNSTAB_DESC_DIST_OFFSET);
-      const size_t nCurrTotColorDistThreshold = nCurrColorDistThreshold * 3;
-      const size_t nCurrTotDescDistThreshold = nCurrDescDistThreshold * 3;
-      const size_t nCurrSCColorDistThreshold = nCurrTotColorDistThreshold / 2;
-      ushort anCurrInterDesc[3], anCurrIntraDesc[3];
-      const size_t anCurrIntraLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]] };
-      LBSP::computeRGBDescriptor(oInputImg, anCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrIntraLBSPThresholds, anCurrIntraDesc);
-      m_oUnstableRegionMask.data[nPxIter] = ((*pfCurrDistThresholdFactor) > UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN) ? 1 : 0;
-      size_t nGoodSamplesCount = 0, nSampleIdx = 0;
-      while (nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples) {
-        const ushort* const anBGIntraDesc = (ushort*)(m_voBGDescSamples[nSampleIdx].data + nDescIterRGB);
-        const uchar* const anBGColor = m_voBGColorSamples[nSampleIdx].data + nPxIterRGB;
-        size_t nTotDescDist = 0;
-        size_t nTotSumDist = 0;
-        for (size_t c = 0; c < 3; ++c) {
-          const size_t nColorDist = L1dist(anCurrColor[c], anBGColor[c]);
-          if (nColorDist > nCurrSCColorDistThreshold)
-            goto failedcheck3ch;
-          const size_t nIntraDescDist = hdist(anCurrIntraDesc[c], anBGIntraDesc[c]);
-          LBSP::computeSingleRGBDescriptor(oInputImg, anBGColor[c], nCurrImgCoord_X, nCurrImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[anBGColor[c]], anCurrInterDesc[c]);
-          const size_t nInterDescDist = hdist(anCurrInterDesc[c], anBGIntraDesc[c]);
-          const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
-          const size_t nSumDist = std::min((nDescDist / 2)*(s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch) + nColorDist, s_nColorMaxDataRange_1ch);
-          if (nSumDist > nCurrSCColorDistThreshold)
-            goto failedcheck3ch;
-          nTotDescDist += nDescDist;
-          nTotSumDist += nSumDist;
-        }
-        if (nTotDescDist > nCurrTotDescDistThreshold || nTotSumDist > nCurrTotColorDistThreshold)
-          goto failedcheck3ch;
-        if (nMinTotDescDist > nTotDescDist)
-          nMinTotDescDist = nTotDescDist;
-        if (nMinTotSumDist > nTotSumDist)
-          nMinTotSumDist = nTotSumDist;
-        nGoodSamplesCount++;
-      failedcheck3ch:
-        nSampleIdx++;
-      }
-      const float fNormalizedLastDist = ((float)L1dist<3>(anLastColor, anCurrColor) / s_nColorMaxDataRange_3ch + (float)hdist<3>(anLastIntraDesc, anCurrIntraDesc) / s_nDescMaxDataRange_3ch) / 2;
-      *pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f - fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST;
-      if (nGoodSamplesCount < m_nRequiredBGSamples) {
-        // == foreground
-        const float fNormalizedMinDist = std::min(1.0f, ((float)nMinTotSumDist / s_nColorMaxDataRange_3ch + (float)nMinTotDescDist / s_nDescMaxDataRange_3ch) / 2 + (float)(m_nRequiredBGSamples - nGoodSamplesCount) / m_nRequiredBGSamples);
-        *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
-        *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
-        oCurrFGMask.data[nPxIter] = UCHAR_MAX;
-        if (m_nModelResetCooldown && (rand() % (size_t)FEEDBACK_T_LOWER) == 0) {
-          const size_t s_rand = rand() % m_nBGSamples;
-          for (size_t c = 0; c < 3; ++c) {
-            *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIterRGB + 2 * c)) = anCurrIntraDesc[c];
-            *(m_voBGColorSamples[s_rand].data + nPxIterRGB + c) = anCurrColor[c];
-          }
-        }
-      }
-      else {
-        // == background
-        const float fNormalizedMinDist = ((float)nMinTotSumDist / s_nColorMaxDataRange_3ch + (float)nMinTotDescDist / s_nDescMaxDataRange_3ch) / 2;
-        *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
-        *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
-        *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT);
-        *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST);
-        const size_t nLearningRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : (size_t)ceil(*pfCurrLearningRate);
-        if ((rand() % nLearningRate) == 0) {
-          const size_t s_rand = rand() % m_nBGSamples;
-          for (size_t c = 0; c < 3; ++c) {
-            *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIterRGB + 2 * c)) = anCurrIntraDesc[c];
-            *(m_voBGColorSamples[s_rand].data + nPxIterRGB + c) = anCurrColor[c];
-          }
-        }
-        int nSampleImgCoord_Y, nSampleImgCoord_X;
-        const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[nPxIter];
-        if (bCurrUsing3x3Spread)
-          getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-        else
-          getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
-        const size_t n_rand = rand();
-        const size_t idx_rand_uchar = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
-        const size_t idx_rand_flt32 = idx_rand_uchar * 4;
-        const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data + idx_rand_flt32));
-        const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32));
-        if ((n_rand % (bCurrUsing3x3Spread ? nLearningRate : (nLearningRate / 2 + 1))) == 0
-          || (fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX && (n_rand % ((size_t)m_fCurrLearningRateLowerCap)) == 0)) {
-          const size_t idx_rand_uchar_rgb = idx_rand_uchar * 3;
-          const size_t idx_rand_ushrt_rgb = idx_rand_uchar_rgb * 2;
-          const size_t s_rand = rand() % m_nBGSamples;
-          for (size_t c = 0; c < 3; ++c) {
-            *((ushort*)(m_voBGDescSamples[s_rand].data + idx_rand_ushrt_rgb + 2 * c)) = anCurrIntraDesc[c];
-            *(m_voBGColorSamples[s_rand].data + idx_rand_uchar_rgb + c) = anCurrColor[c];
-          }
-        }
-      }
-      if (m_oLastFGMask.data[nPxIter] || (std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[nPxIter])) {
-        if ((*pfCurrLearningRate) < m_fCurrLearningRateUpperCap)
-          *pfCurrLearningRate += FEEDBACK_T_INCR / (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor));
-      }
-      else if ((*pfCurrLearningRate) > m_fCurrLearningRateLowerCap)
-        *pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor) / std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST);
-      if ((*pfCurrLearningRate) < m_fCurrLearningRateLowerCap)
-        *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
-      else if ((*pfCurrLearningRate) > m_fCurrLearningRateUpperCap)
-        *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
-      if (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
-        (*pfCurrVariationFactor) += FEEDBACK_V_INCR;
-      else if ((*pfCurrVariationFactor) > FEEDBACK_V_DECR) {
-        (*pfCurrVariationFactor) -= m_oLastFGMask.data[nPxIter] ? FEEDBACK_V_DECR / 4 : m_oUnstableRegionMask.data[nPxIter] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
-        if ((*pfCurrVariationFactor) < FEEDBACK_V_DECR)
-          (*pfCurrVariationFactor) = FEEDBACK_V_DECR;
-      }
-      if ((*pfCurrDistThresholdFactor) < std::pow(1.0f + std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) * 2, 2))
-        (*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor - FEEDBACK_V_DECR);
-      else {
-        (*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR / (*pfCurrVariationFactor);
-        if ((*pfCurrDistThresholdFactor) < 1.0f)
-          (*pfCurrDistThresholdFactor) = 1.0f;
-      }
-      if (popcount<3>(anCurrIntraDesc) >= 4)
-        ++nNonZeroDescCount;
-      for (size_t c = 0; c < 3; ++c) {
-        anLastIntraDesc[c] = anCurrIntraDesc[c];
-        anLastColor[c] = anCurrColor[c];
-      }
-    }
-  }
-#if DISPLAY_SUBSENSE_DEBUG_INFO
-  std::cout << std::endl;
-  cv::Point dbgpt(nDebugCoordX, nDebugCoordY);
-  cv::Mat oMeanMinDistFrameNormalized; m_oMeanMinDistFrame_ST.copyTo(oMeanMinDistFrameNormalized);
-  cv::circle(oMeanMinDistFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oMeanMinDistFrameNormalized, oMeanMinDistFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("d_min(x)", oMeanMinDistFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "  d_min(" << dbgpt << ") = " << m_oMeanMinDistFrame_ST.at<float>(dbgpt) << std::endl;
-  cv::Mat oMeanLastDistFrameNormalized; m_oMeanLastDistFrame.copyTo(oMeanLastDistFrameNormalized);
-  cv::circle(oMeanLastDistFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oMeanLastDistFrameNormalized, oMeanLastDistFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("d_last(x)", oMeanLastDistFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << " d_last(" << dbgpt << ") = " << m_oMeanLastDistFrame.at<float>(dbgpt) << std::endl;
-  cv::Mat oMeanRawSegmResFrameNormalized; m_oMeanRawSegmResFrame_ST.copyTo(oMeanRawSegmResFrameNormalized);
-  cv::circle(oMeanRawSegmResFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oMeanRawSegmResFrameNormalized, oMeanRawSegmResFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("s_avg(x)", oMeanRawSegmResFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "  s_avg(" << dbgpt << ") = " << m_oMeanRawSegmResFrame_ST.at<float>(dbgpt) << std::endl;
-  cv::Mat oMeanFinalSegmResFrameNormalized; m_oMeanFinalSegmResFrame_ST.copyTo(oMeanFinalSegmResFrameNormalized);
-  cv::circle(oMeanFinalSegmResFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oMeanFinalSegmResFrameNormalized, oMeanFinalSegmResFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("z_avg(x)", oMeanFinalSegmResFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "  z_avg(" << dbgpt << ") = " << m_oMeanFinalSegmResFrame_ST.at<float>(dbgpt) << std::endl;
-  cv::Mat oDistThresholdFrameNormalized; m_oDistThresholdFrame.convertTo(oDistThresholdFrameNormalized, CV_32FC1, 0.25f, -0.25f);
-  cv::circle(oDistThresholdFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oDistThresholdFrameNormalized, oDistThresholdFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("r(x)", oDistThresholdFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "      r(" << dbgpt << ") = " << m_oDistThresholdFrame.at<float>(dbgpt) << std::endl;
-  cv::Mat oVariationModulatorFrameNormalized; cv::normalize(m_oVariationModulatorFrame, oVariationModulatorFrameNormalized, 0, 255, cv::NORM_MINMAX, CV_8UC1);
-  cv::circle(oVariationModulatorFrameNormalized, dbgpt, 5, cv::Scalar(255));
-  cv::resize(oVariationModulatorFrameNormalized, oVariationModulatorFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("v(x)", oVariationModulatorFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "      v(" << dbgpt << ") = " << m_oVariationModulatorFrame.at<float>(dbgpt) << std::endl;
-  cv::Mat oUpdateRateFrameNormalized; m_oUpdateRateFrame.convertTo(oUpdateRateFrameNormalized, CV_32FC1, 1.0f / FEEDBACK_T_UPPER, -FEEDBACK_T_LOWER / FEEDBACK_T_UPPER);
-  cv::circle(oUpdateRateFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
-  cv::resize(oUpdateRateFrameNormalized, oUpdateRateFrameNormalized, DEFAULT_FRAME_SIZE);
-  cv::imshow("t(x)", oUpdateRateFrameNormalized);
-  std::cout << std::fixed << std::setprecision(5) << "      t(" << dbgpt << ") = " << m_oUpdateRateFrame.at<float>(dbgpt) << std::endl;
-#endif //DISPLAY_SUBSENSE_DEBUG_INFO
-  cv::bitwise_xor(oCurrFGMask, m_oLastRawFGMask, m_oCurrRawFGBlinkMask);
-  cv::bitwise_or(m_oCurrRawFGBlinkMask, m_oLastRawFGBlinkMask, m_oBlinksFrame);
-  m_oCurrRawFGBlinkMask.copyTo(m_oLastRawFGBlinkMask);
-  oCurrFGMask.copyTo(m_oLastRawFGMask);
-  cv::morphologyEx(oCurrFGMask, m_oFGMask_PreFlood, cv::MORPH_CLOSE, cv::Mat());
-  m_oFGMask_PreFlood.copyTo(m_oFGMask_FloodedHoles);
-  cv::floodFill(m_oFGMask_FloodedHoles, cv::Point(0, 0), UCHAR_MAX);
-  cv::bitwise_not(m_oFGMask_FloodedHoles, m_oFGMask_FloodedHoles);
-  cv::erode(m_oFGMask_PreFlood, m_oFGMask_PreFlood, cv::Mat(), cv::Point(-1, -1), 3);
-  cv::bitwise_or(oCurrFGMask, m_oFGMask_FloodedHoles, oCurrFGMask);
-  cv::bitwise_or(oCurrFGMask, m_oFGMask_PreFlood, oCurrFGMask);
-  cv::medianBlur(oCurrFGMask, m_oLastFGMask, m_nMedianBlurKernelSize);
-  cv::dilate(m_oLastFGMask, m_oLastFGMask_dilated, cv::Mat(), cv::Point(-1, -1), 3);
-  cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
-  cv::bitwise_not(m_oLastFGMask_dilated, m_oLastFGMask_dilated_inverted);
-  cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
-  m_oLastFGMask.copyTo(oCurrFGMask);
-  cv::addWeighted(m_oMeanFinalSegmResFrame_LT, (1.0f - fRollAvgFactor_LT), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_LT, 0, m_oMeanFinalSegmResFrame_LT, CV_32F);
-  cv::addWeighted(m_oMeanFinalSegmResFrame_ST, (1.0f - fRollAvgFactor_ST), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_ST, 0, m_oMeanFinalSegmResFrame_ST, CV_32F);
-  const float fCurrNonZeroDescRatio = (float)nNonZeroDescCount / m_nTotRelevantPxCount;
-  if (fCurrNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN && m_fLastNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN) {
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      if (m_anLBSPThreshold_8bitLUT[t] > cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + ceil(t*m_fRelLBSPThreshold / 4)))
-        --m_anLBSPThreshold_8bitLUT[t];
-  }
-  else if (fCurrNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX && m_fLastNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX) {
-    for (size_t t = 0; t <= UCHAR_MAX; ++t)
-      if (m_anLBSPThreshold_8bitLUT[t] < cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + UCHAR_MAX*m_fRelLBSPThreshold))
-        ++m_anLBSPThreshold_8bitLUT[t];
-  }
-  m_fLastNonZeroDescRatio = fCurrNonZeroDescRatio;
-  if (m_bLearningRateScalingEnabled) {
-    cv::resize(oInputImg, m_oDownSampledFrame_MotionAnalysis, m_oDownSampledFrameSize, 0, 0, cv::INTER_AREA);
-    cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_LT, fRollAvgFactor_LT);
-    cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_ST, fRollAvgFactor_ST);
-    size_t nTotColorDiff = 0;
-    for (int i = 0; i < m_oMeanDownSampledLastDistFrame_ST.rows; ++i) {
-      const size_t idx1 = m_oMeanDownSampledLastDistFrame_ST.step.p[0] * i;
-      for (int j = 0; j < m_oMeanDownSampledLastDistFrame_ST.cols; ++j) {
-        const size_t idx2 = idx1 + m_oMeanDownSampledLastDistFrame_ST.step.p[1] * j;
-        nTotColorDiff += (m_nImgChannels == 1) ?
-          (size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2))) / 2
-          :  //(m_nImgChannels==3)
-          std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2))),
-            std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 4)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 4))),
-            (size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 8)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 8)))));
-      }
-    }
-    const float fCurrColorDiffRatio = (float)nTotColorDiff / (m_oMeanDownSampledLastDistFrame_ST.rows*m_oMeanDownSampledLastDistFrame_ST.cols);
-    if (m_bAutoModelResetEnabled) {
-      if (m_nFramesSinceLastReset > 1000)
-        m_bAutoModelResetEnabled = false;
-      else if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD && m_nModelResetCooldown == 0) {
-        m_nFramesSinceLastReset = 0;
-        refreshModel(0.1f); // reset 10% of the bg model
-        m_nModelResetCooldown = m_nSamplesForMovingAvgs / 4;
-        m_oUpdateRateFrame = cv::Scalar(1.0f);
-      }
-      else
-        ++m_nFramesSinceLastReset;
-    }
-    else if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD * 2) {
-      m_nFramesSinceLastReset = 0;
-      m_bAutoModelResetEnabled = true;
-    }
-    if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD / 2) {
-      m_fCurrLearningRateLowerCap = (float)std::max((int)FEEDBACK_T_LOWER >> (int)(fCurrColorDiffRatio / 2), 1);
-      m_fCurrLearningRateUpperCap = (float)std::max((int)FEEDBACK_T_UPPER >> (int)(fCurrColorDiffRatio / 2), 1);
-    }
-    else {
-      m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
-      m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
-    }
-    if (m_nModelResetCooldown > 0)
-      --m_nModelResetCooldown;
-  }
-}
-
-void BackgroundSubtractorSuBSENSE::getBackgroundImage(cv::OutputArray backgroundImage) const {
-  CV_Assert(m_bInitialized);
-  cv::Mat oAvgBGImg = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
-  for (size_t s = 0; s < m_nBGSamples; ++s) {
-    for (int y = 0; y < m_oImgSize.height; ++y) {
-      for (int x = 0; x < m_oImgSize.width; ++x) {
-        const size_t idx_nimg = m_voBGColorSamples[s].step.p[0] * y + m_voBGColorSamples[s].step.p[1] * x;
-        const size_t nFloatIter = idx_nimg * 4;
-        float* oAvgBgImgPtr = (float*)(oAvgBGImg.data + nFloatIter);
-        const uchar* const oBGImgPtr = m_voBGColorSamples[s].data + idx_nimg;
-        for (size_t c = 0; c < m_nImgChannels; ++c)
-          oAvgBgImgPtr[c] += ((float)oBGImgPtr[c]) / m_nBGSamples;
-      }
-    }
-  }
-  oAvgBGImg.convertTo(backgroundImage, CV_8U);
-}
-
-void BackgroundSubtractorSuBSENSE::getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const {
-  CV_Assert(LBSP::DESC_SIZE == 2);
-  CV_Assert(m_bInitialized);
-  cv::Mat oAvgBGDesc = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
-  for (size_t n = 0; n < m_voBGDescSamples.size(); ++n) {
-    for (int y = 0; y < m_oImgSize.height; ++y) {
-      for (int x = 0; x < m_oImgSize.width; ++x) {
-        const size_t idx_ndesc = m_voBGDescSamples[n].step.p[0] * y + m_voBGDescSamples[n].step.p[1] * x;
-        const size_t nFloatIter = idx_ndesc * 2;
-        float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data + nFloatIter);
-        const ushort* const oBGDescPtr = (ushort*)(m_voBGDescSamples[n].data + idx_ndesc);
-        for (size_t c = 0; c < m_nImgChannels; ++c)
-          oAvgBgDescPtr[c] += ((float)oBGDescPtr[c]) / m_voBGDescSamples.size();
-      }
-    }
-  }
-  oAvgBGDesc.convertTo(backgroundDescImage, CV_16U);
-}
diff --git a/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.h b/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.h
deleted file mode 100644
index 9950ea429270007c4e6ee6c45b2d472668b7d2b0..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.h
+++ /dev/null
@@ -1,129 +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
-
-#include "BackgroundSubtractorLBSP.h"
-
-//! defines the default value for BackgroundSubtractorLBSP::m_fRelLBSPThreshold
-#define BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD (0.333f)
-//! defines the default value for BackgroundSubtractorSuBSENSE::m_nDescDistThresholdOffset
-#define BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET (3)
-//! defines the default value for BackgroundSubtractorSuBSENSE::m_nMinColorDistThreshold
-#define BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD (30)
-//! defines the default value for BackgroundSubtractorSuBSENSE::m_nBGSamples
-#define BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES (50)
-//! defines the default value for BackgroundSubtractorSuBSENSE::m_nRequiredBGSamples
-#define BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES (2)
-//! defines the default value for BackgroundSubtractorSuBSENSE::m_nSamplesForMovingAvgs
-#define BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS (100)
-
-/*!
-  Self-Balanced Sensitivity segmenTER (SuBSENSE) change detection algorithm.
-
-  Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
-  For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
-
-  For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles et al.,
-  "Flexible Background Subtraction With Self-Balanced Local Sensitivity", in CVPRW 2014.
-
-  This algorithm is currently NOT thread-safe.
- */
-class BackgroundSubtractorSuBSENSE : public BackgroundSubtractorLBSP {
-public:
-  //! full constructor
-  BackgroundSubtractorSuBSENSE(float fRelLBSPThreshold = BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
-    size_t nDescDistThresholdOffset = BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET,
-    size_t nMinColorDistThreshold = BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD,
-    size_t nBGSamples = BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES,
-    size_t nRequiredBGSamples = BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES,
-    size_t nSamplesForMovingAvgs = BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
-  //! default destructor
-  virtual ~BackgroundSubtractorSuBSENSE();
-  //! (re)initiaization method; needs to be called before starting background subtraction
-  virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
-  //! refreshes all samples based on the last analyzed frame
-  virtual void refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate = false);
-  //! primary model update function; the learning param is used to override the internal learning thresholds (ignored when <= 0)
-  virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = 0);
-  //! returns a copy of the latest reconstructed background image
-  void getBackgroundImage(cv::OutputArray backgroundImage) const;
-  //! returns a copy of the latest reconstructed background descriptors image
-  void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
-
-protected:
-  //! absolute minimal color distance threshold ('R' or 'radius' in the original ViBe paper, used as the default/initial 'R(x)' value here)
-  const size_t m_nMinColorDistThreshold;
-  //! absolute descriptor distance threshold offset
-  const size_t m_nDescDistThresholdOffset;
-  //! number of different samples per pixel/block to be taken from input frames to build the background model (same as 'N' in ViBe/PBAS)
-  const size_t m_nBGSamples;
-  //! number of similar samples needed to consider the current pixel/block as 'background' (same as '#_min' in ViBe/PBAS)
-  const size_t m_nRequiredBGSamples;
-  //! number of samples to use to compute the learning rate of moving averages
-  const size_t m_nSamplesForMovingAvgs;
-  //! last calculated non-zero desc ratio
-  float m_fLastNonZeroDescRatio;
-  //! specifies whether Tmin/Tmax scaling is enabled or not
-  bool m_bLearningRateScalingEnabled;
-  //! current learning rate caps
-  float m_fCurrLearningRateLowerCap, m_fCurrLearningRateUpperCap;
-  //! current kernel size for median blur post-proc filtering
-  int m_nMedianBlurKernelSize;
-  //! specifies the px update spread range
-  bool m_bUse3x3Spread;
-  //! specifies the downsampled frame size used for cam motion analysis
-  cv::Size m_oDownSampledFrameSize;
-
-  //! background model pixel color intensity samples (equivalent to 'B(x)' in PBAS)
-  std::vector<cv::Mat> m_voBGColorSamples;
-  //! background model descriptors samples
-  std::vector<cv::Mat> m_voBGDescSamples;
-
-  //! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe)
-  cv::Mat m_oUpdateRateFrame;
-  //! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds)
-  cv::Mat m_oDistThresholdFrame;
-  //! per-pixel distance variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations)
-  cv::Mat m_oVariationModulatorFrame;
-  //! per-pixel mean distances between consecutive frames ('D_last(x)', used to detect ghosts and high variation regions in the sequence)
-  cv::Mat m_oMeanLastDistFrame;
-  //! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)')
-  cv::Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST;
-  //! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and control max learning rates globally)
-  cv::Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST;
-  //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
-  cv::Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST;
-  //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
-  cv::Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST;
-  //! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds)
-  cv::Mat m_oUnstableRegionMask;
-  //! per-pixel blink detection map ('Z(x)')
-  cv::Mat m_oBlinksFrame;
-  //! pre-allocated matrix used to downsample the input frame when needed
-  cv::Mat m_oDownSampledFrame_MotionAnalysis;
-  //! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection)
-  cv::Mat m_oLastRawFGMask;
-
-  //! pre-allocated CV_8UC1 matrices used to speed up morph ops
-  cv::Mat m_oFGMask_PreFlood;
-  cv::Mat m_oFGMask_FloodedHoles;
-  cv::Mat m_oLastFGMask_dilated;
-  cv::Mat m_oLastFGMask_dilated_inverted;
-  cv::Mat m_oCurrRawFGBlinkMask;
-  cv::Mat m_oLastRawFGBlinkMask;
-};
-
diff --git a/package_bgs/LBSP/DistanceUtils.h b/package_bgs/LBSP/DistanceUtils.h
deleted file mode 100644
index 9eabca4a79db6f5f83a2d54c9558370cde799115..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/DistanceUtils.h
+++ /dev/null
@@ -1,332 +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
-
-#include <opencv2/core/types_c.h>
-
-//! computes the L1 distance between two integer values
-template<typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type L1dist(T a, T b) {
-  return (size_t)abs((int)a-b);
-}
-
-//! computes the L1 distance between two float values
-template<typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type L1dist(T a, T b) {
-  return fabs((float)a-(float)b);
-}
-
-//! computes the L1 distance between two generic arrays
-template<size_t nChannels, typename T> static inline auto L1dist(const T* a, const T* b) -> decltype(L1dist(*a,*b)) {
-  decltype(L1dist(*a,*b)) oResult = 0;
-  for(size_t c=0; c<nChannels; ++c)
-    oResult += L1dist(a[c],b[c]);
-  return oResult;
-}
-
-//! computes the L1 distance between two generic arrays
-template<size_t nChannels, typename T> static inline auto L1dist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(L1dist<nChannels>(a,b)) {
-  decltype(L1dist<nChannels>(a,b)) oResult = 0;
-  size_t nTotElements = nElements*nChannels;
-  if(m) {
-    for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
-      if(m[i])
-        oResult += L1dist<nChannels>(a+n,b+n);
-  }
-  else {
-    for(size_t n=0; n<nTotElements; n+=nChannels)
-      oResult += L1dist<nChannels>(a+n,b+n);
-  }
-  return oResult;
-}
-
-//! computes the L1 distance between two generic arrays
-template<typename T> static inline auto L1dist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(L1dist<3>(a,b,nElements,m)) {
-  CV_Assert(nChannels>0 && nChannels<=4);
-  switch(nChannels) {
-  case 1: return L1dist<1>(a,b,nElements,m);
-  case 2: return L1dist<2>(a,b,nElements,m);
-  case 3: return L1dist<3>(a,b,nElements,m);
-  case 4: return L1dist<4>(a,b,nElements,m);
-  default: return 0;
-  }
-}
-
-//! computes the L1 distance between two opencv vectors
-template<size_t nChannels, typename T> static inline auto L1dist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(L1dist<nChannels,T>((T*)(0),(T*)(0))) {
-  T a_array[nChannels], b_array[nChannels];
-  for(size_t c=0; c<nChannels; ++c) {
-    a_array[c] = a[(int)c];
-    b_array[c] = b[(int)c];
-  }
-  return L1dist<nChannels>(a_array,b_array);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//! computes the squared L2 distance between two generic variables
-template<typename T> static inline auto L2sqrdist(T a, T b) -> decltype(L1dist(a,b)) {
-  auto oResult = L1dist(a,b);
-  return oResult*oResult;
-}
-
-//! computes the squared L2 distance between two generic arrays
-template<size_t nChannels, typename T> static inline auto L2sqrdist(const T* a, const T* b) -> decltype(L2sqrdist(*a,*b)) {
-  decltype(L2sqrdist(*a,*b)) oResult = 0;
-  for(size_t c=0; c<nChannels; ++c)
-    oResult += L2sqrdist(a[c],b[c]);
-  return oResult;
-}
-
-//! computes the squared L2 distance between two generic arrays
-template<size_t nChannels, typename T> static inline auto L2sqrdist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(L2sqrdist<nChannels>(a,b)) {
-  decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
-  size_t nTotElements = nElements*nChannels;
-  if(m) {
-    for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
-      if(m[i])
-        oResult += L2sqrdist<nChannels>(a+n,b+n);
-  }
-  else {
-    for(size_t n=0; n<nTotElements; n+=nChannels)
-      oResult += L2sqrdist<nChannels>(a+n,b+n);
-  }
-  return oResult;
-}
-
-//! computes the squared L2 distance between two generic arrays
-template<typename T> static inline auto L2sqrdist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(L2sqrdist<3>(a,b,nElements,m)) {
-  CV_Assert(nChannels>0 && nChannels<=4);
-  switch(nChannels) {
-  case 1: return L2sqrdist<1>(a,b,nElements,m);
-  case 2: return L2sqrdist<2>(a,b,nElements,m);
-  case 3: return L2sqrdist<3>(a,b,nElements,m);
-  case 4: return L2sqrdist<4>(a,b,nElements,m);
-  default: return 0;
-  }
-}
-
-//! computes the squared L2 distance between two opencv vectors
-template<size_t nChannels, typename T> static inline auto L2sqrdist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(L2sqrdist<nChannels,T>((T*)(0),(T*)(0))) {
-  T a_array[nChannels], b_array[nChannels];
-  for(size_t c=0; c<nChannels; ++c) {
-    a_array[c] = a[(int)c];
-    b_array[c] = b[(int)c];
-  }
-  return L2sqrdist<nChannels>(a_array,b_array);
-}
-
-//! computes the L2 distance between two generic arrays
-template<size_t nChannels, typename T> static inline float L2dist(const T* a, const T* b) {
-  decltype(L2sqrdist(*a,*b)) oResult = 0;
-  for(size_t c=0; c<nChannels; ++c)
-    oResult += L2sqrdist(a[c],b[c]);
-  return sqrt((float)oResult);
-}
-
-//! computes the L2 distance between two generic arrays
-template<size_t nChannels, typename T> static inline float L2dist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) {
-  decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
-  size_t nTotElements = nElements*nChannels;
-  if(m) {
-    for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
-      if(m[i])
-        oResult += L2sqrdist<nChannels>(a+n,b+n);
-  }
-  else {
-    for(size_t n=0; n<nTotElements; n+=nChannels)
-      oResult += L2sqrdist<nChannels>(a+n,b+n);
-  }
-  return sqrt((float)oResult);
-}
-
-//! computes the squared L2 distance between two generic arrays
-template<typename T> static inline float L2dist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) {
-  CV_Assert(nChannels>0 && nChannels<=4);
-  switch(nChannels) {
-  case 1: return L2dist<1>(a,b,nElements,m);
-  case 2: return L2dist<2>(a,b,nElements,m);
-  case 3: return L2dist<3>(a,b,nElements,m);
-  case 4: return L2dist<4>(a,b,nElements,m);
-  default: return 0;
-  }
-}
-
-//! computes the L2 distance between two opencv vectors
-template<size_t nChannels, typename T> static inline float L2dist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) {
-  T a_array[nChannels], b_array[nChannels];
-  for(size_t c=0; c<nChannels; ++c) {
-    a_array[c] = a[(int)c];
-    b_array[c] = b[(int)c];
-  }
-  return L2dist<nChannels>(a_array,b_array);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//! computes the color distortion between two integer arrays
-template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type cdist(const T* curr, const T* bg) {
-  static_assert(nChannels>1,"cdist: requires more than one channel");
-  size_t curr_sqr = 0;
-  bool bSkip = true;
-  for(size_t c=0; c<nChannels; ++c) {
-    curr_sqr += curr[c]*curr[c];
-    bSkip = bSkip&(bg[c]<=0);
-  }
-  if(bSkip)
-    return (size_t)sqrt((float)curr_sqr);
-  size_t bg_sqr = 0;
-  size_t mix = 0;
-  for(size_t c=0; c<nChannels; ++c) {
-    bg_sqr += bg[c]*bg[c];
-    mix += curr[c]*bg[c];
-  }
-  return (size_t)sqrt(curr_sqr-((float)(mix*mix)/bg_sqr));
-}
-
-//! computes the color distortion between two float arrays
-template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type cdist(const T* curr, const T* bg) {
-  static_assert(nChannels>1,"cdist: requires more than one channel");
-  float curr_sqr = 0;
-  bool bSkip = true;
-  for(size_t c=0; c<nChannels; ++c) {
-    curr_sqr += (float)curr[c]*curr[c];
-    bSkip = bSkip&(bg[c]<=0);
-  }
-  if(bSkip)
-    return sqrt(curr_sqr);
-  float bg_sqr = 0;
-  float mix = 0;
-  for(size_t c=0; c<nChannels; ++c) {
-    bg_sqr += (float)bg[c]*bg[c];
-    mix += (float)curr[c]*bg[c];
-  }
-  return sqrt(curr_sqr-((mix*mix)/bg_sqr));
-}
-
-//! computes the color distortion between two generic arrays
-template<size_t nChannels, typename T> static inline auto cdist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(cdist<nChannels>(a,b)) {
-  decltype(cdist<nChannels>(a,b)) oResult = 0;
-  size_t nTotElements = nElements*nChannels;
-  if(m) {
-    for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
-      if(m[i])
-        oResult += cdist<nChannels>(a+n,b+n);
-  }
-  else {
-    for(size_t n=0; n<nTotElements; n+=nChannels)
-      oResult += cdist<nChannels>(a+n,b+n);
-  }
-  return oResult;
-}
-
-//! computes the color distortion between two generic arrays
-template<typename T> static inline auto cdist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(cdist<3>(a,b,nElements,m)) {
-  CV_Assert(nChannels>1 && nChannels<=4);
-  switch(nChannels) {
-  case 2: return cdist<2>(a,b,nElements,m);
-  case 3: return cdist<3>(a,b,nElements,m);
-  case 4: return cdist<4>(a,b,nElements,m);
-  default: return 0;
-  }
-}
-
-//! computes the color distortion between two opencv vectors
-template<size_t nChannels, typename T> static inline auto cdist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(cdist<nChannels,T>((T*)(0),(T*)(0))) {
-  T a_array[nChannels], b_array[nChannels];
-  for(size_t c=0; c<nChannels; ++c) {
-    a_array[c] = a[(int)c];
-    b_array[c] = b[(int)c];
-  }
-  return cdist<nChannels>(a_array,b_array);
-}
-
-//! computes a color distortion-distance mix using two generic distances
-template<typename T> static inline T cmixdist(T oL1Distance, T oCDistortion) {
-  return (oL1Distance/2+oCDistortion*4);
-}
-
-//! computes a color distoirtion-distance mix using two generic arrays
-template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type cmixdist(const T* curr, const T* bg) {
-  return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
-}
-
-template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type cmixdist(const T* curr, const T* bg) {
-  return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//! popcount LUT for 8-bit vectors
-static const uchar popcount_LUT8[256] = {
-  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
-  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-  4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
-};
-
-//! computes the population count of an N-byte vector using an 8-bit popcount LUT
-template<typename T> static inline size_t popcount(T x) {
-  size_t nBytes = sizeof(T);
-  size_t nResult = 0;
-  for(size_t l=0; l<nBytes; ++l)
-    nResult += popcount_LUT8[(uchar)(x>>l*8)];
-  return nResult;
-}
-
-//! computes the hamming distance between two N-byte vectors using an 8-bit popcount LUT
-template<typename T> static inline size_t hdist(T a, T b) {
-  return popcount(a^b);
-}
-
-//! computes the gradient magnitude distance between two N-byte vectors using an 8-bit popcount LUT
-template<typename T> static inline size_t gdist(T a, T b) {
-  return L1dist(popcount(a),popcount(b));
-}
-
-//! computes the population count of a (nChannels*N)-byte vector using an 8-bit popcount LUT
-template<size_t nChannels, typename T> static inline size_t popcount(const T* x) {
-  size_t nBytes = sizeof(T);
-  size_t nResult = 0;
-  for(size_t c=0; c<nChannels; ++c)
-    for(size_t l=0; l<nBytes; ++l)
-      nResult += popcount_LUT8[(uchar)(*(x+c)>>l*8)];
-  return nResult;
-}
-
-//! computes the hamming distance between two (nChannels*N)-byte vectors using an 8-bit popcount LUT
-template<size_t nChannels, typename T> static inline size_t hdist(const T* a, const T* b) {
-  T xor_array[nChannels];
-  for(size_t c=0; c<nChannels; ++c)
-    xor_array[c] = a[c]^b[c];
-  return popcount<nChannels>(xor_array);
-}
-
-//! computes the gradient magnitude distance between two (nChannels*N)-byte vectors using an 8-bit popcount LUT
-template<size_t nChannels, typename T> static inline size_t gdist(const T* a, const T* b) {
-  return L1dist(popcount<nChannels>(a),popcount<nChannels>(b));
-}
diff --git a/package_bgs/LBSP/LBSP.cpp b/package_bgs/LBSP/LBSP.cpp
deleted file mode 100644
index 4ec17b973dfeaf4d4de076927831838399f4900c..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/LBSP.cpp
+++ /dev/null
@@ -1,334 +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 "LBSP.h"
-
-LBSP::LBSP(size_t nThreshold)
-  : m_bOnlyUsingAbsThreshold(true)
-  , m_fRelThreshold(0) // unused
-  , m_nThreshold(nThreshold)
-  , m_oRefImage() {}
-
-LBSP::LBSP(float fRelThreshold, size_t nThresholdOffset)
-  : m_bOnlyUsingAbsThreshold(false)
-  , m_fRelThreshold(fRelThreshold)
-  , m_nThreshold(nThresholdOffset)
-  , m_oRefImage() {
-  CV_Assert(m_fRelThreshold >= 0);
-}
-
-LBSP::~LBSP() {}
-
-void LBSP::read(const cv::FileNode& /*fn*/) {
-  // ... = fn["..."];
-}
-
-void LBSP::write(cv::FileStorage& /*fs*/) const {
-  //fs << "..." << ...;
-}
-
-void LBSP::setReference(const cv::Mat& img) {
-  CV_DbgAssert(img.empty() || img.type() == CV_8UC1 || img.type() == CV_8UC3);
-  m_oRefImage = img;
-}
-
-int LBSP::descriptorSize() const {
-  return DESC_SIZE;
-}
-
-int LBSP::descriptorType() const {
-  return CV_16U;
-}
-
-bool LBSP::isUsingRelThreshold() const {
-  return !m_bOnlyUsingAbsThreshold;
-}
-
-float LBSP::getRelThreshold() const {
-  return m_fRelThreshold;
-}
-
-size_t LBSP::getAbsThreshold() const {
-  return m_nThreshold;
-}
-
-static inline void lbsp_computeImpl(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  size_t _t) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create((int)nKeyPoints, 1, CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>((int)k);
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create((int)nKeyPoints, 1, CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
-#include "LBSP_16bits_dbcross_3ch1t.i"
-    }
-  }
-}
-
-static inline void lbsp_computeImpl(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  float fThreshold,
-  size_t nThresholdOffset) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(fThreshold >= 0);
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create((int)nKeyPoints, 1, CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>((int)k);
-      const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create((int)nKeyPoints, 1, CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
-      const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
-#include "LBSP_16bits_dbcross_3ch3t.i"
-    }
-  }
-}
-
-static inline void lbsp_computeImpl2(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  size_t _t) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create(oInputImg.size(), CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>(_y, _x);
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create(oInputImg.size(), CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
-#include "LBSP_16bits_dbcross_3ch1t.i"
-    }
-  }
-}
-
-static inline void lbsp_computeImpl2(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  float fThreshold,
-  size_t nThresholdOffset) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(fThreshold >= 0);
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create(oInputImg.size(), CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>(_y, _x);
-      const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create(oInputImg.size(), CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
-      const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
-#include "LBSP_16bits_dbcross_3ch3t.i"
-    }
-  }
-}
-
-void LBSP::compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
-  CV_Assert(!oImage.empty());
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
-  cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
-  if (voKeypoints.empty()) {
-    oDescriptors.release();
-    return;
-  }
-  if (m_bOnlyUsingAbsThreshold)
-    lbsp_computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
-  else
-    lbsp_computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
-}
-
-void LBSP::compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const {
-  CV_Assert(voImageCollection.size() == vvoPointCollection.size());
-  voDescCollection.resize(voImageCollection.size());
-  for (size_t i = 0; i < voImageCollection.size(); i++)
-    compute2(voImageCollection[i], vvoPointCollection[i], voDescCollection[i]);
-}
-
-void LBSP::computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
-  CV_Assert(!oImage.empty());
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
-  cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
-  if (voKeypoints.empty()) {
-    oDescriptors.release();
-    return;
-  }
-  if (m_bOnlyUsingAbsThreshold)
-    lbsp_computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
-  else
-    lbsp_computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
-}
-
-void LBSP::reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput) {
-  CV_DbgAssert(!voKeypoints.empty());
-  CV_DbgAssert(!oDescriptors.empty() && oDescriptors.cols == 1);
-  CV_DbgAssert(oSize.width > 0 && oSize.height > 0);
-  CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(oDescriptors.type() == CV_16UC1 || oDescriptors.type() == CV_16UC3);
-  const size_t nChannels = (size_t)oDescriptors.channels();
-  const size_t nKeyPoints = voKeypoints.size();
-  if (nChannels == 1) {
-    oOutput.create(oSize, CV_16UC1);
-    oOutput = cv::Scalar_<ushort>(0);
-    for (size_t k = 0; k < nKeyPoints; ++k)
-      oOutput.at<ushort>(voKeypoints[k].pt) = oDescriptors.at<ushort>((int)k);
-  }
-  else { //nChannels==3
-    oOutput.create(oSize, CV_16UC3);
-    oOutput = cv::Scalar_<ushort>(0, 0, 0);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      ushort* output_ptr = (ushort*)(oOutput.data + oOutput.step.p[0] * (int)voKeypoints[k].pt.y);
-      const ushort* const desc_ptr = (ushort*)(oDescriptors.data + oDescriptors.step.p[0] * k);
-      const size_t idx = 3 * (int)voKeypoints[k].pt.x;
-      for (size_t n = 0; n < 3; ++n)
-        output_ptr[idx + n] = desc_ptr[n];
-    }
-  }
-}
-
-void LBSP::calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels) {
-  CV_DbgAssert(oDesc1.size() == oDesc2.size() && oDesc1.type() == oDesc2.type());
-  CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(oDesc1.type() == CV_16UC1 || oDesc1.type() == CV_16UC3);
-  CV_DbgAssert(CV_MAT_DEPTH(oDesc1.type()) == CV_16U);
-  CV_DbgAssert(DESC_SIZE * 8 <= UCHAR_MAX);
-  CV_DbgAssert(oDesc1.step.p[0] == oDesc2.step.p[0] && oDesc1.step.p[1] == oDesc2.step.p[1]);
-  const float fScaleFactor = (float)UCHAR_MAX / (DESC_SIZE * 8);
-  const size_t nChannels = CV_MAT_CN(oDesc1.type());
-  const size_t _step_row = oDesc1.step.p[0];
-  if (nChannels == 1) {
-    oOutput.create(oDesc1.size(), CV_8UC1);
-    oOutput = cv::Scalar(0);
-    for (int i = 0; i < oDesc1.rows; ++i) {
-      const size_t idx = _step_row*i;
-      const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
-      const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
-      for (int j = 0; j < oDesc1.cols; ++j)
-        oOutput.at<uchar>(i, j) = (uchar)(fScaleFactor*hdist(desc1_ptr[j], desc2_ptr[j]));
-    }
-  }
-  else { //nChannels==3
-    if (bForceMergeChannels)
-      oOutput.create(oDesc1.size(), CV_8UC1);
-    else
-      oOutput.create(oDesc1.size(), CV_8UC3);
-    oOutput = cv::Scalar::all(0);
-    for (int i = 0; i < oDesc1.rows; ++i) {
-      const size_t idx = _step_row*i;
-      const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
-      const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
-      uchar* output_ptr = oOutput.data + oOutput.step.p[0] * i;
-      for (int j = 0; j < oDesc1.cols; ++j) {
-        for (size_t n = 0; n < 3; ++n) {
-          const size_t idx2 = 3 * j + n;
-          if (bForceMergeChannels)
-            output_ptr[j] += (uchar)((fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2])) / 3);
-          else
-            output_ptr[idx2] = (uchar)(fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2]));
-        }
-      }
-    }
-  }
-}
-
-void LBSP::validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize) {
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImgSize, PATCH_SIZE / 2);
-}
-
-void LBSP::validateROI(cv::Mat& oROI) {
-  CV_Assert(!oROI.empty() && oROI.type() == CV_8UC1);
-  cv::Mat oROI_new(oROI.size(), CV_8UC1, cv::Scalar_<uchar>(0));
-  const size_t nBorderSize = PATCH_SIZE / 2;
-  const cv::Rect nROI_inner(nBorderSize, nBorderSize, oROI.cols - nBorderSize * 2, oROI.rows - nBorderSize * 2);
-  cv::Mat(oROI, nROI_inner).copyTo(cv::Mat(oROI_new, nROI_inner));
-  oROI = oROI_new;
-}
diff --git a/package_bgs/LBSP/LBSP.h b/package_bgs/LBSP/LBSP.h
deleted file mode 100644
index c908eaa068641ece3b1ec0f487e2f6b01fae5899..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/LBSP.h
+++ /dev/null
@@ -1,134 +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
-
-#include <opencv2/core/core.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/features2d/features2d.hpp>
-#include "DistanceUtils.h"
-
-/*!
-  Local Binary Similarity Pattern (LBSP) feature extractor
-
-  Note 1: both grayscale and RGB/BGR images may be used with this extractor.
-  Note 2: using LBSP::compute2(...) is logically equivalent to using LBSP::compute(...) followed by LBSP::reshapeDesc(...).
-
-  For more details on the different parameters, see G.-A. Bilodeau et al, "Change Detection in Feature Space Using Local
-  Binary Similarity Patterns", in CRV 2013.
-
-  This algorithm is currently NOT thread-safe.
- */
-class LBSP : public cv::DescriptorExtractor {
-public:
-  //! constructor 1, threshold = absolute intensity 'similarity' threshold used when computing comparisons
-  LBSP(size_t nThreshold);
-  //! constructor 2, threshold = relative intensity 'similarity' threshold used when computing comparisons
-  LBSP(float fRelThreshold, size_t nThresholdOffset = 0);
-  //! default destructor
-  virtual ~LBSP();
-  //! loads extractor params from the specified file node @@@@ not impl
-  virtual void read(const cv::FileNode&);
-  //! writes extractor params to the specified file storage @@@@ not impl
-  virtual void write(cv::FileStorage&) const;
-  //! sets the 'reference' image to be used for inter-frame comparisons (note: if no image is set or if the image is empty, the algorithm will default back to intra-frame comparisons)
-  virtual void setReference(const cv::Mat&);
-  //! returns the current descriptor size, in bytes
-  virtual int descriptorSize() const;
-  //! returns the current descriptor data type
-  virtual int descriptorType() const;
-  //! returns whether this extractor is using a relative threshold or not
-  virtual bool isUsingRelThreshold() const;
-  //! returns the current relative threshold used for comparisons (-1 = invalid/not used)
-  virtual float getRelThreshold() const;
-  //! returns the current absolute threshold used for comparisons (-1 = invalid/not used)
-  virtual size_t getAbsThreshold() const;
-
-  //! similar to DescriptorExtractor::compute(const cv::Mat& image, ...), but in this case, the descriptors matrix has the same shape as the input matrix (possibly slower, but the result can be displayed)
-  void compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
-  //! batch version of LBSP::compute2(const cv::Mat& image, ...), also similar to DescriptorExtractor::compute(const std::vector<cv::Mat>& imageCollection, ...)
-  void compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const;
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel version)
-  inline static void computeGrayscaleDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _t, ushort& _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC1);
-    CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_1ch.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
-  inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t* const _t, ushort* _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3);
-    CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_3ch3t.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
-  inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t _t, ushort* _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3);
-    CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_3ch1t.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel-RGB version)
-  inline static void computeSingleRGBDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _c, const size_t _t, ushort& _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3 && _c < 3);
-    CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_s3ch.i"
-  }
-
-  //! utility function, used to reshape a descriptors matrix to its input image size via their keypoint locations
-  static void reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput);
-  //! utility function, used to illustrate the difference between two descriptor images
-  static void calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels = false);
-  //! utility function, used to filter out bad keypoints that would trigger out of bounds error because they're too close to the image border
-  static void validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize);
-  //! utility function, used to filter out bad pixels in a ROI that would trigger out of bounds error because they're too close to the image border
-  static void validateROI(cv::Mat& oROI);
-  //! utility, specifies the pixel size of the pattern used (width and height)
-  static const size_t PATCH_SIZE = 5;
-  //! utility, specifies the number of bytes per descriptor (should be the same as calling 'descriptorSize()')
-  static const size_t DESC_SIZE = 2;
-
-protected:
-  //! classic 'compute' implementation, based on the regular DescriptorExtractor::computeImpl arguments & expected output
-  virtual void computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
-
-  const bool m_bOnlyUsingAbsThreshold;
-  const float m_fRelThreshold;
-  const size_t m_nThreshold;
-  cv::Mat m_oRefImage;
-};
diff --git a/package_bgs/LBSP/LBSP_.cpp b/package_bgs/LBSP/LBSP_.cpp
deleted file mode 100644
index ff5c8e8abed8fd8e1a96a4ef1bfea3b91fe74119..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/LBSP_.cpp
+++ /dev/null
@@ -1,334 +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 "LBSP_.h"
-
-LBSP_::LBSP_(size_t nThreshold)
-  : m_bOnlyUsingAbsThreshold(true)
-  , m_fRelThreshold(0) // unused
-  , m_nThreshold(nThreshold)
-  , m_oRefImage() {}
-
-LBSP_::LBSP_(float fRelThreshold, size_t nThresholdOffset)
-  : m_bOnlyUsingAbsThreshold(false)
-  , m_fRelThreshold(fRelThreshold)
-  , m_nThreshold(nThresholdOffset)
-  , m_oRefImage() {
-  CV_Assert(m_fRelThreshold >= 0);
-}
-
-LBSP_::~LBSP_() {}
-
-void LBSP_::read(const cv::FileNode& /*fn*/) {
-  // ... = fn["..."];
-}
-
-void LBSP_::write(cv::FileStorage& /*fs*/) const {
-  //fs << "..." << ...;
-}
-
-void LBSP_::setReference(const cv::Mat& img) {
-  CV_DbgAssert(img.empty() || img.type() == CV_8UC1 || img.type() == CV_8UC3);
-  m_oRefImage = img;
-}
-
-int LBSP_::descriptorSize() const {
-  return DESC_SIZE;
-}
-
-int LBSP_::descriptorType() const {
-  return CV_16U;
-}
-
-bool LBSP_::isUsingRelThreshold() const {
-  return !m_bOnlyUsingAbsThreshold;
-}
-
-float LBSP_::getRelThreshold() const {
-  return m_fRelThreshold;
-}
-
-size_t LBSP_::getAbsThreshold() const {
-  return m_nThreshold;
-}
-
-static inline void LBSP__computeImpl(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  size_t _t) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create((int)nKeyPoints, 1, CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>((int)k);
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create((int)nKeyPoints, 1, CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
-#include "LBSP_16bits_dbcross_3ch1t.i"
-    }
-  }
-}
-
-static inline void LBSP__computeImpl(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  float fThreshold,
-  size_t nThresholdOffset) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(fThreshold >= 0);
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create((int)nKeyPoints, 1, CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>((int)k);
-      const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create((int)nKeyPoints, 1, CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
-      const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
-#include "LBSP_16bits_dbcross_3ch3t.i"
-    }
-  }
-}
-
-static inline void LBSP__computeImpl2(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  size_t _t) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create(oInputImg.size(), CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>(_y, _x);
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create(oInputImg.size(), CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
-#include "LBSP_16bits_dbcross_3ch1t.i"
-    }
-  }
-}
-
-static inline void LBSP__computeImpl2(const cv::Mat& oInputImg,
-  const cv::Mat& oRefImg,
-  const std::vector<cv::KeyPoint>& voKeyPoints,
-  cv::Mat& oDesc,
-  float fThreshold,
-  size_t nThresholdOffset) {
-  CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
-  CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
-  CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(fThreshold >= 0);
-  const size_t nChannels = (size_t)oInputImg.channels();
-  const size_t _step_row = oInputImg.step.p[0];
-  const uchar* _data = oInputImg.data;
-  const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
-  const size_t nKeyPoints = voKeyPoints.size();
-  if (nChannels == 1) {
-    oDesc.create(oInputImg.size(), CV_16UC1);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar _ref = _refdata[_step_row*(_y)+_x];
-      ushort& _res = oDesc.at<ushort>(_y, _x);
-      const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
-#include "LBSP_16bits_dbcross_1ch.i"
-    }
-  }
-  else { //nChannels==3
-    oDesc.create(oInputImg.size(), CV_16UC3);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      const int _x = (int)voKeyPoints[k].pt.x;
-      const int _y = (int)voKeyPoints[k].pt.y;
-      const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
-      ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
-      const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
-#include "LBSP_16bits_dbcross_3ch3t.i"
-    }
-  }
-}
-
-void LBSP_::compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
-  CV_Assert(!oImage.empty());
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
-  cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
-  if (voKeypoints.empty()) {
-    oDescriptors.release();
-    return;
-  }
-  if (m_bOnlyUsingAbsThreshold)
-    LBSP__computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
-  else
-    LBSP__computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
-}
-
-void LBSP_::compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const {
-  CV_Assert(voImageCollection.size() == vvoPointCollection.size());
-  voDescCollection.resize(voImageCollection.size());
-  for (size_t i = 0; i < voImageCollection.size(); i++)
-    compute2(voImageCollection[i], vvoPointCollection[i], voDescCollection[i]);
-}
-
-void LBSP_::computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
-  CV_Assert(!oImage.empty());
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
-  cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
-  if (voKeypoints.empty()) {
-    oDescriptors.release();
-    return;
-  }
-  if (m_bOnlyUsingAbsThreshold)
-    LBSP__computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
-  else
-    LBSP__computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
-}
-
-void LBSP_::reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput) {
-  CV_DbgAssert(!voKeypoints.empty());
-  CV_DbgAssert(!oDescriptors.empty() && oDescriptors.cols == 1);
-  CV_DbgAssert(oSize.width > 0 && oSize.height > 0);
-  CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(oDescriptors.type() == CV_16UC1 || oDescriptors.type() == CV_16UC3);
-  const size_t nChannels = (size_t)oDescriptors.channels();
-  const size_t nKeyPoints = voKeypoints.size();
-  if (nChannels == 1) {
-    oOutput.create(oSize, CV_16UC1);
-    oOutput = cv::Scalar_<ushort>(0);
-    for (size_t k = 0; k < nKeyPoints; ++k)
-      oOutput.at<ushort>(voKeypoints[k].pt) = oDescriptors.at<ushort>((int)k);
-  }
-  else { //nChannels==3
-    oOutput.create(oSize, CV_16UC3);
-    oOutput = cv::Scalar_<ushort>(0, 0, 0);
-    for (size_t k = 0; k < nKeyPoints; ++k) {
-      ushort* output_ptr = (ushort*)(oOutput.data + oOutput.step.p[0] * (int)voKeypoints[k].pt.y);
-      const ushort* const desc_ptr = (ushort*)(oDescriptors.data + oDescriptors.step.p[0] * k);
-      const size_t idx = 3 * (int)voKeypoints[k].pt.x;
-      for (size_t n = 0; n < 3; ++n)
-        output_ptr[idx + n] = desc_ptr[n];
-    }
-  }
-}
-
-void LBSP_::calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels) {
-  CV_DbgAssert(oDesc1.size() == oDesc2.size() && oDesc1.type() == oDesc2.type());
-  CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
-  CV_DbgAssert(oDesc1.type() == CV_16UC1 || oDesc1.type() == CV_16UC3);
-  CV_DbgAssert(CV_MAT_DEPTH(oDesc1.type()) == CV_16U);
-  CV_DbgAssert(DESC_SIZE * 8 <= UCHAR_MAX);
-  CV_DbgAssert(oDesc1.step.p[0] == oDesc2.step.p[0] && oDesc1.step.p[1] == oDesc2.step.p[1]);
-  const float fScaleFactor = (float)UCHAR_MAX / (DESC_SIZE * 8);
-  const size_t nChannels = CV_MAT_CN(oDesc1.type());
-  const size_t _step_row = oDesc1.step.p[0];
-  if (nChannels == 1) {
-    oOutput.create(oDesc1.size(), CV_8UC1);
-    oOutput = cv::Scalar(0);
-    for (int i = 0; i < oDesc1.rows; ++i) {
-      const size_t idx = _step_row*i;
-      const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
-      const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
-      for (int j = 0; j < oDesc1.cols; ++j)
-        oOutput.at<uchar>(i, j) = (uchar)(fScaleFactor*hdist(desc1_ptr[j], desc2_ptr[j]));
-    }
-  }
-  else { //nChannels==3
-    if (bForceMergeChannels)
-      oOutput.create(oDesc1.size(), CV_8UC1);
-    else
-      oOutput.create(oDesc1.size(), CV_8UC3);
-    oOutput = cv::Scalar::all(0);
-    for (int i = 0; i < oDesc1.rows; ++i) {
-      const size_t idx = _step_row*i;
-      const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
-      const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
-      uchar* output_ptr = oOutput.data + oOutput.step.p[0] * i;
-      for (int j = 0; j < oDesc1.cols; ++j) {
-        for (size_t n = 0; n < 3; ++n) {
-          const size_t idx2 = 3 * j + n;
-          if (bForceMergeChannels)
-            output_ptr[j] += (uchar)((fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2])) / 3);
-          else
-            output_ptr[idx2] = (uchar)(fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2]));
-        }
-      }
-    }
-  }
-}
-
-void LBSP_::validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize) {
-  cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImgSize, PATCH_SIZE / 2);
-}
-
-void LBSP_::validateROI(cv::Mat& oROI) {
-  CV_Assert(!oROI.empty() && oROI.type() == CV_8UC1);
-  cv::Mat oROI_new(oROI.size(), CV_8UC1, cv::Scalar_<uchar>(0));
-  const size_t nBorderSize = PATCH_SIZE / 2;
-  const cv::Rect nROI_inner(nBorderSize, nBorderSize, oROI.cols - nBorderSize * 2, oROI.rows - nBorderSize * 2);
-  cv::Mat(oROI, nROI_inner).copyTo(cv::Mat(oROI_new, nROI_inner));
-  oROI = oROI_new;
-}
diff --git a/package_bgs/LBSP/LBSP_.h b/package_bgs/LBSP/LBSP_.h
deleted file mode 100644
index 819174a948ea1556f898f7804cacff30ac25d1b2..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/LBSP_.h
+++ /dev/null
@@ -1,134 +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
-
-#include <opencv2/core/core.hpp>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/features2d/features2d.hpp>
-#include "DistanceUtils.h"
-
-/*!
-    Local Binary Similarity Pattern (LBSP) feature extractor
-
-    Note 1: both grayscale and RGB/BGR images may be used with this extractor.
-    Note 2: using LBSP_::compute2(...) is logically equivalent to using LBSP_::compute(...) followed by LBSP_::reshapeDesc(...).
-
-    For more details on the different parameters, see G.-A. Bilodeau et al, "Change Detection in Feature Space Using Local
-    Binary Similarity Patterns", in CRV 2013.
-
-    This algorithm is currently NOT thread-safe.
- */
-class LBSP_ : public cv::Feature2D {
-public:
-  //! constructor 1, threshold = absolute intensity 'similarity' threshold used when computing comparisons
-  LBSP_(size_t nThreshold);
-  //! constructor 2, threshold = relative intensity 'similarity' threshold used when computing comparisons
-  LBSP_(float fRelThreshold, size_t nThresholdOffset = 0);
-  //! default destructor
-  virtual ~LBSP_();
-  //! loads extractor params from the specified file node @@@@ not impl
-  virtual void read(const cv::FileNode&);
-  //! writes extractor params to the specified file storage @@@@ not impl
-  virtual void write(cv::FileStorage&) const;
-  //! sets the 'reference' image to be used for inter-frame comparisons (note: if no image is set or if the image is empty, the algorithm will default back to intra-frame comparisons)
-  virtual void setReference(const cv::Mat&);
-  //! returns the current descriptor size, in bytes
-  virtual int descriptorSize() const;
-  //! returns the current descriptor data type
-  virtual int descriptorType() const;
-  //! returns whether this extractor is using a relative threshold or not
-  virtual bool isUsingRelThreshold() const;
-  //! returns the current relative threshold used for comparisons (-1 = invalid/not used)
-  virtual float getRelThreshold() const;
-  //! returns the current absolute threshold used for comparisons (-1 = invalid/not used)
-  virtual size_t getAbsThreshold() const;
-
-  //! similar to DescriptorExtractor::compute(const cv::Mat& image, ...), but in this case, the descriptors matrix has the same shape as the input matrix (possibly slower, but the result can be displayed)
-  void compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
-  //! batch version of LBSP_::compute2(const cv::Mat& image, ...), also similar to DescriptorExtractor::compute(const std::vector<cv::Mat>& imageCollection, ...)
-  void compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const;
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel version)
-  inline static void computeGrayscaleDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _t, ushort& _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC1);
-    CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_1ch.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
-  inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t* const _t, ushort* _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3);
-    CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_3ch3t.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
-  inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t _t, ushort* _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3);
-    CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_3ch1t.i"
-  }
-
-  //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel-RGB version)
-  inline static void computeSingleRGBDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _c, const size_t _t, ushort& _res) {
-    CV_DbgAssert(!oInputImg.empty());
-    CV_DbgAssert(oInputImg.type() == CV_8UC3 && _c < 3);
-    CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
-    CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
-    CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
-    const size_t _step_row = oInputImg.step.p[0];
-    const uchar* const _data = oInputImg.data;
-#include "LBSP_16bits_dbcross_s3ch.i"
-  }
-
-  //! utility function, used to reshape a descriptors matrix to its input image size via their keypoint locations
-  static void reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput);
-  //! utility function, used to illustrate the difference between two descriptor images
-  static void calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels = false);
-  //! utility function, used to filter out bad keypoints that would trigger out of bounds error because they're too close to the image border
-  static void validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize);
-  //! utility function, used to filter out bad pixels in a ROI that would trigger out of bounds error because they're too close to the image border
-  static void validateROI(cv::Mat& oROI);
-  //! utility, specifies the pixel size of the pattern used (width and height)
-  static const size_t PATCH_SIZE = 5;
-  //! utility, specifies the number of bytes per descriptor (should be the same as calling 'descriptorSize()')
-  static const size_t DESC_SIZE = 2;
-
-protected:
-  //! classic 'compute' implementation, based on the regular DescriptorExtractor::computeImpl arguments & expected output
-  virtual void computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
-
-  const bool m_bOnlyUsingAbsThreshold;
-  const float m_fRelThreshold;
-  const size_t m_nThreshold;
-  cv::Mat m_oRefImage;
-};
diff --git a/package_bgs/LBSP/RandUtils.h b/package_bgs/LBSP/RandUtils.h
deleted file mode 100644
index f676ca08da83ee0478c762180664d1b9a9dc34e4..0000000000000000000000000000000000000000
--- a/package_bgs/LBSP/RandUtils.h
+++ /dev/null
@@ -1,112 +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
-
-/*// gaussian 3x3 pattern, based on 'floor(fspecial('gaussian', 3, 1)*256)'
-static const int s_nSamplesInitPatternWidth = 3;
-static const int s_nSamplesInitPatternHeight = 3;
-static const int s_nSamplesInitPatternTot = 256;
-static const int s_anSamplesInitPattern[s_nSamplesInitPatternHeight][s_nSamplesInitPatternWidth] = {
-    {19,    32,    19,},
-    {32,    52,    32,},
-    {19,    32,    19,},
-};*/
-
-// gaussian 7x7 pattern, based on 'floor(fspecial('gaussian',7,2)*512)'
-static const int s_nSamplesInitPatternWidth = 7;
-static const int s_nSamplesInitPatternHeight = 7;
-static const int s_nSamplesInitPatternTot = 512;
-static const int s_anSamplesInitPattern[s_nSamplesInitPatternHeight][s_nSamplesInitPatternWidth] = {
-  {2,     4,     6,     7,     6,     4,     2,},
-  {4,     8,    12,    14,    12,     8,     4,},
-  {6,    12,    21,    25,    21,    12,     6,},
-  {7,    14,    25,    28,    25,    14,     7,},
-  {6,    12,    21,    25,    21,    12,     6,},
-  {4,     8,    12,    14,    12,     8,     4,},
-  {2,     4,     6,     7,     6,     4,     2,},
-};
-
-//! returns a random init/sampling position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
-static inline void getRandSamplePosition(int& x_sample, int& y_sample, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
-  int r = 1+rand()%s_nSamplesInitPatternTot;
-  for(x_sample=0; x_sample<s_nSamplesInitPatternWidth; ++x_sample) {
-    for(y_sample=0; y_sample<s_nSamplesInitPatternHeight; ++y_sample) {
-      r -= s_anSamplesInitPattern[y_sample][x_sample];
-      if(r<=0)
-        goto stop;
-    }
-  }
-stop:
-  x_sample += x_orig-s_nSamplesInitPatternWidth/2;
-  y_sample += y_orig-s_nSamplesInitPatternHeight/2;
-  if(x_sample<border)
-    x_sample = border;
-  else if(x_sample>=imgsize.width-border)
-    x_sample = imgsize.width-border-1;
-  if(y_sample<border)
-    y_sample = border;
-  else if(y_sample>=imgsize.height-border)
-    y_sample = imgsize.height-border-1;
-}
-
-// simple 8-connected (3x3) neighbors pattern
-static const int s_anNeighborPatternSize_3x3 = 8;
-static const int s_anNeighborPattern_3x3[8][2] = {
-  {-1, 1},  { 0, 1},  { 1, 1},
-  {-1, 0},            { 1, 0},
-  {-1,-1},  { 0,-1},  { 1,-1},
-};
-
-//! returns a random neighbor position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
-static inline void getRandNeighborPosition_3x3(int& x_neighbor, int& y_neighbor, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
-  int r = rand()%s_anNeighborPatternSize_3x3;
-  x_neighbor = x_orig+s_anNeighborPattern_3x3[r][0];
-  y_neighbor = y_orig+s_anNeighborPattern_3x3[r][1];
-  if(x_neighbor<border)
-    x_neighbor = border;
-  else if(x_neighbor>=imgsize.width-border)
-    x_neighbor = imgsize.width-border-1;
-  if(y_neighbor<border)
-    y_neighbor = border;
-  else if(y_neighbor>=imgsize.height-border)
-    y_neighbor = imgsize.height-border-1;
-}
-
-// 5x5 neighbors pattern
-static const int s_anNeighborPatternSize_5x5 = 24;
-static const int s_anNeighborPattern_5x5[24][2] = {
-  {-2, 2},  {-1, 2},  { 0, 2},  { 1, 2},  { 2, 2},
-  {-2, 1},  {-1, 1},  { 0, 1},  { 1, 1},  { 2, 1},
-  {-2, 0},  {-1, 0},            { 1, 0},  { 2, 0},
-  {-2,-1},  {-1,-1},  { 0,-1},  { 1,-1},  { 2,-1},
-  {-2,-2},  {-1,-2},  { 0,-2},  { 1,-2},  { 2,-2},
-};
-
-//! returns a random neighbor position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
-static inline void getRandNeighborPosition_5x5(int& x_neighbor, int& y_neighbor, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
-  int r = rand()%s_anNeighborPatternSize_5x5;
-  x_neighbor = x_orig+s_anNeighborPattern_5x5[r][0];
-  y_neighbor = y_orig+s_anNeighborPattern_5x5[r][1];
-  if(x_neighbor<border)
-    x_neighbor = border;
-  else if(x_neighbor>=imgsize.width-border)
-    x_neighbor = imgsize.width-border-1;
-  if(y_neighbor<border)
-    y_neighbor = border;
-  else if(y_neighbor>=imgsize.height-border)
-    y_neighbor = imgsize.height-border-1;
-}
diff --git a/package_bgs/LBSimpleGaussian.cpp b/package_bgs/LBSimpleGaussian.cpp
deleted file mode 100644
index 9ce071c029e94969da5b07347bf4696a98dec84e..0000000000000000000000000000000000000000
--- a/package_bgs/LBSimpleGaussian.cpp
+++ /dev/null
@@ -1,96 +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 "LBSimpleGaussian.h"
-
-using namespace bgslibrary::algorithms;
-
-LBSimpleGaussian::LBSimpleGaussian() :
-  sensitivity(66), noiseVariance(162), learningRate(18)
-{
-  std::cout << "LBSimpleGaussian()" << std::endl;
-  setup("./config/LBSimpleGaussian.xml");
-}
-
-LBSimpleGaussian::~LBSimpleGaussian()
-{
-  delete m_pBGModel;
-  std::cout << "~LBSimpleGaussian()" << std::endl;
-}
-
-void LBSimpleGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  IplImage *frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    int w = cvGetSize(frame).width;
-    int h = cvGetSize(frame).height;
-
-    m_pBGModel = new BGModelGauss(w, h);
-    m_pBGModel->InitModel(frame);
-  }
-
-  m_pBGModel->setBGModelParameter(0, sensitivity);
-  m_pBGModel->setBGModelParameter(1, noiseVariance);
-  m_pBGModel->setBGModelParameter(2, learningRate);
-
-  m_pBGModel->UpdateModel(frame);
-
-  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("SG Mask", img_foreground);
-    cv::imshow("SG Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-
-  firstTime = false;
-}
-
-void LBSimpleGaussian::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "sensitivity", sensitivity);
-  cvWriteInt(fs, "noiseVariance", noiseVariance);
-  cvWriteInt(fs, "learningRate", learningRate);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LBSimpleGaussian::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 66);
-  noiseVariance = cvReadIntByName(fs, nullptr, "noiseVariance", 162);
-  learningRate = cvReadIntByName(fs, nullptr, "learningRate", 18);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LBSimpleGaussian.h b/package_bgs/LBSimpleGaussian.h
deleted file mode 100644
index 5c829234f86933736682ca4d41e9fa4f12bf550c..0000000000000000000000000000000000000000
--- a/package_bgs/LBSimpleGaussian.h
+++ /dev/null
@@ -1,48 +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
-
-#include "IBGS.h"
-#include "lb/BGModelGauss.h"
-
-using namespace lb_library;
-using namespace lb_library::SimpleGaussian;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LBSimpleGaussian : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int noiseVariance;
-      int learningRate;
-
-    public:
-      LBSimpleGaussian();
-      ~LBSimpleGaussian();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/LOBSTER.cpp b/package_bgs/LOBSTER.cpp
deleted file mode 100644
index dc48a63ba3a578e1ac0b8ebd9f123189827e2959..0000000000000000000000000000000000000000
--- a/package_bgs/LOBSTER.cpp
+++ /dev/null
@@ -1,98 +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 "LOBSTER.h"
-
-using namespace bgslibrary::algorithms;
-
-LOBSTER::LOBSTER() :
-  pLOBSTER(nullptr),
-  fRelLBSPThreshold(BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
-  nLBSPThresholdOffset(BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD),
-  nDescDistThreshold(BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD),
-  nColorDistThreshold(BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD),
-  nBGSamples(BGSLOBSTER_DEFAULT_NB_BG_SAMPLES),
-  nRequiredBGSamples(BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES)
-{
-  std::cout << "LOBSTER()" << std::endl;
-  setup("./config/LOBSTER.xml");
-}
-
-LOBSTER::~LOBSTER()
-{
-  if (pLOBSTER)
-    delete pLOBSTER;
-  std::cout << "~LOBSTER()" << std::endl;
-}
-
-void LOBSTER::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    pLOBSTER = new BackgroundSubtractorLOBSTER(
-      fRelLBSPThreshold, nLBSPThresholdOffset, nDescDistThreshold,
-      nColorDistThreshold, nBGSamples, nRequiredBGSamples);
-
-    pLOBSTER->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
-    firstTime = false;
-  }
-
-  pLOBSTER->apply(img_input, img_foreground);
-  pLOBSTER->getBackgroundImage(img_background);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    imshow("LOBSTER FG", img_foreground);
-    imshow("LOBSTER BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-}
-
-void LOBSTER::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "fRelLBSPThreshold", fRelLBSPThreshold);
-  cvWriteInt(fs, "nLBSPThresholdOffset", nLBSPThresholdOffset);
-  cvWriteInt(fs, "nDescDistThreshold", nDescDistThreshold);
-  cvWriteInt(fs, "nColorDistThreshold", nColorDistThreshold);
-  cvWriteInt(fs, "nBGSamples", nBGSamples);
-  cvWriteInt(fs, "nRequiredBGSamples", nRequiredBGSamples);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void LOBSTER::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  fRelLBSPThreshold = cvReadRealByName(fs, nullptr, "fRelLBSPThreshold", BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD);
-  nLBSPThresholdOffset = cvReadIntByName(fs, nullptr, "nLBSPThresholdOffset", BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD);
-  nDescDistThreshold = cvReadIntByName(fs, nullptr, "nDescDistThreshold", BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD);
-  nColorDistThreshold = cvReadIntByName(fs, nullptr, "nColorDistThreshold", BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD);
-  nBGSamples = cvReadIntByName(fs, nullptr, "nBGSamples", BGSLOBSTER_DEFAULT_NB_BG_SAMPLES);
-  nRequiredBGSamples = cvReadIntByName(fs, nullptr, "nRequiredBGSamples", BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/LOBSTER.h b/package_bgs/LOBSTER.h
deleted file mode 100644
index 41ba8828664215cf1b9201a1c9f64b748e43ff34..0000000000000000000000000000000000000000
--- a/package_bgs/LOBSTER.h
+++ /dev/null
@@ -1,49 +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
-
-#include "IBGS.h"
-#include "LBSP/BackgroundSubtractorLOBSTER.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class LOBSTER : public IBGS
-    {
-    private:
-      BackgroundSubtractorLOBSTER* pLOBSTER;
-
-      float fRelLBSPThreshold;
-      size_t nLBSPThresholdOffset;
-      size_t nDescDistThreshold;
-      size_t nColorDistThreshold;
-      size_t nBGSamples;
-      size_t nRequiredBGSamples;
-
-    public:
-      LOBSTER();
-      ~LOBSTER();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/MixtureOfGaussianV1.cpp b/package_bgs/MixtureOfGaussianV1.cpp
deleted file mode 100644
index e56609a64c69539e2e6638db5fc159b055d8ac9f..0000000000000000000000000000000000000000
--- a/package_bgs/MixtureOfGaussianV1.cpp
+++ /dev/null
@@ -1,100 +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 "MixtureOfGaussianV1.h"
-
-#if CV_MAJOR_VERSION == 2
-
-using namespace bgslibrary::algorithms;
-
-MixtureOfGaussianV1::MixtureOfGaussianV1() :
-  alpha(0.05), enableThreshold(true), threshold(15)
-{
-  std::cout << "MixtureOfGaussianV1()" << std::endl;
-  setup("./config/MixtureOfGaussianV1.xml");
-}
-
-MixtureOfGaussianV1::~MixtureOfGaussianV1()
-{
-  std::cout << "~MixtureOfGaussianV1()" << std::endl;
-}
-
-void MixtureOfGaussianV1::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  //------------------------------------------------------------------
-  // BackgroundSubtractorMOG
-  // http://opencv.itseez.com/modules/video/doc/motion_analysis_and_object_tracking.html#backgroundsubtractormog
-  //
-  // Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm.
-  //
-  // The class implements the algorithm described in:
-  //   P. KadewTraKuPong and R. Bowden,
-  //   An improved adaptive background mixture model for real-time tracking with shadow detection,
-  //   Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001
-  //------------------------------------------------------------------
-
-  mog(img_input, img_foreground, alpha);
-  mog.getBackgroundImage(img_background);
-
-  if (enableThreshold)
-    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
-
-  if (img_foreground.empty())
-    img_foreground = cv::Mat::zeros(img_input.size(), img_input.type());
-
-  if (img_background.empty())
-    img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("GMM FG (KadewTraKuPong&Bowden)", img_foreground);
-    cv::imshow("GMM BG (KadewTraKuPong&Bowden)", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void MixtureOfGaussianV1::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void MixtureOfGaussianV1::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.05);
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
-#endif
diff --git a/package_bgs/MixtureOfGaussianV1.h b/package_bgs/MixtureOfGaussianV1.h
deleted file mode 100644
index e18dbdbeae973b8d8e6c4b73504a5bea94050c5e..0000000000000000000000000000000000000000
--- a/package_bgs/MixtureOfGaussianV1.h
+++ /dev/null
@@ -1,53 +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
-
-#include "opencv2/core/version.hpp"
-#if CV_MAJOR_VERSION == 2
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-#include <opencv2/video/background_segm.hpp>
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class MixtureOfGaussianV1 : public IBGS
-    {
-    private:
-      cv::BackgroundSubtractorMOG mog;
-      double alpha;
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      MixtureOfGaussianV1();
-      ~MixtureOfGaussianV1();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
-
-#endif
diff --git a/package_bgs/MixtureOfGaussianV2.h b/package_bgs/MixtureOfGaussianV2.h
deleted file mode 100644
index edc8add6c693988fd2bc9c06815b0b6e4d01c9ca..0000000000000000000000000000000000000000
--- a/package_bgs/MixtureOfGaussianV2.h
+++ /dev/null
@@ -1,52 +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
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-#include <opencv2/video/background_segm.hpp>
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class MixtureOfGaussianV2 : public IBGS
-    {
-    private:
-#if CV_MAJOR_VERSION == 2
-      cv::BackgroundSubtractorMOG2 mog;
-#elif CV_MAJOR_VERSION == 3
-      cv::Ptr<cv::BackgroundSubtractorMOG2> mog;
-#endif
-      double alpha;
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      MixtureOfGaussianV2();
-      ~MixtureOfGaussianV2();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/MultiLayer.cpp b/package_bgs/MultiLayer.cpp
deleted file mode 100644
index 180d88d74a7fdded44fd4700038d3dbbe0ac9ade..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer.cpp
+++ /dev/null
@@ -1,330 +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 "MultiLayer.h"
-
-using namespace bgslibrary::algorithms;
-
-MultiLayer::MultiLayer() :
-  frameNumber(0), saveModel(false), disableDetectMode(true), disableLearning(false),
-  detectAfter(0), bg_model_preload(""), loadDefaultParams(true)
-{
-  std::cout << "MultiLayer()" << std::endl;
-  setup("./config/MultiLayer.xml");
-}
-
-MultiLayer::~MultiLayer()
-{
-  finish();
-  std::cout << "~MultiLayer()" << std::endl;
-}
-
-void MultiLayer::setStatus(Status _status)
-{
-  status = _status;
-}
-
-void MultiLayer::finish()
-{
-  if (bg_model_preload.empty())
-  {
-    bg_model_preload = "./MultiLayerModel.yml";
-    saveConfig();
-  }
-
-  if (status == MLBGS_LEARN && saveModel == true)
-  {
-    std::cout << "MultiLayer saving background model: " << bg_model_preload << std::endl;
-    BGS->Save(bg_model_preload.c_str());
-  }
-
-  cvReleaseImage(&fg_img);
-  cvReleaseImage(&bg_img);
-  cvReleaseImage(&fg_prob_img);
-  cvReleaseImage(&fg_mask_img);
-  cvReleaseImage(&fg_prob_img3);
-  cvReleaseImage(&merged_img);
-
-  delete BGS;
-}
-
-void MultiLayer::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-  CvSize img_size = cvSize(cvCeil((double)img_input.size().width), cvCeil((double)img_input.size().height));
-
-  if (firstTime)
-  {
-    if (disableDetectMode)
-      status = MLBGS_LEARN;
-
-    if (status == MLBGS_LEARN)
-      std::cout << "MultiLayer in LEARN mode" << std::endl;
-
-    if (status == MLBGS_DETECT)
-      std::cout << "MultiLayer in DETECT mode" << std::endl;
-
-    org_img = new IplImage(img_input);
-
-    fg_img = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
-    bg_img = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
-    fg_prob_img = cvCreateImage(img_size, org_img->depth, 1);
-    fg_mask_img = cvCreateImage(img_size, org_img->depth, 1);
-    fg_prob_img3 = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
-    merged_img = cvCreateImage(cvSize(img_size.width * 2, img_size.height * 2), org_img->depth, org_img->nChannels);
-
-    BGS = new CMultiLayerBGS();
-    BGS->Init(img_size.width, img_size.height);
-    BGS->SetForegroundMaskImage(fg_mask_img);
-    BGS->SetForegroundProbImage(fg_prob_img);
-
-    if (bg_model_preload.empty() == false)
-    {
-      std::cout << "MultiLayer loading background model: " << bg_model_preload << std::endl;
-      BGS->Load(bg_model_preload.c_str());
-    }
-
-    if (status == MLBGS_DETECT)
-    {
-      BGS->m_disableLearning = disableLearning;
-
-      if (disableLearning)
-        std::cout << "MultiLayer disabled learning in DETECT mode" << std::endl;
-      else
-        std::cout << "MultiLayer enabled learning in DETECT mode" << std::endl;
-    }
-
-    if (loadDefaultParams)
-    {
-      std::cout << "MultiLayer loading default params" << std::endl;
-
-      max_mode_num = 5;
-      weight_updating_constant = 5.0;
-      texture_weight = 0.5;
-      bg_mode_percent = 0.6f;
-      pattern_neig_half_size = 4;
-      pattern_neig_gaus_sigma = 3.0f;
-      bg_prob_threshold = 0.2f;
-      bg_prob_updating_threshold = 0.2f;
-      robust_LBP_constant = 3;
-      min_noised_angle = 10.0 / 180.0 * PI; //0,01768
-      shadow_rate = 0.6f;
-      highlight_rate = 1.2f;
-      bilater_filter_sigma_s = 3.0f;
-      bilater_filter_sigma_r = 0.1f;
-    }
-    else
-      std::cout << "MultiLayer loading config params" << std::endl;
-
-    BGS->m_nMaxLBPModeNum = max_mode_num;
-    BGS->m_fWeightUpdatingConstant = weight_updating_constant;
-    BGS->m_fTextureWeight = texture_weight;
-    BGS->m_fBackgroundModelPercent = bg_mode_percent;
-    BGS->m_nPatternDistSmoothNeigHalfSize = pattern_neig_half_size;
-    BGS->m_fPatternDistConvGaussianSigma = pattern_neig_gaus_sigma;
-    BGS->m_fPatternColorDistBgThreshold = bg_prob_threshold;
-    BGS->m_fPatternColorDistBgUpdatedThreshold = bg_prob_updating_threshold;
-    BGS->m_fRobustColorOffset = robust_LBP_constant;
-    BGS->m_fMinNoisedAngle = min_noised_angle;
-    BGS->m_fRobustShadowRate = shadow_rate;
-    BGS->m_fRobustHighlightRate = highlight_rate;
-    BGS->m_fSigmaS = bilater_filter_sigma_s;
-    BGS->m_fSigmaR = bilater_filter_sigma_r;
-
-    if (loadDefaultParams)
-    {
-      //frame_duration = 1.0 / 30.0;
-      //frame_duration = 1.0 / 25.0;
-      frame_duration = 1.0f / 10.0f;
-    }
-
-    BGS->SetFrameRate(frame_duration);
-
-    if (status == MLBGS_LEARN)
-    {
-      if (loadDefaultParams)
-      {
-        mode_learn_rate_per_second = 0.5;
-        weight_learn_rate_per_second = 0.5;
-        init_mode_weight = 0.05f;
-      }
-      else
-      {
-        mode_learn_rate_per_second = learn_mode_learn_rate_per_second;
-        weight_learn_rate_per_second = learn_weight_learn_rate_per_second;
-        init_mode_weight = learn_init_mode_weight;
-      }
-    }
-
-    if (status == MLBGS_DETECT)
-    {
-      if (loadDefaultParams)
-      {
-        mode_learn_rate_per_second = 0.01f;
-        weight_learn_rate_per_second = 0.01f;
-        init_mode_weight = 0.001f;
-      }
-      else
-      {
-        mode_learn_rate_per_second = detect_mode_learn_rate_per_second;
-        weight_learn_rate_per_second = detect_weight_learn_rate_per_second;
-        init_mode_weight = detect_init_mode_weight;
-      }
-    }
-
-    BGS->SetParameters(max_mode_num, mode_learn_rate_per_second, weight_learn_rate_per_second, init_mode_weight);
-    delete org_img;
-  }
-
-  //IplImage* inputImage = new IplImage(img_input);
-  //IplImage* img = cvCreateImage(img_size, IPL_DEPTH_8U, 3);
-  //cvCopy(inputImage, img);
-  //delete inputImage;
-
-  if (detectAfter > 0 && detectAfter == frameNumber)
-  {
-    std::cout << "MultiLayer in DETECT mode" << std::endl;
-
-    status = MLBGS_DETECT;
-
-    mode_learn_rate_per_second = 0.01f;
-    weight_learn_rate_per_second = 0.01f;
-    init_mode_weight = 0.001f;
-
-    BGS->SetParameters(max_mode_num, mode_learn_rate_per_second, weight_learn_rate_per_second, init_mode_weight);
-
-    BGS->m_disableLearning = disableLearning;
-
-    if (disableLearning)
-      std::cout << "MultiLayer disabled learning in DETECT mode" << std::endl;
-    else
-      std::cout << "MultiLayer enabled learning in DETECT mode" << std::endl;
-  }
-
-  IplImage* img = new IplImage(img_input);
-
-  BGS->SetRGBInputImage(img);
-  BGS->Process();
-
-  BGS->GetBackgroundImage(bg_img);
-  BGS->GetForegroundImage(fg_img);
-  BGS->GetForegroundProbabilityImage(fg_prob_img3);
-  BGS->GetForegroundMaskImage(fg_mask_img);
-  BGS->MergeImages(4, img, bg_img, fg_prob_img3, fg_img, merged_img);
-
-  img_merged = cv::cvarrToMat(merged_img);
-  img_foreground = cv::cvarrToMat(fg_mask_img);
-  img_background = cv::cvarrToMat(bg_img);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("MLBGS Layers", img_merged);
-    cv::imshow("MLBGS FG Mask", img_foreground);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete img;
-  //cvReleaseImage(&img);
-
-  firstTime = false;
-  frameNumber++;
-}
-
-void MultiLayer::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteString(fs, "preloadModel", bg_model_preload.c_str());
-  cvWriteInt(fs, "saveModel", saveModel);
-  cvWriteInt(fs, "detectAfter", detectAfter);
-  cvWriteInt(fs, "disableDetectMode", disableDetectMode);
-  cvWriteInt(fs, "disableLearningInDetecMode", disableLearning);
-  cvWriteInt(fs, "loadDefaultParams", loadDefaultParams);
-
-  cvWriteInt(fs, "max_mode_num", max_mode_num);
-  cvWriteReal(fs, "weight_updating_constant", weight_updating_constant);
-  cvWriteReal(fs, "texture_weight", texture_weight);
-  cvWriteReal(fs, "bg_mode_percent", bg_mode_percent);
-  cvWriteInt(fs, "pattern_neig_half_size", pattern_neig_half_size);
-  cvWriteReal(fs, "pattern_neig_gaus_sigma", pattern_neig_gaus_sigma);
-  cvWriteReal(fs, "bg_prob_threshold", bg_prob_threshold);
-  cvWriteReal(fs, "bg_prob_updating_threshold", bg_prob_updating_threshold);
-  cvWriteInt(fs, "robust_LBP_constant", robust_LBP_constant);
-  cvWriteReal(fs, "min_noised_angle", min_noised_angle);
-  cvWriteReal(fs, "shadow_rate", shadow_rate);
-  cvWriteReal(fs, "highlight_rate", highlight_rate);
-  cvWriteReal(fs, "bilater_filter_sigma_s", bilater_filter_sigma_s);
-  cvWriteReal(fs, "bilater_filter_sigma_r", bilater_filter_sigma_r);
-
-  cvWriteReal(fs, "frame_duration", frame_duration);
-
-  cvWriteReal(fs, "learn_mode_learn_rate_per_second", learn_mode_learn_rate_per_second);
-  cvWriteReal(fs, "learn_weight_learn_rate_per_second", learn_weight_learn_rate_per_second);
-  cvWriteReal(fs, "learn_init_mode_weight", learn_init_mode_weight);
-
-  cvWriteReal(fs, "detect_mode_learn_rate_per_second", detect_mode_learn_rate_per_second);
-  cvWriteReal(fs, "detect_weight_learn_rate_per_second", detect_weight_learn_rate_per_second);
-  cvWriteReal(fs, "detect_init_mode_weight", detect_init_mode_weight);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void MultiLayer::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  bg_model_preload = cvReadStringByName(fs, nullptr, "preloadModel", "");
-  saveModel = cvReadIntByName(fs, nullptr, "saveModel", false);
-  detectAfter = cvReadIntByName(fs, nullptr, "detectAfter", 0);
-  disableDetectMode = cvReadIntByName(fs, nullptr, "disableDetectMode", true);
-  disableLearning = cvReadIntByName(fs, nullptr, "disableLearningInDetecMode", false);
-  loadDefaultParams = cvReadIntByName(fs, nullptr, "loadDefaultParams", true);
-
-  max_mode_num = cvReadIntByName(fs, nullptr, "max_mode_num", 5);
-  weight_updating_constant = cvReadRealByName(fs, 0, "weight_updating_constant", 5.0);
-  texture_weight = cvReadRealByName(fs, nullptr, "texture_weight", 0.5);
-  bg_mode_percent = cvReadRealByName(fs, nullptr, "bg_mode_percent", 0.6);
-  pattern_neig_half_size = cvReadIntByName(fs, nullptr, "pattern_neig_half_size", 4);
-  pattern_neig_gaus_sigma = cvReadRealByName(fs, nullptr, "pattern_neig_gaus_sigma", 3.0);
-  bg_prob_threshold = cvReadRealByName(fs, nullptr, "bg_prob_threshold", 0.2);
-  bg_prob_updating_threshold = cvReadRealByName(fs, nullptr, "bg_prob_updating_threshold", 0.2);
-  robust_LBP_constant = cvReadIntByName(fs, nullptr, "robust_LBP_constant", 3);
-  min_noised_angle = cvReadRealByName(fs, nullptr, "min_noised_angle", 0.01768);
-  shadow_rate = cvReadRealByName(fs, nullptr, "shadow_rate", 0.6);
-  highlight_rate = cvReadRealByName(fs, nullptr, "highlight_rate", 1.2);
-  bilater_filter_sigma_s = cvReadRealByName(fs, nullptr, "bilater_filter_sigma_s", 3.0);
-  bilater_filter_sigma_r = cvReadRealByName(fs, nullptr, "bilater_filter_sigma_r", 0.1);
-
-  frame_duration = cvReadRealByName(fs, nullptr, "frame_duration", 0.1);
-
-  learn_mode_learn_rate_per_second = cvReadRealByName(fs, nullptr, "learn_mode_learn_rate_per_second", 0.5);
-  learn_weight_learn_rate_per_second = cvReadRealByName(fs, nullptr, "learn_weight_learn_rate_per_second", 0.5);
-  learn_init_mode_weight = cvReadRealByName(fs, nullptr, "learn_init_mode_weight", 0.05);
-
-  detect_mode_learn_rate_per_second = cvReadRealByName(fs, nullptr, "detect_mode_learn_rate_per_second", 0.01);
-  detect_weight_learn_rate_per_second = cvReadRealByName(fs, nullptr, "detect_weight_learn_rate_per_second", 0.01);
-  detect_init_mode_weight = cvReadRealByName(fs, nullptr, "detect_init_mode_weight", 0.001);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/MultiLayer/BGS.h b/package_bgs/MultiLayer/BGS.h
deleted file mode 100644
index ad2129bccbfdfbce8164925eddfee7aef07853fb..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BGS.h
+++ /dev/null
@@ -1,212 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-#pragma once
-
-#include "OpenCvLegacyIncludes.h"
-
-
-// TODO check these defines are not used (or not redundant with real params)
-#define MAX_LBP_MODE_NUM	5
-
-#define ROBUST_COLOR_OFFSET	6.0f
-
-#define LOW_INITIAL_MODE_WEIGHT	0.01f
-
-#define MODE_UPDATING_LEARN_RATE	0.01f
-#define WEIGHT_UPDATING_LEARN_RATE	0.01f
-
-#define COLOR_MAX_MIN_OFFSET		5
-
-#define BACKGROUND_MODEL_PERCENT	0.6f
-
-#define PATTERN_COLOR_DIST_BACKGROUND_THRESHOLD	0.2f
-
-#define PATTERN_DIST_SMOOTH_NEIG_HALF_SIZE	6
-#define PATTERN_DIST_CONV_GAUSSIAN_SIGMA	2.5f
-
-#define ROBUST_SHADOW_RATE	0.6f
-#define ROBUST_HIGHLIGHT_RATE	1.20f
-
-#define BINARY_PATTERM_ELEM(c1, c2, offset)	\
-  ((float)(c2)-(float)(c1)+offset > 0)
-
-/*
-#define BINARY_PATTERM_ELEM(c1, c2, offset)	\
-( fabsf((float)(c2)-(float)(c1)) <= offset ? 1 : (float)(c2)-(float)(c1) >=0 )
-*/
-
-#ifndef PI
-#define PI 3.141592653589793f
-#endif
-
-/************************************************************************/
-/* some data structures for multi-level LBP (local binary pattern)      */
-/* texture feature for background subtraction                           */
-/************************************************************************/
-typedef struct _LBP
-{
-  float* bg_pattern;			/* the average local binary pattern of background mode */
-  float* bg_intensity;			/* the average color intensity of background mode */
-  float* max_intensity;			/* the maximal color intensity of background mode */
-  float* min_intensity;			/* the minimal color intensity of background mode */
-  float weight;				/* the weight of background mode, i.e. probability that the background mode belongs to background */
-  float max_weight;			/* the maximal weight of background mode */
-  int bg_layer_num;			/* the background layer number of background mode */
-  unsigned long first_time;				/* the first time of background mode appearing */
-  unsigned long last_time;				/* the last time of background model appearing */
-  int freq;				/* the appearing frequency */
-  //long mnrl;				/* maximum negative run-length */
-  unsigned long layer_time;				/* the first time of background mode becoming a background layer */
-}
-LBPStruct;
-
-typedef struct _PixelLBP
-{
-  LBPStruct* LBPs;			/* the background modes */
-  unsigned short* lbp_idxes;		/* the indices of background modes */
-  unsigned int cur_bg_layer_no;
-  unsigned int num;			/* the total number of background modes */
-  unsigned int bg_num;			/* the number of the first background modes for foreground detection */
-  unsigned char* cur_intensity;		/* the color intensity of current pixel */
-  float* cur_pattern;			/* the local binary pattern of current pixel */
-  float matched_mode_first_time;		/* the index of currently matched pixel mode */
-}
-PixelLBPStruct;
-
-/*********************************************************************************/
-/* should replace the above structure using class in the future (not finished)   */
-/*********************************************************************************/
-
-class BG_PIXEL_MODE
-{
-public:
-  float* bg_lbp_pattern;			/* the average local binary pattern of background mode */
-  float* bg_intensity;			/* the average color intensity of background mode */
-  float* max_intensity;			/* the maximal color intensity of background mode */
-  float* min_intensity;			/* the minimal color intensity of background mode */
-  float weight;				/* the weight of background mode, i.e. probability that the background mode belongs to background */
-  float max_weight;			/* the maximal weight of background mode */
-  int bg_layer_num;			/* the background layer number of background mode */
-
-  int lbp_pattern_length;
-  int color_channel;
-
-  BG_PIXEL_MODE(int _lbp_pattern_length, int _color_channel = 3) {
-    lbp_pattern_length = _lbp_pattern_length;
-    color_channel = _color_channel;
-
-    bg_lbp_pattern = new float[lbp_pattern_length];
-    bg_intensity = new float[color_channel];
-    max_intensity = new float[color_channel];
-    min_intensity = new float[color_channel];
-  };
-
-  virtual ~BG_PIXEL_MODE() {
-    delete[] bg_lbp_pattern;
-    delete[] bg_intensity;
-    delete[] max_intensity;
-    delete[] min_intensity;
-  };
-};
-
-class BG_PIXEL_PATTERN
-{
-public:
-  BG_PIXEL_MODE** pixel_MODEs;		/* the background modes */
-  unsigned short* lbp_pattern_idxes;	/* the indices of background modes */
-  unsigned int cur_bg_layer_no;
-  unsigned int num;			/* the total number of background modes */
-  unsigned int bg_num;			/* the number of the first background modes for foreground detection */
-  unsigned char* cur_intensity;		/* the color intensity of current pixel */
-  float* cur_lbp_pattern;			/* the local binary pattern of current pixel */
-
-  int lbp_pattern_length;
-  int color_channel;
-  int pixel_mode_num;
-
-  BG_PIXEL_PATTERN(int _pixel_mode_num, int _lbp_pattern_length, int _color_channel = 3) {
-    pixel_mode_num = _pixel_mode_num;
-    lbp_pattern_length = _lbp_pattern_length;
-    color_channel = _color_channel;
-
-    pixel_MODEs = new BG_PIXEL_MODE*[pixel_mode_num];
-
-    for (int i = 0; i < pixel_mode_num; i++) {
-      pixel_MODEs[i] = new BG_PIXEL_MODE(_lbp_pattern_length, _color_channel);
-    }
-
-    lbp_pattern_idxes = new unsigned short[pixel_mode_num];
-    cur_intensity = new unsigned char[color_channel];
-    cur_lbp_pattern = new float[lbp_pattern_length];
-  };
-
-  virtual ~BG_PIXEL_PATTERN() {
-    delete[] lbp_pattern_idxes;
-    delete[] cur_intensity;
-    delete[] cur_lbp_pattern;
-
-    for (int i = 0; i < pixel_mode_num; i++)
-      delete pixel_MODEs[i];
-    delete[] pixel_MODEs;
-  };
-};
-
-class IMAGE_BG_MODEL
-{
-  int pixel_length;
-
-  BG_PIXEL_PATTERN** pixel_PATTERNs;
-
-  IMAGE_BG_MODEL(int _pixel_length, int _pixel_mode_num, int _lbp_pattern_length, int _color_channel = 3) {
-    pixel_length = _pixel_length;
-
-    pixel_PATTERNs = new BG_PIXEL_PATTERN*[pixel_length];
-    for (int i = 0; i < pixel_length; i++)
-      pixel_PATTERNs[i] = new BG_PIXEL_PATTERN(_pixel_mode_num, _lbp_pattern_length, _color_channel);
-  }
-  virtual ~IMAGE_BG_MODEL() {
-    for (int i = 0; i < pixel_length; i++)
-      delete pixel_PATTERNs[i];
-    delete[] pixel_PATTERNs;
-  }
-};
diff --git a/package_bgs/MultiLayer/BackgroundSubtractionAPI.h b/package_bgs/MultiLayer/BackgroundSubtractionAPI.h
deleted file mode 100644
index 409fa4049d2cda20f7c92506e90e16bc60e5cfed..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BackgroundSubtractionAPI.h
+++ /dev/null
@@ -1,153 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-//////////////////////////////////////////////////////////////////////
-//
-// BackgroundSubtractionAPI.h: 
-//   interface for the BackgroundSubtractionAPI class.
-//
-// A background subtraction algorithm takes as input
-// an RGB image and provide as ouput a Binary mask
-// with a value of 0 for points belonging to the 
-// background, and non zero for points belonging
-// to the foreground.
-//
-//
-//
-// To add:
-//  - a function indicating the valid input and ouput
-//    images 
-//     e.g. RGB  image (default) or greylevel image for the input
-//          char image for the output
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include "OpenCvLegacyIncludes.h"
-
-class CBackgroundSubtractionAPI
-{
-public:
-  //CBackgroundSubtractionAPI(){};
-  //virtual ~CBackgroundSubtractionAPI(){};
-
-  //-------------------------------------------------------------
-  // TO CALL AT INITIALISATION: DEFINES THE SIZE OF THE INPUT IMAGES
-  // NORMALLY, UNNECESSARY IF A CONFIGURATION FILE IS LOADED
-  void   Init(int width, int height);
-
-  //-------------------------------------------------------------
-  // PROVIDE A MASK TO DEFINE THE SET OF POINTS WHERE BACKGROUND
-  // SUBTRACTION DOES NOT NEED TO BE PERFORMED
-  //
-  //  mode is useful to specify if the points to remove from
-  //  processing are in addition to the ones potentially
-  //  removed according to the configuration file,
-  //  or if they are the only ones to be removed
-  //
-  // mode=0 : provided points need to be removed
-  //          in addition to those already removed
-  // mode=1 : the provided points are the only one to remove
-  //          from processing
-  // Note:  maskImage(li,co)=0 indicate the points to remove
-  //       from background processing
-  void   SetValidPointMask(IplImage* maskImage, int mode);
-
-  //-------------------------------------------------------------
-  //
-  //   set the frame rate, to adjust the update parameters
-  //   to the actual frame rate.
-  //   Can be called only once at initialisation,
-  //   but in online cases, can be used to indicate
-  //   the time interval during the last processed frame
-  //
-  //   frameDuration is in millisecond
-  void   SetFrameRate(float    frameDuration);
-
-  //-------------------------------------------------------------
-  //   PROVIDE A POINTER TO THE INPUT IMAGE
-  //   -> INDICATE WHERE THE NEW IMAGE TO PROCESS IS STORED
-  //
-  //   Here assumes that the input image will contain RGB images.
-  //   The memory of this image is handled by the caller.
-  //
-  //    The return value indicate whether the actual Background
-  //    Subtraction algorithm handles RGB images (1) or not (0).
-  //
-  int  SetRGBInputImage(IplImage  *  inputImage);
-
-  //-------------------------------------------------------------
-  //   PROVIDE A POINTER TO THE RESULT IMAGE
-  //   INDICATE WHERE THE BACKGROUND RESULT NEED TO BE STORED
-  //
-  //   The return value is 1 if correct image format is provided,
-  //   otherwise the return value is 0.
-  //   e.g. fg_mask_img = cvCreateImage(imgSize, IPL_DEPTH_8U, 1);
-  int  SetForegroundMaskImage(IplImage *fg_mask_img);
-
-  //   The return value is 1 if the function is implemented
-  //   with correct format, otherwise the return value is 0
-  //   e.g. fg_prob_img = cvCreateImage(imgSize, IPL_DEPTH_32F, 1);
-  int  SetForegroundProbImage(IplImage *fg_prob_img);
-
-  //-------------------------------------------------------------
-  // This function should be called each time a new image is
-  // available in the input image.
-  //
-  // The return value is 1 if everything goes well,
-  // otherwise the return value is 0.
-  //
-  int   Process();
-
-  //-------------------------------------------------------------
-  // this function should save parameters and information of the model
-  // (e.g. after a training of the model, or in such a way
-  // that the model can be reload to process the next frame
-  // type of save:
-  void   Save(char   *bg_model_fn);
-
-  //-------------------------------------------------------------
-  // this function should load the parameters necessary
-  // for the processing of the background subtraction or
-  // load background model information
-  void   Load(char  *bg_model_fn);
-};
diff --git a/package_bgs/MultiLayer/BlobExtraction.cpp b/package_bgs/MultiLayer/BlobExtraction.cpp
deleted file mode 100644
index 7aecd65b2577f162333674f84c5263f7a0c32128..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BlobExtraction.cpp
+++ /dev/null
@@ -1,1496 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-//***********************************************************//
-//* Blob analysis package  8 August 2003                    *//
-//* Version 1.0                                             *//
-//* Input: IplImage* binary image                           *//
-//* Output: attributes of each connected region             *//
-//* Author: Dave Grossman                                   *//
-//* Modifications: Francesc Pinyol and Ricard Borras		*//
-//* Email: dgrossman@cdr.stanford.edu                       *//
-//* Email: fpinyol@cvc.uab.es rborras@cvc.uab.es            *//
-//* Acknowledgement: the algorithm has been around > 20 yrs *//
-//***********************************************************//
-
-//! Indica si la connectivitat es a 8 (si es desactiva es a 4)
-#define B_CONNECTIVITAT_8
-
-//! si la imatge és cíclica verticalment (els blobs que toquen
-//! les vores superior i inferior no es consideren externs)
-#define IMATGE_CICLICA_VERTICAL		1
-//! si la imatge és cíclica horitzontalment (els blobs que toquen
-//! les vores dreta i esquerra no es consideren externs)
-#define IMATGE_CICLICA_HORITZONTAL	0
-
-#define PERIMETRE_DIAGONAL (1.41421356237310 - 2)
-#define SQRT2	1.41421356237310
-// color dels píxels de la màscara per ser exteriors
-#define PIXEL_EXTERIOR 0
-
-
-#include "BlobResult.h"
-#include "BlobExtraction.h"
-#include "OpenCvLegacyIncludes.h"
-
-namespace Blob
-{
-
-  /**
-    - FUNCIÓ: BlobAnalysis
-    - FUNCIONALITAT: Extreu els blobs d'una imatge d'un sol canal
-    - PARÀMETRES:
-    - inputImage: Imatge d'entrada. Ha de ser d'un sol canal
-    - threshold: Nivell de gris per considerar un pixel blanc o negre
-    - maskImage: Imatge de màscara fora de la cual no es calculen els blobs. A més,
-    els blobs que toquen els pixels de la màscara a 0, són considerats
-    externs
-    - borderColor: Color del marc de la imatge (0=black or 1=white)
-    - findmoments: calcula els moments dels blobs o no
-    - RegionData: on es desarà el resultat
-    - RESULTAT:
-    - retorna true si tot ha anat bé, false si no. Deixa el resultat a blobs.
-    - RESTRICCIONS:
-    - La imatge d'entrada ha de ser d'un sol canal
-    - AUTOR: dgrossman@cdr.stanford.edu
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    - fpinyol@cvc.uab.es, rborras@cvc.uab.es: adaptació a les OpenCV
-    */
-  bool BlobAnalysis(IplImage* inputImage,
-    uchar threshold,
-    IplImage* maskImage,
-    bool borderColor,
-    bool findmoments,
-    blob_vector &RegionData)
-  {
-    // dimensions of input image taking in account the ROI
-    int Cols, Rows, startCol, startRow;
-
-    if (inputImage->roi)
-    {
-      CvRect imageRoi = cvGetImageROI(inputImage);
-      startCol = imageRoi.x;
-      startRow = imageRoi.y;
-      Cols = imageRoi.width;
-      Rows = imageRoi.height;
-    }
-    else
-    {
-      startCol = 0;
-      startRow = 0;
-      Cols = inputImage->width;
-      Rows = inputImage->height;
-    }
-
-    int Trans = Cols;				// MAX trans in any row
-    char* pMask = NULL;
-    char* pImage;
-
-    // Convert image array into transition array. In each row
-    // the transition array tells which columns have a color change
-    int iCol, iRow, iTran, Tran;				// Data for a given run
-    bool ThisCell, LastCell;		// Contents (colors (0 or 1)) within this row
-    int TransitionOffset = 0;		// Performance booster to avoid multiplication
-
-    // row 0 and row Rows+1 represent the border
-    int i;
-    int *Transition;				// Transition Matrix
-
-    int nombre_pixels_mascara = 0;
-    //! Imatge amb el perimetre extern de cada pixel
-    IplImage *imatgePerimetreExtern;
-
-    // input images must have only 1-channel and be an image
-    if (!CV_IS_IMAGE(inputImage) || (inputImage->nChannels != 1))
-    {
-      return false;
-    }
-    if (maskImage != NULL)
-    {
-      // input image and mask are a valid image?
-      if (!CV_IS_IMAGE(inputImage) || !CV_IS_IMAGE(maskImage))
-        return false;
-
-      // comprova que la màscara tingui les mateixes dimensions que la imatge
-      if (inputImage->width != maskImage->width || inputImage->height != maskImage->height)
-      {
-        return false;
-      }
-
-      // comprova que la màscara sigui una imatge d'un sol canal (grayscale)
-      if (maskImage->nChannels != 1)
-      {
-        return false;
-      }
-
-    }
-
-    // Initialize Transition array
-    Transition = new int[(Rows + 2)*(Cols + 2)];
-    memset(Transition, 0, (Rows + 2) * (Cols + 2) * sizeof(int));
-    Transition[0] = Transition[(Rows + 1) * (Cols + 2)] = Cols + 2;
-
-    // Start at the beginning of the image (startCol, startRow)
-    pImage = inputImage->imageData + startCol - 1 + startRow * inputImage->widthStep;
-
-    /*
-      Paral·lelització del càlcul de la matriu de transicions
-      Fem que cada iteració del for el faci un thread o l'altre ( tenim 2 possibles threads )
-      */
-    if (maskImage == NULL)
-    {
-      imatgePerimetreExtern = NULL;
-
-      //Fill Transition array
-      for (iRow = 1; iRow < Rows + 1; iRow++)		// Choose a row of Bordered image
-      {
-        TransitionOffset = iRow*(Cols + 2); //per a que sigui paral·litzable
-        iTran = 0;					// Index into Transition array
-        Tran = 0;					// No transitions at row start
-        LastCell = borderColor;
-
-        for (iCol = 0; iCol < Cols + 2; iCol++)	// Scan that row of Bordered image
-        {
-          if (iCol == 0 || iCol == Cols + 1)
-            ThisCell = borderColor;
-          else
-            ThisCell = ((unsigned char)*(pImage)) > threshold;
-
-          if (ThisCell != LastCell)
-          {
-            Transition[TransitionOffset + iTran] = Tran;	// Save completed Tran
-            iTran++;						// Prepare new index
-            LastCell = ThisCell;			// With this color
-          }
-
-          Tran++;	// Tran continues
-          pImage++;
-        }
-
-        Transition[TransitionOffset + iTran] = Tran;	// Save completed run
-        if ((TransitionOffset + iTran + 1) < (Rows + 1)*(Cols + 2))
-        {
-          Transition[TransitionOffset + iTran + 1] = -1;
-        }
-        //jump to next row (beginning from (startCol, startRow))
-        pImage = inputImage->imageData - 1 + startCol + (iRow + startRow)*inputImage->widthStep;
-      }
-    }
-    else
-    {
-      //maskImage not NULL: Cal recòrrer la màscara també per calcular la matriu de transicions
-
-      char perimeter;
-      char *pPerimetre;
-
-      // creem la imatge que contindrà el perimetre extern de cada pixel
-      imatgePerimetreExtern = cvCreateImage(cvSize(maskImage->width, maskImage->height), IPL_DEPTH_8U, 1);
-      cvSetZero(imatgePerimetreExtern);
-
-      pMask = maskImage->imageData - 1;
-
-      //Fill Transition array
-      for (iRow = 1; iRow < Rows + 1; iRow++)		// Choose a row of Bordered image
-      {
-        TransitionOffset = iRow*(Cols + 2);
-        iTran = 0;					// Index into Transition array
-        Tran = 0;					// No transitions at row start
-        LastCell = borderColor;
-
-        pPerimetre = imatgePerimetreExtern->imageData + (iRow - 1) * imatgePerimetreExtern->widthStep;
-        //pMask = maskImage->imageData + (iRow-1) * maskImage->widthStep;
-
-        for (iCol = 0; iCol < Cols + 2; iCol++)	// Scan that row of Bordered image
-        {
-          if (iCol == 0 || iCol == Cols + 1 || ((unsigned char)*pMask) == PIXEL_EXTERIOR)
-            ThisCell = borderColor;
-          else
-            ThisCell = ((unsigned char)*(pImage)) > threshold;
-
-          if (ThisCell != LastCell)
-          {
-            Transition[TransitionOffset + iTran] = Tran;	// Save completed Tran
-            iTran++;						// Prepare new index
-            LastCell = ThisCell;			// With this color
-          }
-
-          /*////////////////////////////////////////////////////////////////////////
-            Calcul de la imatge amb els pixels externs
-            ////////////////////////////////////////////////////////////////////////*/
-            // pels pixels externs no cal calcular res pq no hi accedir-hem
-          if ((iCol > 0) && (iCol < Cols))
-          {
-            if (*pMask == PIXEL_EXTERIOR)
-            {
-              *pPerimetre = 0;
-            }
-            else
-            {
-              perimeter = 0;
-
-              // pixels al nord de l'actual
-              if (iRow > 1)
-              {
-                if (*(pMask - maskImage->widthStep) == PIXEL_EXTERIOR) perimeter++;
-              }
-
-              // pixels a l'est i oest de l'actual
-              if (iRow < imatgePerimetreExtern->height)
-              {
-                if ((iCol > 0) && (*(pMask - 1) == PIXEL_EXTERIOR)) perimeter++;
-
-                if ((iCol < imatgePerimetreExtern->width - 1) && (*(pMask + 1) == PIXEL_EXTERIOR)) perimeter++;
-              }
-
-              // pixels al sud de l'actual
-              if (iRow < imatgePerimetreExtern->height - 1)
-              {
-                if ((*(pMask + maskImage->widthStep) == PIXEL_EXTERIOR)) perimeter++;
-              }
-
-              *pPerimetre = perimeter;
-            }
-          }
-
-          Tran++;	// Tran continues
-          pImage++;
-          pMask++;
-          pPerimetre++;
-        }
-        Transition[TransitionOffset + iTran] = Tran;	// Save completed run
-
-        if ((TransitionOffset + iTran + 1) < (Rows + 1)*(Cols + 2))
-        {
-          Transition[TransitionOffset + iTran + 1] = -1;
-        }
-
-
-        //jump to next row (beginning from (startCol, startRow))
-        pImage = inputImage->imageData - 1 + startCol + (iRow + startRow)*inputImage->widthStep;
-        //the mask should be the same size as image Roi, so don't take into account the offset
-        pMask = maskImage->imageData - 1 + iRow*maskImage->widthStep;
-      }
-    }
-
-    // Process transition code depending on Last row and This row
-    //
-    // Last ---++++++--+++++++++++++++-----+++++++++++++++++++-----++++++-------+++---
-    // This -----+++-----++++----+++++++++----+++++++---++------------------++++++++--
-    //
-    // There are various possibilities:
-    //
-    // Case     1       2       3       4       5       6       7       8
-    // Last |xxx    |xxxxoo |xxxxxxx|xxxxxxx|ooxxxxx|ooxxx  |ooxxxxx|    xxx|
-    // This |    yyy|    yyy|  yyyy |  yyyyy|yyyyyyy|yyyyyyy|yyyy   |yyyy   |
-    // Here o is optional
-    //
-    // Here are the primitive tests to distinguish these 6 cases:
-    //   A) Last end < This start - 1 OR NOT		Note: -1
-    //   B) This end < Last start OR NOT
-    //   C) Last start < This start OR NOT
-    //   D) This end < Last end OR NOT
-    //   E) This end = Last end OR NOT
-    //
-    // Here is how to use these tests to determine the case:
-    //   Case 1 = A [=> NOT B AND C AND NOT D AND NOT E]
-    //   Case 2 = C AND NOT D AND NOT E [AND NOT A AND NOT B]
-    //   Case 3 = C AND D [=> NOT E] [AND NOT A AND NOT B]
-    //   Case 4 = C AND NOT D AND E [AND NOT A AND NOT B]
-    //   Case 5 = NOT C AND E [=> NOT D] [AND NOT A AND NOT B]
-    //   Case 6 = NOT C AND NOT D AND NOT E [AND NOT A AND NOT B]
-    //   Case 7 = NOT C AND D [=> NOT E] [AND NOT A AND NOT B]
-    //   Case 8 = B [=> NOT A AND NOT C AND D AND NOT E]
-    //
-    // In cases 2,3,4,5,6,7 the following additional test is needed:
-    //   Match) This color = Last color OR NOT
-    //
-    // In cases 5,6,7 the following additional test is needed:
-    //   Known) This region was already matched OR NOT
-    //
-    // Here are the main tests and actions:
-    //   Case 1: LastIndex++;
-    //   Case 2: if(Match) {y = x;}
-    //           LastIndex++;
-    //   Case 3: if(Match) {y = x;}
-    //           else {y = new}
-    //           ThisIndex++;
-    //   Case 4: if(Match) {y = x;}
-    //           else {y = new}
-    //           LastIndex++;
-    //           ThisIndex++;
-    //   Case 5: if(Match AND NOT Known) {y = x}
-    //           else if(Match AND Known) {Subsume(x,y)}
-    //           LastIndex++;ThisIndex++
-    //   Case 6: if(Match AND NOT Known) {y = x}
-    //           else if(Match AND Known) {Subsume(x,y)}
-    //           LastIndex++;
-    //   Case 7: if(Match AND NOT Known) {y = x}
-    //           else if(Match AND Known) {Subsume(x,y)}
-    //           ThisIndex++;
-    //   Case 8: ThisIndex++;
-
-    int *SubsumedRegion = NULL;
-
-    double ThisParent;	// These data can change when the line is current
-    double ThisArea;
-    double ThisPerimeter;
-    double ThisSumX = 0;
-    double ThisSumY = 0;
-    double ThisSumXX = 0;
-    double ThisSumYY = 0;
-    double ThisSumXY = 0;
-    double ThisMinX;
-    double ThisMaxX;
-    double ThisMinY;
-    double ThisMaxY;
-    double LastPerimeter;	// This is the only data for retroactive change
-    double ThisExternPerimeter;
-
-    int HighRegionNum = 0;
-    //int RegionNum = 0;
-    int ErrorFlag = 0;
-
-    int LastRow, ThisRow;			// Row number
-    int LastStart, ThisStart;		// Starting column of run
-    int LastEnd, ThisEnd;			// Ending column of run
-    int LastColor, ThisColor;		// Color of run
-
-    int LastIndex, ThisIndex;		// Which run are we up to
-    int LastIndexCount, ThisIndexCount;	// Out of these runs
-    int LastRegionNum, ThisRegionNum;	// Which assignment
-    int *LastRegion;				// Row assignment of region number
-    int *ThisRegion;		// Row assignment of region number
-
-    int LastOffset = -(Trans + 2);	// For performance to avoid multiplication
-    int ThisOffset = 0;				// For performance to avoid multiplication
-    int ComputeData;
-
-    CvPoint actualedge;
-    uchar imagevalue;
-    bool CandidatExterior = false;
-
-    // apuntadors als blobs de la regió actual i last
-    CBlob *regionDataThisRegion, *regionDataLastRegion;
-
-    LastRegion = new int[Cols + 2];
-    ThisRegion = new int[Cols + 2];
-
-    for (i = 0; i < Cols + 2; i++)	// Initialize result arrays
-    {
-      LastRegion[i] = -1;
-      ThisRegion[i] = -1;
-    }
-
-    //create the external blob
-    RegionData.push_back(new CBlob());
-    SubsumedRegion = NewSubsume(SubsumedRegion, 0);
-    RegionData[0]->parent = -1;
-    RegionData[0]->area = (double)Transition[0];
-    RegionData[0]->perimeter = (double)(2 + 2 * Transition[0]);
-
-    ThisIndexCount = 1;
-    ThisRegion[0] = 0;	// Border region
-
-    // beginning of the image
-    // en cada linia, pimage apunta al primer pixel de la fila
-    pImage = inputImage->imageData - 1 + startCol + startRow * inputImage->widthStep;
-    //the mask should be the same size as image Roi, so don't take into account the offset
-    if (maskImage != NULL) pMask = maskImage->imageData - 1;
-
-    char *pImageAux, *pMaskAux = NULL;
-
-    // Loop over all rows
-    for (ThisRow = 1; ThisRow < Rows + 2; ThisRow++)
-    {
-      //cout << "========= THIS ROW = " << ThisRow << endl;	// for debugging
-      ThisOffset += Trans + 2;
-      ThisIndex = 0;
-      LastOffset += Trans + 2;;
-      LastRow = ThisRow - 1;
-      LastIndexCount = ThisIndexCount;
-      LastIndex = 0;
-
-      int EndLast = 0;
-      int EndThis = 0;
-
-      for (int j = 0; j < Trans + 2; j++)
-      {
-        int Index = ThisOffset + j;
-        int TranVal = Transition[Index];
-        if (TranVal > 0) ThisIndexCount = j + 1;	// stop at highest
-
-        if (ThisRegion[j] == -1) { EndLast = 1; }
-        if (TranVal < 0) { EndThis = 1; }
-
-        if (EndLast > 0 && EndThis > 0) { break; }
-
-        LastRegion[j] = ThisRegion[j];
-        ThisRegion[j] = -1;		// Flag indicates region is not initialized
-      }
-
-      int MaxIndexCount = LastIndexCount;
-      if (ThisIndexCount > MaxIndexCount) MaxIndexCount = ThisIndexCount;
-
-      // Main loop over runs within Last and This rows
-      while (LastIndex < LastIndexCount && ThisIndex < ThisIndexCount)
-      {
-        ComputeData = 0;
-
-        if (LastIndex == 0) LastStart = 0;
-        else LastStart = Transition[LastOffset + LastIndex - 1];
-        LastEnd = Transition[LastOffset + LastIndex] - 1;
-        LastColor = LastIndex - 2 * (LastIndex / 2);
-        LastRegionNum = LastRegion[LastIndex];
-
-        regionDataLastRegion = RegionData[LastRegionNum];
-
-
-        if (ThisIndex == 0) ThisStart = 0;
-        else ThisStart = Transition[ThisOffset + ThisIndex - 1];
-        ThisEnd = Transition[ThisOffset + ThisIndex] - 1;
-        ThisColor = ThisIndex - 2 * (ThisIndex / 2);
-        ThisRegionNum = ThisRegion[ThisIndex];
-
-        if (ThisRegionNum >= 0)
-          regionDataThisRegion = RegionData[ThisRegionNum];
-        else
-          regionDataThisRegion = NULL;
-
-
-        // blobs externs
-        CandidatExterior = false;
-        if (
-#if !IMATGE_CICLICA_VERTICAL
-          ThisRow == 1 || ThisRow == Rows ||
-#endif
-#if !IMATGE_CICLICA_HORITZONTAL
-          ThisStart <= 1 || ThisEnd >= Cols ||
-#endif
-          GetExternPerimeter(ThisStart, ThisEnd, ThisRow, inputImage->width, inputImage->height, imatgePerimetreExtern)
-          )
-        {
-          CandidatExterior = true;
-        }
-
-        int TestA = (LastEnd < ThisStart - 1);	// initially false
-        int TestB = (ThisEnd < LastStart);		// initially false
-        int TestC = (LastStart < ThisStart);	// initially false
-        int TestD = (ThisEnd < LastEnd);
-        int TestE = (ThisEnd == LastEnd);
-
-        int TestMatch = (ThisColor == LastColor);		// initially true
-        int TestKnown = (ThisRegion[ThisIndex] >= 0);	// initially false
-
-        int Case = 0;
-        if (TestA) Case = 1;
-        else if (TestB) Case = 8;
-        else if (TestC)
-        {
-          if (TestD) Case = 3;
-          else if (!TestE) Case = 2;
-          else Case = 4;
-        }
-        else
-        {
-          if (TestE) Case = 5;
-          else if (TestD) Case = 7;
-          else Case = 6;
-        }
-
-        // Initialize common variables
-        ThisArea = (float) 0.0;
-
-        if (findmoments)
-        {
-          ThisSumX = ThisSumY = (float) 0.0;
-          ThisSumXX = ThisSumYY = ThisSumXY = (float) 0.0;
-        }
-        ThisMinX = ThisMinY = (float) 1000000.0;
-        ThisMaxX = ThisMaxY = (float)-1.0;
-
-        LastPerimeter = ThisPerimeter = (float) 0.0;
-        ThisParent = (float)-1;
-        ThisExternPerimeter = 0.0;
-
-        // Determine necessary action and take it
-        switch (Case)
-        {
-        case 1: //|xxx    |
-          //|    yyy|
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          LastIndex++;
-
-          //afegim la cantonada a LastRegion
-          actualedge.x = ThisEnd;
-          actualedge.y = ThisRow - 1;
-          cvSeqPush(regionDataLastRegion->edges, &actualedge);
-
-          //afegim la cantonada a ThisRegion
-          actualedge.x = ThisStart - 1;
-          actualedge.y = ThisRow - 1;
-          cvSeqPush(regionDataThisRegion->edges, &actualedge);
-
-          break;
-
-
-        case 2: //|xxxxoo |
-          //|    yyy|
-
-          if (TestMatch)	// Same color
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-
-            ThisArea = ThisEnd - ThisStart + 1;
-            LastPerimeter = LastEnd - ThisStart + 1;	// to subtract
-            ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter +
-              PERIMETRE_DIAGONAL * 2;
-
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-              ThisExternPerimeter += PERIMETRE_DIAGONAL * 2;
-            }
-            ComputeData = 1;
-          }
-
-          //afegim la cantonada a ThisRegion
-          if (ThisRegionNum != -1)
-          {
-            // afegim dos vertexs si són diferents, només
-            if (ThisStart - 1 != ThisEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-          }
-          //afegim la cantonada a ThisRegion
-          if (LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            // afegim dos vertexs si són diferents, només
-            if (ThisStart - 1 != ThisEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataLastRegion->edges, &actualedge);
-            }
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          LastIndex++;
-          break;
-
-
-        case 3: //|xxxxxxx|
-          //|  yyyy |
-
-          if (TestMatch)	// Same color
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-
-            ThisArea = ThisEnd - ThisStart + 1;
-            LastPerimeter = ThisArea;	// to subtract
-            ThisPerimeter = 2 + ThisArea + PERIMETRE_DIAGONAL * 2;
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-              ThisExternPerimeter += PERIMETRE_DIAGONAL * 2;
-            }
-          }
-          else		// Different color => New region
-          {
-            ThisParent = LastRegionNum;
-            ThisRegionNum = ++HighRegionNum;
-            ThisArea = ThisEnd - ThisStart + 1;
-            ThisPerimeter = 2 + 2 * ThisArea;
-            RegionData.push_back(new CBlob());
-            regionDataThisRegion = RegionData.back();
-
-            SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
-            if (CandidatExterior)
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-          }
-
-          if (ThisRegionNum != -1)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            //afegim la cantonada a la regio
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-          }
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-            //afegim la cantonada a la regio
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          ComputeData = 1;
-          ThisIndex++;
-          break;
-
-
-        case 4:	//|xxxxxxx|
-          //|  yyyyy|
-
-          if (TestMatch)	// Same color
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-            ThisArea = ThisEnd - ThisStart + 1;
-            LastPerimeter = ThisArea;	// to subtract
-            ThisPerimeter = 2 + ThisArea + PERIMETRE_DIAGONAL;
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-              ThisExternPerimeter += PERIMETRE_DIAGONAL;
-            }
-          }
-          else		// Different color => New region
-          {
-            ThisParent = LastRegionNum;
-            ThisRegionNum = ++HighRegionNum;
-            ThisArea = ThisEnd - ThisStart + 1;
-            ThisPerimeter = 2 + 2 * ThisArea;
-            RegionData.push_back(new CBlob());
-            regionDataThisRegion = RegionData.back();
-            SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
-            if (CandidatExterior)
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-          }
-
-          if (ThisRegionNum != -1)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-          }
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          ComputeData = 1;
-
-#ifdef B_CONNECTIVITAT_8
-          if (TestMatch)
-          {
-            LastIndex++;
-            ThisIndex++;
-          }
-          else
-          {
-            LastIndex++;
-          }
-#else
-          LastIndex++;
-          ThisIndex++;
-#endif					
-          break;
-
-
-        case 5:	//|ooxxxxx|
-          //|yyyyyyy|
-
-          if (!TestMatch && !TestKnown)	// Different color and unknown => new region
-          {
-            ThisParent = LastRegionNum;
-            ThisRegionNum = ++HighRegionNum;
-            ThisArea = ThisEnd - ThisStart + 1;
-            ThisPerimeter = 2 + 2 * ThisArea;
-            RegionData.push_back(new CBlob());
-            regionDataThisRegion = RegionData.back();
-            SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
-            if (CandidatExterior)
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-          }
-          else if (TestMatch && !TestKnown)	// Same color and unknown
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-            ThisArea = ThisEnd - ThisStart + 1;
-            LastPerimeter = LastEnd - LastStart + 1;	// to subtract
-            ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
-              + PERIMETRE_DIAGONAL * (LastStart != ThisStart);
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-
-              ThisExternPerimeter += PERIMETRE_DIAGONAL * (LastStart != ThisStart);
-            }
-            ComputeData = 1;
-          }
-          else if (TestMatch && TestKnown)	// Same color and known
-          {
-            LastPerimeter = LastEnd - LastStart + 1;	// to subtract
-            //ThisPerimeter = - LastPerimeter;
-            ThisPerimeter = -2 * LastPerimeter
-              + PERIMETRE_DIAGONAL * (LastStart != ThisStart);
-
-            if (ThisRegionNum > LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
-                findmoments, ThisRegionNum, LastRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
-                if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
-              }
-              ThisRegionNum = LastRegionNum;
-            }
-            else if (ThisRegionNum < LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
-                findmoments, LastRegionNum, ThisRegionNum);
-
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
-                if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
-              }
-              LastRegionNum = ThisRegionNum;
-            }
-          }
-
-
-          if (ThisRegionNum != -1)
-          {
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-
-            if (ThisStart - 1 != LastEnd)
-            {
-              //afegim la cantonada a la regio
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-          }
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-
-#ifdef B_CONNECTIVITAT_8
-          if (TestMatch)
-          {
-            LastIndex++;
-            ThisIndex++;
-          }
-          else
-          {
-            LastIndex++;
-          }
-#else
-          LastIndex++;
-          ThisIndex++;
-#endif	
-          break;
-
-
-        case 6:	//|ooxxx  |
-          //|yyyyyyy|
-
-          if (TestMatch && !TestKnown)
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-            ThisArea = ThisEnd - ThisStart + 1;
-            LastPerimeter = LastEnd - LastStart + 1;	// to subtract
-            ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
-              + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-
-              ThisExternPerimeter += PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-            }
-            ComputeData = 1;
-          }
-          else if (TestMatch && TestKnown)
-          {
-            LastPerimeter = LastEnd - LastStart + 1;	// to subtract
-            //ThisPerimeter = - LastPerimeter;
-            ThisPerimeter = -2 * LastPerimeter
-              + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-
-            if (ThisRegionNum > LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
-                findmoments, ThisRegionNum, LastRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
-                if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
-              }
-              ThisRegionNum = LastRegionNum;
-            }
-            else if (ThisRegionNum < LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
-                findmoments, LastRegionNum, ThisRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
-                if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
-              }
-              LastRegionNum = ThisRegionNum;
-            }
-          }
-
-
-          if (ThisRegionNum != -1)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            if (ThisStart - 1 != LastEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-          }
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            //afegim la cantonada a la regio
-            if (ThisStart - 1 != LastEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          LastIndex++;
-          break;
-
-
-        case 7:	//|ooxxxxx|
-          //|yyyy   |
-
-          if (!TestMatch && !TestKnown)	// Different color and unknown => new region
-          {
-            ThisParent = LastRegionNum;
-            ThisRegionNum = ++HighRegionNum;
-            ThisArea = ThisEnd - ThisStart + 1;
-            ThisPerimeter = 2 + 2 * ThisArea;
-            RegionData.push_back(new CBlob());
-            regionDataThisRegion = RegionData.back();
-            SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
-            if (CandidatExterior)
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-          }
-          else if (TestMatch && !TestKnown)
-          {
-            ThisRegionNum = LastRegionNum;
-            regionDataThisRegion = regionDataLastRegion;
-            ThisArea = ThisEnd - ThisStart + 1;
-            ThisPerimeter = 2 + ThisArea;
-            LastPerimeter = ThisEnd - LastStart + 1;
-            ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
-              + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-            if (CandidatExterior)
-            {
-              ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
-                inputImage->width, inputImage->height,
-                imatgePerimetreExtern);
-
-              ThisExternPerimeter += PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-            }
-            ComputeData = 1;
-          }
-          else if (TestMatch && TestKnown)
-          {
-            LastPerimeter = ThisEnd - LastStart + 1;	// to subtract
-            //ThisPerimeter = - LastPerimeter;
-            ThisPerimeter = -2 * LastPerimeter
-              + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
-
-            if (ThisRegionNum > LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
-                findmoments, ThisRegionNum, LastRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
-                if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
-              }
-              ThisRegionNum = LastRegionNum;
-            }
-            else if (ThisRegionNum < LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
-                findmoments, LastRegionNum, ThisRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
-                if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
-              }
-              LastRegionNum = ThisRegionNum;
-            }
-          }
-
-          if (ThisRegionNum != -1)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            if (ThisStart - 1 != LastEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-          }
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisEnd;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-            if (ThisStart - 1 != LastEnd)
-            {
-              actualedge.x = ThisStart - 1;
-              actualedge.y = ThisRow - 1;
-              cvSeqPush(regionDataThisRegion->edges, &actualedge);
-            }
-          }
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          ThisIndex++;
-          break;
-
-        case 8:	//|    xxx|
-          //|yyyy   |
-
-#ifdef B_CONNECTIVITAT_8					
-        // fusionem blobs
-          if (TestMatch)
-          {
-            if (ThisRegionNum > LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
-                findmoments, ThisRegionNum, LastRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
-                if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
-              }
-              ThisRegionNum = LastRegionNum;
-            }
-            else if (ThisRegionNum < LastRegionNum)
-            {
-              Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
-                findmoments, LastRegionNum, ThisRegionNum);
-              for (int iOld = 0; iOld < MaxIndexCount; iOld++)
-              {
-                if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
-                if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
-              }
-              LastRegionNum = ThisRegionNum;
-            }
-
-            regionDataThisRegion->perimeter = regionDataThisRegion->perimeter + PERIMETRE_DIAGONAL * 2;
-          }
-#endif
-
-          if (ThisRegionNum != -1)
-          {
-            //afegim la cantonada a la regio
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataThisRegion->edges, &actualedge);
-          }
-#ifdef B_CONNECTIVITAT_8					
-          // si hem creat un nou blob, afegim tb a l'anterior
-          if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
-          {
-#endif					
-            //afegim la cantonada a la regio
-            actualedge.x = ThisStart - 1;
-            actualedge.y = ThisRow - 1;
-            cvSeqPush(regionDataLastRegion->edges, &actualedge);
-#ifdef B_CONNECTIVITAT_8
-          }
-#endif
-
-          ThisRegion[ThisIndex] = ThisRegionNum;
-          LastRegion[LastIndex] = LastRegionNum;
-          ThisIndex++;
-#ifdef B_CONNECTIVITAT_8					
-          LastIndex--;
-#endif
-          break;
-
-        default:
-          ErrorFlag = -1;
-        }	// end switch case
-
-        // calculate the blob moments and mean gray level of the current blob (ThisRegionNum)
-        if (ComputeData > 0)
-        {
-          // compute blob moments if necessary
-          if (findmoments)
-          {
-            float ImageRow = (float)(ThisRow - 1);
-
-            for (int k = ThisStart; k <= ThisEnd; k++)
-            {
-              ThisSumX += (float)(k - 1);
-              ThisSumXX += (float)(k - 1) * (k - 1);
-            }
-
-            ThisSumXY = ThisSumX * ImageRow;
-            ThisSumY = ThisArea * ImageRow;
-            ThisSumYY = ThisSumY * ImageRow;
-
-          }
-
-          // compute the mean gray level and its std deviation
-          if (ThisRow <= Rows)
-          {
-            pImageAux = pImage + ThisStart;
-            if (maskImage != NULL) pMaskAux = pMask + ThisStart;
-            for (int k = ThisStart; k <= ThisEnd; k++)
-            {
-              if ((k > 0) && (k <= Cols))
-              {
-                if (maskImage != NULL)
-                {
-                  // només es té en compte el valor del píxel de la
-                  // imatge que queda dins de la màscara
-                  // (de pas, comptem el nombre de píxels de la màscara)
-                  if (((unsigned char)*pMaskAux) != PIXEL_EXTERIOR)
-                  {
-                    imagevalue = (unsigned char)(*pImageAux);
-                    regionDataThisRegion->mean += imagevalue;
-                    regionDataThisRegion->stddev += imagevalue*imagevalue;
-                  }
-                  else
-                  {
-                    nombre_pixels_mascara++;
-                  }
-                }
-                else
-                {
-                  imagevalue = (unsigned char)(*pImageAux);
-                  regionDataThisRegion->mean += imagevalue;
-                  regionDataThisRegion->stddev += imagevalue*imagevalue;
-
-                }
-              }
-              pImageAux++;
-              if (maskImage != NULL) pMaskAux++;
-            }
-          }
-
-          // compute the min and max values of X and Y
-          if (ThisStart - 1 < (int)ThisMinX) ThisMinX = (float)(ThisStart - 1);
-          if (ThisMinX < (float) 0.0) ThisMinX = (float) 0.0;
-          if (ThisEnd > (int) ThisMaxX) ThisMaxX = (float)ThisEnd;
-
-          if (ThisRow - 1 < ThisMinY) ThisMinY = ThisRow - 1;
-          if (ThisMinY < (float) 0.0) ThisMinY = (float) 0.0;
-          if (ThisRow > ThisMaxY) ThisMaxY = ThisRow;
-        }
-
-        // put the current results into RegionData
-        if (ThisRegionNum >= 0)
-        {
-          if (ThisParent >= 0) { regionDataThisRegion->parent = (int)ThisParent; }
-          regionDataThisRegion->etiqueta = ThisRegionNum;
-          regionDataThisRegion->area += ThisArea;
-          regionDataThisRegion->perimeter += ThisPerimeter;
-          regionDataThisRegion->externPerimeter += ThisExternPerimeter;
-
-          if (ComputeData > 0)
-          {
-            if (findmoments)
-            {
-              regionDataThisRegion->sumx += ThisSumX;
-              regionDataThisRegion->sumy += ThisSumY;
-              regionDataThisRegion->sumxx += ThisSumXX;
-              regionDataThisRegion->sumyy += ThisSumYY;
-              regionDataThisRegion->sumxy += ThisSumXY;
-            }
-            regionDataThisRegion->perimeter -= LastPerimeter;
-            regionDataThisRegion->minx = MIN(regionDataThisRegion->minx, ThisMinX);
-            regionDataThisRegion->maxx = MAX(regionDataThisRegion->maxx, ThisMaxX);
-            regionDataThisRegion->miny = MIN(regionDataThisRegion->miny, ThisMinY);
-            regionDataThisRegion->maxy = MAX(regionDataThisRegion->maxy, ThisMaxY);
-          }
-          // blobs externs
-          if (CandidatExterior)
-          {
-            regionDataThisRegion->exterior = true;
-          }
-
-        }
-      }	// end Main loop
-
-      if (ErrorFlag != 0) {
-        delete[] Transition;
-        delete[] ThisRegion;
-        delete[] LastRegion;
-        return false;
-      }
-      // ens situem al primer pixel de la seguent fila
-      pImage = inputImage->imageData - 1 + startCol + (ThisRow + startRow) * inputImage->widthStep;
-
-      if (maskImage != NULL)
-        pMask = maskImage->imageData - 1 + ThisRow * maskImage->widthStep;
-    }	// end Loop over all rows
-
-    // eliminem l'àrea del marc
-    // i també els píxels de la màscara
-    // ATENCIO: PERFER: el fet de restar el nombre_pixels_mascara del
-    // blob 0 només serà cert si la màscara té contacte amb el marc.
-    // Si no, s'haurà de trobar quin és el blob que conté més píxels del
-    // compte.
-    RegionData[0]->area -= (Rows + 1 + Cols + 1) * 2 + nombre_pixels_mascara;
-
-    // eliminem el perímetre de més:
-    // - sense marc: 2m+2n (perímetre extern)
-    // - amb marc:   2(m+2)+2(n+2) = 2m+2n + 8
-    // (segurament no és del tot acurat)
-    // (i amb les màscares encara menys...)
-    RegionData[0]->perimeter -= 8.0;
-
-    // Condense the list
-    blob_vector::iterator itNew, itOld, iti;
-    CBlob *blobActual;
-
-    itNew = RegionData.begin();
-    itOld = RegionData.begin();
-    int iNew = 0;
-    for (int iOld = 0; iOld <= HighRegionNum; iOld++, itOld++)
-    {
-      if (SubsumedRegion[iOld] < 1)	// This number not subsumed
-      {
-        // Move data from old region number to new region number
-        //*RegionData[iNew] = *RegionData[iOld];
-        **itNew = **itOld;
-
-        // Update and parent pointer if necessary
-        iti = RegionData.begin();
-        for (int i = 0; i <= HighRegionNum; i++)
-        {
-          //if(RegionData[i]->parent == iOld) { RegionData[i]->parent = iNew; }
-          if ((*iti)->parent == iOld) { (*iti)->parent = iNew; }
-
-          ++iti;
-        }
-        iNew++;
-        ++itNew;
-      }
-    }
-
-
-    HighRegionNum = iNew - 1;				// Update where the data ends
-    RegionData[HighRegionNum]->parent = -1;	// and set end of array flag
-
-
-    if (findmoments)
-    {
-      iti = RegionData.begin();
-      // Normalize summation fields into moments
-      for (ThisRegionNum = 0; ThisRegionNum <= HighRegionNum; ThisRegionNum++, iti++)
-      {
-        blobActual = *iti;
-
-        // Get averages
-        blobActual->sumx /= blobActual->area;
-        blobActual->sumy /= blobActual->area;
-        blobActual->sumxx /= blobActual->area;
-        blobActual->sumyy /= blobActual->area;
-        blobActual->sumxy /= blobActual->area;
-
-        // Create moments
-        blobActual->sumxx -= blobActual->sumx * blobActual->sumx;
-        blobActual->sumyy -= blobActual->sumy * blobActual->sumy;
-        blobActual->sumxy -= blobActual->sumx * blobActual->sumy;
-        if (blobActual->sumxy > -1.0E-14 && blobActual->sumxy < 1.0E-14)
-        {
-          blobActual->sumxy = (float) 0.0; // Eliminate roundoff error
-        }
-
-      }
-    }
-
-    //Get the real mean and std deviation
-    iti = RegionData.begin();
-    for (ThisRegionNum = 0; ThisRegionNum <= HighRegionNum; ThisRegionNum++, iti++)
-    {
-      blobActual = *iti;
-      if (blobActual->area > 1)
-      {
-        blobActual->stddev =
-          sqrt(
-          (
-            blobActual->stddev * blobActual->area -
-            blobActual->mean * blobActual->mean
-            ) /
-            (blobActual->area*(blobActual->area - 1))
-          );
-      }
-      else
-        blobActual->stddev = 0;
-
-      if (blobActual->area > 0)
-        blobActual->mean /= blobActual->area;
-      else
-        blobActual->mean = 0;
-
-    }
-    // eliminem els blobs subsumats
-    blob_vector::iterator itBlobs = RegionData.begin() + HighRegionNum + 1;
-    while (itBlobs != RegionData.end())
-    {
-      delete *itBlobs;
-      //RegionData.erase( itBlobs );
-      ++itBlobs;
-    }
-    RegionData.erase(RegionData.begin() + HighRegionNum + 1, RegionData.end());
-
-    //free(RegionData);
-    free(SubsumedRegion);
-    delete[] Transition;
-    delete[] ThisRegion;
-    delete[] LastRegion;
-
-    if (imatgePerimetreExtern) cvReleaseImage(&imatgePerimetreExtern);
-
-    return true;
-  }
-
-
-  int *NewSubsume(int *subsumed, int index_subsume)
-  {
-    if (index_subsume == 0)
-    {
-      subsumed = (int*)malloc(sizeof(int));
-    }
-    else
-    {
-      subsumed = (int*)realloc(subsumed, (index_subsume + 1) * sizeof(int));
-    }
-    subsumed[index_subsume] = 0;
-    return subsumed;
-  }
-
-  /**
-    Fusiona dos blobs i afegeix el blob les característiques del blob RegionData[HiNum]
-    al blob RegionData[LoNum]. Al final allibera el blob de RegionData[HiNum]
-    */
-  void Subsume(blob_vector &RegionData,
-    int HighRegionNum,
-    int* SubsumedRegion,
-    CBlob* blobHi,
-    CBlob* blobLo,
-    bool findmoments,
-    int HiNum,
-    int LoNum)
-  {
-    // cout << "\nSubsuming " << HiNum << " into " << LoNum << endl; // for debugging
-
-    int i;
-
-    blobLo->minx = MIN(blobHi->minx, blobLo->minx);
-    blobLo->miny = MIN(blobHi->miny, blobLo->miny);
-    blobLo->maxx = MAX(blobHi->maxx, blobLo->maxx);
-    blobLo->maxy = MAX(blobHi->maxy, blobLo->maxy);
-    blobLo->area += blobHi->area;
-    blobLo->perimeter += blobHi->perimeter;
-    blobLo->externPerimeter += blobHi->externPerimeter;
-    blobLo->exterior = blobLo->exterior || blobHi->exterior;
-    blobLo->mean += blobHi->mean;
-    blobLo->stddev += blobHi->stddev;
-
-    if (findmoments)
-    {
-      blobLo->sumx += blobHi->sumx;
-      blobLo->sumy += blobHi->sumy;
-      blobLo->sumxx += blobHi->sumxx;
-      blobLo->sumyy += blobHi->sumyy;
-      blobLo->sumxy += blobHi->sumxy;
-    }
-    // Make sure no region still has subsumed region as parent
-    blob_vector::iterator it = (RegionData.begin() + HiNum + 1);
-
-    for (i = HiNum + 1; i <= HighRegionNum; i++, it++)
-    {
-      if ((*it)->parent == (float)HiNum) { (*it)->parent = LoNum; }
-    }
-
-    // Mark dead region number for future compression
-    SubsumedRegion[HiNum] = 1;
-    // marquem el blob com a lliure
-    blobHi->etiqueta = -1;
-
-    // Atenció!!!! abans d'eliminar els edges
-    // s'han de traspassar del blob HiNum al blob LoNum
-    blobHi->CopyEdges(*blobLo);
-    blobHi->ClearEdges();
-  }
-
-  /**
-    - FUNCIÓ: GetExternPerimeter
-    - FUNCIONALITAT: Retorna el perimetre extern d'una run lenght
-    - PARÀMETRES:
-    - start: columna d'inici del run
-    - end: columna final del run
-    - row: fila del run
-    - maskImage: màscara pels pixels externs
-    - RESULTAT:
-    - quantitat de perimetre extern d'un run, suposant que és un blob
-    d'una única fila d'alçada
-    - RESTRICCIONS:
-    - AUTOR:
-    - DATA DE CREACIÓ: 2006/02/27
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-  double GetExternPerimeter(int start, int end, int row, int width, int height, IplImage *imatgePerimetreExtern)
-  {
-    double perimeter = 0.0f;
-    char *pPerimetre;
-
-
-    // comprovem les dimensions de la imatge
-    perimeter += (start <= 0) + (end >= width - 1);
-    if (row <= 1) perimeter += start - end;
-    if (row >= height - 1) perimeter += start - end;
-
-
-    // comprovem els pixels que toquen a la màscara (si s'escau)
-    if (imatgePerimetreExtern != NULL)
-    {
-      if (row <= 0 || row >= height) return perimeter;
-
-      if (start < 0) start = 1;
-      if (end >= width) end = width - 2;
-
-      pPerimetre = imatgePerimetreExtern->imageData + (row - 1) * imatgePerimetreExtern->widthStep + start;
-      for (int x = start - 1; x <= end; x++)
-      {
-        perimeter += *pPerimetre;
-        pPerimetre++;
-      }
-    }
-
-    return perimeter;
-  }
-
-}
diff --git a/package_bgs/MultiLayer/BlobExtraction.h b/package_bgs/MultiLayer/BlobExtraction.h
deleted file mode 100644
index d8bd1af5dc762d0434311e0f6bac9c373b7af64f..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BlobExtraction.h
+++ /dev/null
@@ -1,70 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-//***********************************************************//
-//* Blob analysis package  8 August 2003                    *//
-//* Version 1.0                                             *//
-//* Input: IplImage* binary image                           *//
-//* Output: attributes of each connected region             *//
-//* Author: Dave Grossman                                   *//
-//* Email: dgrossman@cdr.stanford.edu                       *//
-//* Acknowledgement: the algorithm has been around > 20 yrs *//
-//***********************************************************//
-#pragma once
-
-namespace Blob
-{
-
-  //! Extreu els blobs d'una imatge
-  bool BlobAnalysis(IplImage* inputImage, uchar threshold, IplImage* maskImage,
-    bool borderColor, bool findmoments, blob_vector &RegionData);
-
-
-  // FUNCIONS AUXILIARS
-
-  //! Fusiona dos blobs
-  void Subsume(blob_vector &RegionData, int, int*, CBlob*, CBlob*, bool, int, int);
-  //! Reallocata el vector auxiliar de blobs subsumats
-  int *NewSubsume(int *SubSumedRegion, int elems_inbuffer);
-  //! Retorna el perimetre extern d'una run lenght
-  double GetExternPerimeter(int start, int end, int row, int width, int height, IplImage *maskImage);
-}
diff --git a/package_bgs/MultiLayer/BlobLibraryConfiguration.h b/package_bgs/MultiLayer/BlobLibraryConfiguration.h
deleted file mode 100644
index 0ba18fc3ac1d846e054a17ab9087915e9a50d2b8..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BlobLibraryConfiguration.h
+++ /dev/null
@@ -1,63 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/************************************************************************
-BlobLibraryConfiguration.h
-
-FUNCIONALITAT: Configuració del comportament global de la llibreria
-AUTOR: Inspecta S.L.
-MODIFICACIONS (Modificació, Autor, Data):
-
-FUNCTIONALITY: Global configuration of the library
-AUTHOR: Inspecta S.L.
-MODIFICATIONS (Modification, Author, Date):
-
-**************************************************************************/
-#pragma once
-
-//! Indica si es volen fer servir les MatrixCV o no
-//! Use/Not use the MatrixCV class
-//#define MATRIXCV_ACTIU
-
-// Uses/not use the blob object factory
-//#define BLOB_OBJECT_FACTORY
-
diff --git a/package_bgs/MultiLayer/BlobResult.cpp b/package_bgs/MultiLayer/BlobResult.cpp
deleted file mode 100644
index 1ec60e35e0ddc24dbef325abb7f9b9fffa5e7633..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BlobResult.cpp
+++ /dev/null
@@ -1,847 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/************************************************************************
-BlobResult.cpp
-
-FUNCIONALITAT: Implementació de la classe CBlobResult
-AUTOR: Inspecta S.L.
-MODIFICACIONS (Modificació, Autor, Data):
-
-**************************************************************************/
-
-#include <limits.h>
-#include <stdio.h>
-#include <functional>
-#include <algorithm>
-#include "BlobResult.h"
-#include "BlobExtraction.h"
-
-/**************************************************************************
-Constructors / Destructors
-**************************************************************************/
-
-namespace Blob
-{
-
-  /**
-    - FUNCIÓ: CBlobResult
-    - FUNCIONALITAT: Constructor estandard.
-    - PARÀMETRES:
-    - RESULTAT:
-    - Crea un CBlobResult sense cap blob
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobResult
-      - FUNCTIONALITY: Standard constructor
-      - PARAMETERS:
-      - RESULT:
-      - creates an empty set of blobs
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlobResult::CBlobResult()
-  {
-    m_blobs = blob_vector();
-  }
-
-  /**
-    - FUNCIÓ: CBlobResult
-    - FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seqüència de blobs
-    amb els blobs resultants de l'anàlisi de blobs de la imatge.
-    - PARÀMETRES:
-    - source: imatge d'on s'extreuran els blobs
-    - mask: màscara a aplicar. Només es calcularan els blobs on la màscara sigui
-    diferent de 0. Els blobs que toquin a un pixel 0 de la màscara seran
-    considerats exteriors.
-    - threshold: llindar que s'aplicarà a la imatge source abans de calcular els blobs
-    - findmoments: indica si s'han de calcular els moments de cada blob
-    - RESULTAT:
-    - objecte CBlobResult amb els blobs de la imatge source
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlob
-      - FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs in
-      the image
-      - PARAMETERS:
-      - source: image to extract the blobs from
-      - mask: optional mask to apply. The blobs will be extracted where the mask is
-      not 0. All the neighbouring blobs where the mask is 0 will be extern blobs
-      - threshold: threshold level to apply to the image before computing blobs
-      - findmoments: true to calculate the blob moments (slower)
-      - RESULT:
-      - object with all the blobs in the image. It throws an EXCEPCIO_CALCUL_BLOBS
-      if some error appears in the BlobAnalysis function
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlobResult::CBlobResult(IplImage *source, IplImage *mask, int threshold, bool findmoments)
-  {
-    bool success;
-
-    try
-    {
-      // cridem la funció amb el marc a true=1=blanc (així no unirà els blobs externs)
-      success = BlobAnalysis(source, (uchar)threshold, mask, true, findmoments, m_blobs);
-    }
-    catch (...)
-    {
-      success = false;
-    }
-
-    if (!success) throw EXCEPCIO_CALCUL_BLOBS;
-  }
-
-  /**
-    - FUNCIÓ: CBlobResult
-    - FUNCIONALITAT: Constructor de còpia. Inicialitza la seqüència de blobs
-    amb els blobs del paràmetre.
-    - PARÀMETRES:
-    - source: objecte que es copiarà
-    - RESULTAT:
-    - objecte CBlobResult amb els blobs de l'objecte source
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobResult
-      - FUNCTIONALITY: Copy constructor
-      - PARAMETERS:
-      - source: object to copy
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlobResult::CBlobResult(const CBlobResult &source)
-  {
-    m_blobs = blob_vector(source.GetNumBlobs());
-
-    // creem el nou a partir del passat com a paràmetre
-    m_blobs = blob_vector(source.GetNumBlobs());
-    // copiem els blobs de l'origen a l'actual
-    blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
-    blob_vector::iterator pBlobsDst = m_blobs.begin();
-
-    while (pBlobsSrc != source.m_blobs.end())
-    {
-      // no podem cridar a l'operador = ja que blob_vector és un
-      // vector de CBlob*. Per tant, creem un blob nou a partir del
-      // blob original
-      *pBlobsDst = new CBlob(**pBlobsSrc);
-      ++pBlobsSrc;
-      ++pBlobsDst;
-    }
-  }
-
-
-
-  /**
-    - FUNCIÓ: ~CBlobResult
-    - FUNCIONALITAT: Destructor estandard.
-    - PARÀMETRES:
-    - RESULTAT:
-    - Allibera la memòria reservada de cadascun dels blobs de la classe
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: ~CBlobResult
-      - FUNCTIONALITY: Destructor
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlobResult::~CBlobResult()
-  {
-    ClearBlobs();
-  }
-
-  /**************************************************************************
-    Operadors / Operators
-    **************************************************************************/
-
-
-    /**
-      - FUNCIÓ: operador =
-      - FUNCIONALITAT: Assigna un objecte source a l'actual
-      - PARÀMETRES:
-      - source: objecte a assignar
-      - RESULTAT:
-      - Substitueix els blobs actuals per els de l'objecte source
-      - RESTRICCIONS:
-      - AUTOR: Ricard Borràs
-      - DATA DE CREACIÓ: 25-05-2005.
-      - MODIFICACIÓ: Data. Autor. Descripció.
-      */
-      /**
-        - FUNCTION: Assigment operator
-        - FUNCTIONALITY:
-        - PARAMETERS:
-        - RESULT:
-        - RESTRICTIONS:
-        - AUTHOR: Ricard Borràs
-        - CREATION DATE: 25-05-2005.
-        - MODIFICATION: Date. Author. Description.
-        */
-  CBlobResult& CBlobResult::operator=(const CBlobResult& source)
-  {
-    // si ja són el mateix, no cal fer res
-    if (this != &source)
-    {
-      // alliberem el conjunt de blobs antic
-      for (int i = 0; i < GetNumBlobs(); i++)
-      {
-        delete m_blobs[i];
-      }
-      m_blobs.clear();
-      // creem el nou a partir del passat com a paràmetre
-      m_blobs = blob_vector(source.GetNumBlobs());
-      // copiem els blobs de l'origen a l'actual
-      blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
-      blob_vector::iterator pBlobsDst = m_blobs.begin();
-
-      while (pBlobsSrc != source.m_blobs.end())
-      {
-        // no podem cridar a l'operador = ja que blob_vector és un
-        // vector de CBlob*. Per tant, creem un blob nou a partir del
-        // blob original
-        *pBlobsDst = new CBlob(**pBlobsSrc);
-        ++pBlobsSrc;
-        ++pBlobsDst;
-      }
-    }
-    return *this;
-  }
-
-
-  /**
-    - FUNCIÓ: operador +
-    - FUNCIONALITAT: Concatena els blobs de dos CBlobResult
-    - PARÀMETRES:
-    - source: d'on s'agafaran els blobs afegits a l'actual
-    - RESULTAT:
-    - retorna un nou CBlobResult amb els dos CBlobResult concatenats
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - NOTA: per la implementació, els blobs del paràmetre es posen en ordre invers
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: + operator
-      - FUNCTIONALITY: Joins the blobs in source with the current ones
-      - PARAMETERS:
-      - source: object to copy the blobs
-      - RESULT:
-      - object with the actual blobs and the source blobs
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlobResult CBlobResult::operator+(const CBlobResult& source)
-  {
-    //creem el resultat a partir dels blobs actuals
-    CBlobResult resultat(*this);
-
-    // reservem memòria per als nous blobs
-    resultat.m_blobs.resize(resultat.GetNumBlobs() + source.GetNumBlobs());
-
-    // declarem els iterador per recòrrer els blobs d'origen i desti
-    blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
-    blob_vector::iterator pBlobsDst = resultat.m_blobs.end();
-
-    // insertem els blobs de l'origen a l'actual
-    while (pBlobsSrc != source.m_blobs.end())
-    {
-      --pBlobsDst;
-      *pBlobsDst = new CBlob(**pBlobsSrc);
-      ++pBlobsSrc;
-    }
-
-    return resultat;
-  }
-
-  /**************************************************************************
-    Operacions / Operations
-    **************************************************************************/
-
-    /**
-      - FUNCIÓ: AddBlob
-      - FUNCIONALITAT: Afegeix un blob al conjunt
-      - PARÀMETRES:
-      - blob: blob a afegir
-      - RESULTAT:
-      - modifica el conjunt de blobs actual
-      - RESTRICCIONS:
-      - AUTOR: Ricard Borràs
-      - DATA DE CREACIÓ: 2006/03/01
-      - MODIFICACIÓ: Data. Autor. Descripció.
-      */
-  void CBlobResult::AddBlob(CBlob *blob)
-  {
-    if (blob != NULL)
-      m_blobs.push_back(new CBlob(blob));
-  }
-
-
-  /**
-    - FUNCIÓ: GetSTLResult
-    - FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe
-    - PARÀMETRES:
-    - evaluador: Qualsevol objecte derivat de COperadorBlob
-    - RESULTAT:
-    - Retorna un array de double's STL amb el resultat per cada blob
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: GetResult
-      - FUNCTIONALITY: Computes the function evaluador on all the blobs of the class
-      and returns a vector with the result
-      - PARAMETERS:
-      - evaluador: function to apply to each blob (any object derived from the
-      COperadorBlob class )
-      - RESULT:
-      - vector with all the results in the same order as the blobs
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double_stl_vector CBlobResult::GetSTLResult(funcio_calculBlob *evaluador) const
-  {
-    if (GetNumBlobs() <= 0)
-    {
-      return double_stl_vector();
-    }
-
-    // definim el resultat
-    double_stl_vector result = double_stl_vector(GetNumBlobs());
-    // i iteradors sobre els blobs i el resultat
-    double_stl_vector::iterator itResult = result.begin();
-    blob_vector::const_iterator itBlobs = m_blobs.begin();
-
-    // avaluem la funció en tots els blobs
-    while (itBlobs != m_blobs.end())
-    {
-      *itResult = (*evaluador)(**itBlobs);
-      ++itBlobs;
-      ++itResult;
-    }
-    return result;
-  }
-
-  /**
-    - FUNCIÓ: GetNumber
-    - FUNCIONALITAT: Calcula el resultat especificat sobre un únic blob de la classe
-    - PARÀMETRES:
-    - evaluador: Qualsevol objecte derivat de COperadorBlob
-    - indexblob: número de blob del que volem calcular el resultat.
-    - RESULTAT:
-    - Retorna un double amb el resultat
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: GetNumber
-      - FUNCTIONALITY: Computes the function evaluador on a blob of the class
-      - PARAMETERS:
-      - indexBlob: index of the blob to compute the function
-      - evaluador: function to apply to each blob (any object derived from the
-      COperadorBlob class )
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobResult::GetNumber(int indexBlob, funcio_calculBlob *evaluador) const
-  {
-    if (indexBlob < 0 || indexBlob >= GetNumBlobs())
-      RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
-    return (*evaluador)(*m_blobs[indexBlob]);
-  }
-
-  /////////////////////////// FILTRAT DE BLOBS ////////////////////////////////////
-
-  /**
-    - FUNCIÓ: Filter
-    - FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb només
-    els blobs que han passat el filtre.
-    El filtrat es basa en especificar condicions sobre un resultat dels blobs
-    i seleccionar (o excloure) aquells blobs que no compleixen una determinada
-    condicio
-    - PARÀMETRES:
-    - dst: variable per deixar els blobs filtrats
-    - filterAction:	acció de filtrat. Incloure els blobs trobats (B_INCLUDE),
-    o excloure els blobs trobats (B_EXCLUDE)
-    - evaluador: Funció per evaluar els blobs (qualsevol objecte derivat de COperadorBlob
-    - Condition: tipus de condició que ha de superar la mesura (FilterType)
-    sobre cada blob per a ser considerat.
-    B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
-    B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
-    - LowLimit:  valor numèric per a la comparació (Condition) de la mesura (FilterType)
-    - HighLimit: valor numèric per a la comparació (Condition) de la mesura (FilterType)
-    (només té sentit per a aquelles condicions que tenen dos valors
-    (B_INSIDE, per exemple).
-    - RESULTAT:
-    - Deixa els blobs resultants del filtrat a destination
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: Filter
-      - FUNCTIONALITY: Get some blobs from the class based on conditions on measures
-      of the blobs.
-      - PARAMETERS:
-      - dst: where to store the selected blobs
-      - filterAction:	B_INCLUDE: include the blobs which pass the filter in the result
-      B_EXCLUDE: exclude the blobs which pass the filter in the result
-      - evaluador: Object to evaluate the blob
-      - Condition: How to decide if  the result returned by evaluador on each blob
-      is included or not. It can be:
-      B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
-      B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
-      - LowLimit:  numerical value to evaluate the Condition on evaluador(blob)
-      - HighLimit: numerical value to evaluate the Condition on evaluador(blob).
-      Only useful for B_INSIDE and B_OUTSIDE
-      - RESULT:
-      - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE)
-      the Condition on the result returned by evaluador on each blob
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlobResult::Filter(CBlobResult &dst,
-    int filterAction,
-    funcio_calculBlob *evaluador,
-    int condition,
-    double lowLimit, double highLimit /*=0*/)
-
-  {
-    int i, numBlobs;
-    bool resultavaluacio;
-    double_stl_vector avaluacioBlobs;
-    double_stl_vector::iterator itavaluacioBlobs;
-
-    if (GetNumBlobs() <= 0) return;
-    if (!evaluador) return;
-    //avaluem els blobs amb la funció pertinent
-    avaluacioBlobs = GetSTLResult(evaluador);
-    itavaluacioBlobs = avaluacioBlobs.begin();
-    numBlobs = GetNumBlobs();
-    switch (condition)
-    {
-    case B_EQUAL:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs == lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_NOT_EQUAL:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs != lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_GREATER:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs > lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_LESS:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs < lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_GREATER_OR_EQUAL:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs >= lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_LESS_OR_EQUAL:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = *itavaluacioBlobs <= lowLimit;
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_INSIDE:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = (*itavaluacioBlobs >= lowLimit) && (*itavaluacioBlobs <= highLimit);
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    case B_OUTSIDE:
-      for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
-      {
-        resultavaluacio = (*itavaluacioBlobs < lowLimit) || (*itavaluacioBlobs > highLimit);
-        if ((resultavaluacio && filterAction == B_INCLUDE) ||
-          (!resultavaluacio && filterAction == B_EXCLUDE))
-        {
-          dst.m_blobs.push_back(new CBlob(GetBlob(i)));
-        }
-      }
-      break;
-    }
-
-
-    // en cas de voler filtrar un CBlobResult i deixar-ho en el mateix CBlobResult
-    // ( operacio inline )
-    if (&dst == this)
-    {
-      // esborrem els primers blobs ( que són els originals )
-      // ja que els tindrem replicats al final si passen el filtre
-      blob_vector::iterator itBlobs = m_blobs.begin();
-      for (int i = 0; i < numBlobs; i++)
-      {
-        delete *itBlobs;
-        ++itBlobs;
-      }
-      m_blobs.erase(m_blobs.begin(), itBlobs);
-    }
-  }
-
-
-  /**
-    - FUNCIÓ: GetBlob
-    - FUNCIONALITAT: Retorna un blob si aquest existeix (index != -1)
-    - PARÀMETRES:
-    - indexblob: index del blob a retornar
-    - RESULTAT:
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /*
-      - FUNCTION: GetBlob
-      - FUNCTIONALITY: Gets the n-th blob (without ordering the blobs)
-      - PARAMETERS:
-      - indexblob: index in the blob array
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlob CBlobResult::GetBlob(int indexblob) const
-  {
-    if (indexblob < 0 || indexblob >= GetNumBlobs())
-      RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
-
-    return *m_blobs[indexblob];
-  }
-  CBlob *CBlobResult::GetBlob(int indexblob)
-  {
-    if (indexblob < 0 || indexblob >= GetNumBlobs())
-      RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
-
-    return m_blobs[indexblob];
-  }
-
-  /**
-    - FUNCIÓ: GetNthBlob
-    - FUNCIONALITAT: Retorna l'enèssim blob segons un determinat criteri
-    - PARÀMETRES:
-    - criteri: criteri per ordenar els blobs (objectes derivats de COperadorBlob)
-    - nBlob: index del blob a retornar
-    - dst: on es retorna el resultat
-    - RESULTAT:
-    - retorna el blob nBlob a dst ordenant els blobs de la classe segons el criteri
-    en ordre DESCENDENT. Per exemple, per obtenir el blob major:
-    GetNthBlob( CBlobGetArea(), 0, blobMajor );
-    GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob més gran)
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /*
-      - FUNCTION: GetNthBlob
-      - FUNCTIONALITY: Gets the n-th blob ordering first the blobs with some criteria
-      - PARAMETERS:
-      - criteri: criteria to order the blob array
-      - nBlob: index of the returned blob in the ordered blob array
-      - dst: where to store the result
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlobResult::GetNthBlob(funcio_calculBlob *criteri, int nBlob, CBlob &dst) const
-  {
-    // verifiquem que no estem accedint fora el vector de blobs
-    if (nBlob < 0 || nBlob >= GetNumBlobs())
-    {
-      //RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS );
-      dst = CBlob();
-      return;
-    }
-
-    double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat;
-    double valorEnessim;
-
-    //avaluem els blobs amb la funció pertinent
-    avaluacioBlobs = GetSTLResult(criteri);
-
-    avaluacioBlobsOrdenat = double_stl_vector(GetNumBlobs());
-
-    // obtenim els nBlob primers resultats (en ordre descendent)
-    std::partial_sort_copy(avaluacioBlobs.begin(),
-      avaluacioBlobs.end(),
-      avaluacioBlobsOrdenat.begin(),
-      avaluacioBlobsOrdenat.end(),
-      std::greater<double>());
-
-    valorEnessim = avaluacioBlobsOrdenat[nBlob];
-
-    // busquem el primer blob que té el valor n-ssim
-    double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin();
-
-    bool trobatBlob = false;
-    int indexBlob = 0;
-    while (itAvaluacio != avaluacioBlobs.end() && !trobatBlob)
-    {
-      if (*itAvaluacio == valorEnessim)
-      {
-        trobatBlob = true;
-        dst = CBlob(GetBlob(indexBlob));
-      }
-      ++itAvaluacio;
-      indexBlob++;
-    }
-  }
-
-  /**
-    - FUNCIÓ: ClearBlobs
-    - FUNCIONALITAT: Elimina tots els blobs de l'objecte
-    - PARÀMETRES:
-    - RESULTAT:
-    - Allibera tota la memòria dels blobs
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs Navarra
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /*
-      - FUNCTION: ClearBlobs
-      - FUNCTIONALITY: Clears all the blobs from the object and releases all its memory
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlobResult::ClearBlobs()
-  {
-    /*for( int i = 0; i < GetNumBlobs(); i++ )
-      {
-      delete m_blobs[i];
-      }*/
-    blob_vector::iterator itBlobs = m_blobs.begin();
-    while (itBlobs != m_blobs.end())
-    {
-      delete *itBlobs;
-      ++itBlobs;
-    }
-
-    m_blobs.clear();
-  }
-
-  /**
-    - FUNCIÓ: RaiseError
-    - FUNCIONALITAT: Funció per a notificar errors al l'usuari (en debug) i llença
-    les excepcions
-    - PARÀMETRES:
-    - errorCode: codi d'error
-    - RESULTAT:
-    - Ensenya un missatge a l'usuari (en debug) i llença una excepció
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs Navarra
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /*
-      - FUNCTION: RaiseError
-      - FUNCTIONALITY: Error handling function
-      - PARAMETERS:
-      - errorCode: reason of the error
-      - RESULT:
-      - in _DEBUG version, shows a message box with the error. In release is silent.
-      In both cases throws an exception with the error.
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlobResult::RaiseError(const int errorCode) const
-  {
-    throw errorCode;
-  }
-
-
-
-  /**************************************************************************
-    Auxiliars / Auxiliary functions
-    **************************************************************************/
-
-
-    /**
-      - FUNCIÓ: PrintBlobs
-      - FUNCIONALITAT: Escriu els paràmetres (àrea, perímetre, exterior, mitjana)
-      de tots els blobs a un fitxer.
-      - PARÀMETRES:
-      - nom_fitxer: path complet del fitxer amb el resultat
-      - RESULTAT:
-      - RESTRICCIONS:
-      - AUTOR: Ricard Borràs
-      - DATA DE CREACIÓ: 25-05-2005.
-      - MODIFICACIÓ: Data. Autor. Descripció.
-      */
-      /*
-        - FUNCTION: PrintBlobs
-        - FUNCTIONALITY: Prints some blob features in an ASCII file
-        - PARAMETERS:
-        - nom_fitxer: full path + filename to generate
-        - RESULT:
-        - RESTRICTIONS:
-        - AUTHOR: Ricard Borràs
-        - CREATION DATE: 25-05-2005.
-        - MODIFICATION: Date. Author. Description.
-        */
-  void CBlobResult::PrintBlobs(char *nom_fitxer) const
-  {
-    double_stl_vector area, /*perimetre,*/ exterior, mitjana, compacitat, longitud,
-      externPerimeter, perimetreConvex, perimetre;
-    int i;
-    FILE *fitxer_sortida;
-
-    area = GetSTLResult(CBlobGetArea());
-    perimetre = GetSTLResult(CBlobGetPerimeter());
-    exterior = GetSTLResult(CBlobGetExterior());
-    mitjana = GetSTLResult(CBlobGetMean());
-    compacitat = GetSTLResult(CBlobGetCompactness());
-    longitud = GetSTLResult(CBlobGetLength());
-    externPerimeter = GetSTLResult(CBlobGetExternPerimeter());
-    perimetreConvex = GetSTLResult(CBlobGetHullPerimeter());
-
-    fitxer_sortida = fopen(nom_fitxer, "w");
-
-    for (i = 0; i < GetNumBlobs(); i++)
-    {
-      fprintf(fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n",
-        i, area[i], perimetre[i], externPerimeter[i], perimetreConvex[i], exterior[i], mitjana[i], compacitat[i], longitud[i]);
-    }
-    fclose(fitxer_sortida);
-
-  }
-
-}
diff --git a/package_bgs/MultiLayer/BlobResult.h b/package_bgs/MultiLayer/BlobResult.h
deleted file mode 100644
index aa3e37b31c12998d96a91c3493f25557ad4e5a32..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/BlobResult.h
+++ /dev/null
@@ -1,196 +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/>.
-*/
-/* --- --- ---
- * Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /************************************************************************
-         BlobResult.h
-
-         FUNCIONALITAT: Definició de la classe CBlobResult
-         AUTOR: Inspecta S.L.
-         MODIFICACIONS (Modificació, Autor, Data):
-
-         FUNCTIONALITY: Definition of the CBlobResult class
-         AUTHOR: Inspecta S.L.
-         MODIFICATIONS (Modification, Author, Date):
-
-         **************************************************************************/
-#pragma once
-
-#include "BlobLibraryConfiguration.h"
-#include <math.h>
-         //#include "cxcore.h"
-#include <vector>
-#include <functional>
-#include "OpenCvLegacyIncludes.h"
-#include "blob.h"
-
-typedef std::vector<double> double_stl_vector;
-
-/**************************************************************************
-  Filtres / Filters
-  **************************************************************************/
-
-  //! accions que es poden fer amb els filtres
-  //! Actions performed by a filter (include or exclude blobs)
-#define B_INCLUDE				1L
-#define B_EXCLUDE				2L
-
-//! condicions sobre els filtres
-//! Conditions to apply the filters
-#define B_EQUAL					3L
-#define B_NOT_EQUAL				4L
-#define B_GREATER				5L
-#define B_LESS					6L
-#define B_GREATER_OR_EQUAL		7L
-#define B_LESS_OR_EQUAL			8L
-#define B_INSIDE			    9L
-#define B_OUTSIDE			    10L
-
-
-/**************************************************************************
-  Excepcions / Exceptions
-  **************************************************************************/
-
-  //! Excepcions llençades per les funcions:
-#define EXCEPTION_BLOB_OUT_OF_BOUNDS	1000
-#define EXCEPCIO_CALCUL_BLOBS			1001
-
-namespace Blob
-{
-
-  //! definició de que es un vector de blobs
-  typedef std::vector<CBlob*>	blob_vector;
-
-  /**
-      Classe que conté un conjunt de blobs i permet extreure'n propietats
-      o filtrar-los segons determinats criteris.
-      Class to calculate the blobs of an image and calculate some properties
-      on them. Also, the class provides functions to filter the blobs using
-      some criteria.
-      */
-  class CBlobResult
-  {
-  public:
-
-    //! constructor estandard, crea un conjunt buit de blobs
-    //! Standard constructor, it creates an empty set of blobs
-    CBlobResult();
-    //! constructor a partir d'una imatge
-    //! Image constructor, it creates an object with the blobs of the image
-    CBlobResult(IplImage *source, IplImage *mask, int threshold, bool findmoments);
-    //! constructor de còpia
-    //! Copy constructor
-    CBlobResult(const CBlobResult &source);
-    //! Destructor
-    virtual ~CBlobResult();
-
-    //! operador = per a fer assignacions entre CBlobResult
-    //! Assigment operator
-    CBlobResult& operator=(const CBlobResult& source);
-    //! operador + per concatenar dos CBlobResult
-    //! Addition operator to concatenate two sets of blobs
-    CBlobResult operator+(const CBlobResult& source);
-
-    //! Afegeix un blob al conjunt
-    //! Adds a blob to the set of blobs
-    void AddBlob(CBlob *blob);
-
-#ifdef MATRIXCV_ACTIU
-    //! Calcula un valor sobre tots els blobs de la classe retornant una MatrixCV
-    //! Computes some property on all the blobs of the class
-    double_vector GetResult(funcio_calculBlob *evaluador) const;
-#endif
-    //! Calcula un valor sobre tots els blobs de la classe retornant un std::vector<double>
-    //! Computes some property on all the blobs of the class
-    double_stl_vector GetSTLResult(funcio_calculBlob *evaluador) const;
-
-    //! Calcula un valor sobre un blob de la classe
-    //! Computes some property on one blob of the class
-    double GetNumber(int indexblob, funcio_calculBlob *evaluador) const;
-
-    //! Retorna aquells blobs que compleixen les condicions del filtre en el destination
-    //! Filters the blobs of the class using some property
-    void Filter(CBlobResult &dst,
-      int filterAction, funcio_calculBlob *evaluador,
-      int condition, double lowLimit, double highLimit = 0);
-
-    //! Retorna l'enèssim blob segons un determinat criteri
-    //! Sorts the blobs of the class acording to some criteria and returns the n-th blob
-    void GetNthBlob(funcio_calculBlob *criteri, int nBlob, CBlob &dst) const;
-
-    //! Retorna el blob enèssim
-    //! Gets the n-th blob of the class ( without sorting )
-    CBlob GetBlob(int indexblob) const;
-    CBlob *GetBlob(int indexblob);
-
-    //! Elimina tots els blobs de l'objecte
-    //! Clears all the blobs of the class
-    void ClearBlobs();
-
-    //! Escriu els blobs a un fitxer
-    //! Prints some features of all the blobs in a file
-    void PrintBlobs(char *nom_fitxer) const;
-
-
-    //Metodes GET/SET
-
-    //! Retorna el total de blobs
-    //! Gets the total number of blobs
-    int GetNumBlobs() const
-    {
-      return(m_blobs.size());
-    }
-
-
-  private:
-
-    //! Funció per gestionar els errors
-    //! Function to manage the errors
-    void RaiseError(const int errorCode) const;
-
-  protected:
-
-    //! Vector amb els blobs
-    //! Vector with all the blobs
-    blob_vector		m_blobs;
-  };
-
-}
diff --git a/package_bgs/MultiLayer/CMultiLayerBGS.h b/package_bgs/MultiLayer/CMultiLayerBGS.h
deleted file mode 100644
index 78a0527ddb75bcce0f324ec0ecd52d017bc0c529..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/CMultiLayerBGS.h
+++ /dev/null
@@ -1,308 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// BackgroundSubtraction.h: interface for the CBackgroundSubtraction class.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-/*
-Since the used fast cross bilateral filter codes can not be compiled under Windows,
-we don't use the bilateral filter to remove the noise in the foreground detection
-step. If you compile it under Linux, please uncomment it.
-*/
-//#define LINUX_BILATERAL_FILTER
-
-#include "LocalBinaryPattern.h"
-#include "BGS.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include "BlobResult.h"
-#include "OpenCvDataConversion.h"
-
-#include "BackgroundSubtractionAPI.h"
-
-#ifdef LINUX_BILATERAL_FILTER
-#include "CrossBilateralFilter.h"				// cross bilateral filter
-#endif
-
-#include <ctime>						// clock
-#include <cstdlib>						// C standard library
-#include <cstdio>						// C I/O (for sscanf)
-#include <cstring>						// string manipulation
-#include <fstream>						// file I/O
-#include <cmath>						// math includes
-#include <iostream>						// I/O streams
-
-using namespace std;						// make std:: accessible
-
-class CMultiLayerBGS : public CBackgroundSubtractionAPI
-{
-public:
-  //-------------------------------------------------------------
-  // TO CALL AT INITIALISATION: DEFINES THE SIZE OF THE INPUT IMAGES
-  // NORMALLY, UNNECESSARY IF A CONFIGURATION FILE IS LOADED
-  void   Init(int width, int height);
-
-  //-------------------------------------------------------------
-  // PROVIDE A MASK TO DEFINE THE SET OF POINTS WHERE BACKGROUND
-  // SUBTRACTION DOES NOT NEED TO BE PERFORMED
-  //
-  //  mode is useful to specify if the points to remove from
-  //  processing are in addition to the ones potentially
-  //  removed according to the configuration file,
-  //  or if they are the only ones to be removed
-  //
-  // mode=0 : provided points need to be removed
-  //          in addition to those already removed
-  // mode=1 : the provided points are the only one to remove
-  //          from processing
-  // Note:  maskImage(li,co)=0 indicate the points to remove
-  //       from background processing
-  void   SetValidPointMask(IplImage* maskImage, int mode);
-
-  //-------------------------------------------------------------
-  //
-  //   set the frame rate, to adjust the update parameters
-  //   to the actual frame rate.
-  //   Can be called only once at initialisation,
-  //   but in online cases, can be used to indicate
-  //   the time interval during the last processed frame
-  //
-  //   frameDuration is in millisecond
-  void   SetFrameRate(float    frameDuration);
-
-  //-------------------------------------------------------------
-  //
-  //   set some main parameters for background model learning.
-  //   in general, we can set large updating rates for background
-  //   model learning and set small updating rates in foreground
-  //   detection
-  void SetParameters(int max_lbp_mode_num,		// maximal LBP mode number
-    float mode_updating_learn_rate_per_second,	// background mode updating learning rate per second
-    float weight_updating_learn_rate_per_second,	// mode's weight updating learning rate per second
-    float low_init_mode_weight);			// the low initial mode weight
-
-//-------------------------------------------------------------
-//   PROVIDE A POINTER TO THE INPUT IMAGE
-//   -> INDICATE WHERE THE NEW IMAGE TO PROCESS IS STORED
-//
-//   Here assumes that the input image will contain RGB images.
-//   The memory of this image is handled by the caller.
-//
-//    The return value indicate whether the actual Background
-//    Subtraction algorithm handles RGB images (1) or not (0).
-//
-  int   SetRGBInputImage(IplImage  *  inputImage, CvRect *roi = NULL);
-
-  //-------------------------------------------------------------
-  //   PROVIDE A POINTER TO THE RESULT IMAGE
-  //   INDICATE WHERE THE BACKGROUND RESULT NEED TO BE STORED
-  //
-  int SetForegroundMaskImage(IplImage* fg_mask_img);
-  int SetForegroundProbImage(IplImage* fg_prob_img);
-
-  //-------------------------------------------------------------
-  // This function should be called each time a new image is
-  // available in the input image.
-  //
-  // The return value is 0 if everything goes well, a non-zero value
-  // otherwise.
-  //
-  int   Process();
-
-  //-------------------------------------------------------------
-  // this function should save parameters and information of the model
-  // (e.g. after a training of the model, or in such a way
-  // that the model can be reload to process the next frame
-  // type of save:
-  //	0 - background model information (pixel by pixel)
-  //	1 - background model parameters
-  //	2 - both background information (pixel by pixel) and parameters
-  void   Save(const char   *bg_model_fn, int save_type);
-  void   Save(const char* bg_model_fn);
-
-  //-------------------------------------------------------------
-  // this function should load the parameters necessary
-  // for the processing of the background subtraction or
-  // load background model information
-  bool   Load(const char  *bg_model_fn);
-
-
-  void SetCurrentFrameNumber(unsigned long cur_frame_no);
-
-  void GetForegroundMaskImage(IplImage *fg_mask_img);
-  void GetForegroundImage(IplImage *fg_img, CvScalar bg_color = CV_RGB(0, 255, 0));
-  void GetBackgroundImage(IplImage *bk_img);
-  void GetForegroundProbabilityImage(IplImage* fg_prob_img);
-
-  void GetBgLayerNoImage(IplImage *bg_layer_no_img, CvScalar* layer_colors = NULL, int layer_num = 0);
-  void GetLayeredBackgroundImage(int layered_no, IplImage *layered_bg_img, CvScalar empty_color = CV_RGB(0, 0, 0));
-  void GetCurrentLayeredBackgroundImage(int layered_no, IplImage *layered_bg_img, IplImage *layered_fg_img = NULL,
-    CvScalar layered_bg_bk_color = CV_RGB(0, 0, 0), CvScalar layered_fg_color = CV_RGB(255, 0, 0),
-    int smooth_win = 13, float smooth_sigma = 3.0f, float below_layer_noise = 0.5f, float above_layer_noise = 0.3f, int min_blob_size = 50);
-  float DistLBP(LBPStruct *LBP1, LBPStruct *LBP2);
-  void GetColoredBgMultiLayeredImage(IplImage *bg_multi_layer_img, CvScalar *layer_colors);
-  void UpdatePatternColorDistWeights(float *cur_pattern, float *bg_pattern);
-  void ExportLogMessage(char* msg);
-  void Postprocessing();
-  void GetFloatEdgeImage(IplImage *src, IplImage *dst);
-  void RemoveBackgroundLayers(PixelLBPStruct *PLBP, bool *removed_modes = NULL);
-  float CalColorRangeDist(unsigned char *cur_intensity, float *bg_intensity, float *max_intensity,
-    float *min_intensity, float shadow_rate, float highlight_rate);
-  float CalVectorsAngle(float *c1, unsigned char *c2, int length);
-  float CalVectorsNoisedAngle(float *bg_color, unsigned char *noised_color, float offset, int length);
-  void ComputeGradientImage(IplImage *src, IplImage *dst, bool bIsFloat);
-  float CalColorBgDist(uchar *cur_intensity, float *bg_intensity, float *max_intensity, float *min_intensity);
-  float CalPatternBgDist(float *cur_pattern, float *bg_pattern);
-
-  void GetForegroundMaskMap(CvMat *fg_mask_mat);
-  void Initialization(IplImage *first_img, int lbp_level_num, float *radiuses, int *neig_pt_nums);
-  void GetCurrentBackgroundDistMap(CvMat *bk_dist_map);
-  void BackgroundSubtractionProcess();
-  void SetBkMaskImage(IplImage *mask_img);
-  void SetNewImage(IplImage *new_img, CvRect *roi = NULL);
-
-  void ResetAllParameters();
-  void QuickSort(float *pData, unsigned short *pIdxes, long low, long high, bool bAscent);
-  void UpdateBgPixelPattern(float *cur_pattern, float *bg_bg_pattern);
-  void UpdateBgPixelColor(unsigned char* cur_intensity, float* bg_intensity);
-  void Update_MAX_MIN_Intensity(unsigned char *cur_intensity, float *max_intensity, float *min_intensity);
-  void MergeImages(int num, ...);
-
-  int	m_nChannel;				/* most of opencv functions support 1,2,3 or 4 channels, for the input images */
-
-  PixelLBPStruct*	m_pPixelLBPs;			/* the LBP texture patterns for each image */
-  int	m_nMaxLBPModeNum;			/* the maximal number for the used LBP pattern models */
-  float	m_fModeUpdatingLearnRate;		/* the background mode learning rate */
-  float	m_fWeightUpdatingLearnRate;		/* the background mode weight updating rate */
-  float	m_f1_ModeUpdatingLearnRate;		/* 1 - background_mode_learning_rate */
-  float	m_f1_WeightUpdatingLearnRate;		/* 1 - background_mode_weight_updating_rate */
-  float	m_fRobustColorOffset;			/* the intensity offset robust to noise */
-  float	m_fLowInitialModeWeight;		/* the lowest weight of initial background mode */
-  int	m_nLBPLength;				/* the length of texture LBP operator */
-  float	m_fPatternColorDistBgThreshold;		/* the threshold value used to classify background and foreground */
-  float	m_fPatternColorDistBgUpdatedThreshold;	/* the threshold value used to update the background modeling */
-  float	m_fMinBgLayerWeight;			/* the minimal weight to remove background layers */
-
-  int	m_nPatternDistSmoothNeigHalfSize;	/* the neighboring half size of gaussian window to remove the noise
-                                        on the distance map */
-  float	m_fPatternDistConvGaussianSigma;	/* the gaussian sigma used to remove the noise on the distance map */
-
-  float	m_fBackgroundModelPercent;		/* the background mode percent, the first several background modes
-                                      with high mode weights should be regarded as reliable background modes */
-
-  float	m_fRobustShadowRate;			/* the minimal shadow rate, [0.4, 0.7] */
-  float	m_fRobustHighlightRate;			/* the maximal highlight rate, [1.1, 1.4] */
-
-  int	m_nLBPImgNum;				/* the number of images used for texture LBP feature */
-
-  float	m_fMinLBPBinaryProb;			/* the minimal LBP binary probability */
-  float	m_f1_MinLBPBinaryProb;			/* 1 - minimal_LBP_binary_probability */
-
-  CvSize	m_cvImgSize;				/* the image size (width, height) */
-
-  unsigned long	m_nCurImgFrameIdx;			/* the frame index of current image */
-
-  bool	m_bUsedGradImage;			/* the boolean variable signaling whether the gradient image is used
-                              or not for computing LBP operator */
-
-  bool	m_bUsedColorLBP;			/* true - multi-channel color image for LBP operator,
-                              false - gray-scale image for LBP operator  */
-
-  CLocalBinaryPattern	m_cLBP;			/* the class instant for computing LBP (local binary pattern) texture feature */
-
-  IplImage* m_pBkMaskImg;				/* the mask image corresponding to the input image,
-                                i.e. all the masked pixels should be processed  */
-
-  IplImage* m_pOrgImg;				/* the original image */
-  IplImage** m_ppOrgLBPImgs;			/* the multi-layer images used for LBP feature extraction */
-  IplImage* m_pFgImg;				/* the foreground image */
-  IplImage* m_pBgImg;				/* the background image */
-  IplImage* m_pFgMaskImg;				/* the foreground mask image */
-  IplImage* m_pBgDistImg;				/* the background distance image (float) */
-  IplImage* m_pEdgeImg;				/* the edge image used for cross bilateral filter */
-  IplImage* m_pFgProbImg;				/* the foreground probability image (uchar) */
-
-  IplImage* m_pFirstAppearingTimeMap;
-
-#ifdef LINUX_BILATERAL_FILTER
-  CCrossBilateralFilter	m_cCrossBF;		/* the class instant for cross bilateral filter
-                                      which should be used to remove noise on the distance map */
-#endif
-
-  bool	m_disableLearning;
-  float	m_fSigmaS;				/* sigma in the spatial domain for cross bilateral filter */
-  float	m_fSigmaR;				/* sigma in the normalized intensity domain for cross bilateral filter */
-
-  float	m_fTextureWeight;			/* the weight value of texture LBP feature
-                              for background modeling & foreground detection */
-
-  float	m_fColorWeight;				/* the weight value of color invariant feature
-                              for background modeling & foreground detection */
-
-  float	m_fWeightUpdatingConstant;		/* the constant ( >= 1 ) for 'hysteries' weight updating scheme
-                                      (increase when matched, decrease when un-matched */
-
-  float	m_fReliableBackgroundModeWeight;	/* the weight value for background mode
-                                          which should be regarded as a reliable background mode,
-                                          which is useful for multi-layer scheme */
-
-  float	m_fMinNoisedAngle;			/* the minimal angle value between the background color
-                                and the noised observed color */
-
-  float	m_fMinNoisedAngleSine;			/* the minimal angle sine value between the background color
-                                    and the noised observed color */
-
-  float	m_fFrameDuration;			/* frame duration */
-
-  float	m_fModeUpdatingLearnRatePerSecond;
-  float	m_fWeightUpdatingLearnRatePerSecond;
-
-  int m_nLBPLevelNum;
-  float m_pLBPRadiuses[10];
-  int m_pLBPMeigPointNums[10];
-
-  CvRect* m_pROI;
-  CMultiLayerBGS();
-  virtual ~CMultiLayerBGS();
-};
diff --git a/package_bgs/MultiLayer/LocalBinaryPattern.h b/package_bgs/MultiLayer/LocalBinaryPattern.h
deleted file mode 100644
index 40d43790f96292be18559c6056912ed4c7537469..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/LocalBinaryPattern.h
+++ /dev/null
@@ -1,98 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// LocalBinaryPattern.h: interface for the CLocalBinaryPattern class.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include "OpenCvLegacyIncludes.h"
-#include "BGS.h"
-
-
-/************************************************************************/
-/* two types of computing the LBP operators but currently GENERAL_LBP   */
-/* has been implemented.                                                */
-/************************************************************************/
-#define	GENERAL_LBP	0
-#define SYMMETRIC_LBP	1
-
-#include <cstdio>						// C I/O (for sscanf)
-#include "OpenCvDataConversion.h"
-
-
-class CLocalBinaryPattern
-{
-public:
-  void CalImageDifferenceMap(IplImage *cent_img, IplImage *neig_img, float *pattern, CvRect *roi = NULL);
-  void CalNeigPixelOffset(float radius, int tot_neig_pts_num, int neig_pt_idx, int &offset_x, int &offset_y);
-  void CalShiftedImage(IplImage *src, int offset_x, int offset_y, IplImage *dst, CvRect *roi = NULL);
-  void FreeMemories();
-  void ComputeLBP(PixelLBPStruct *PLBP, CvRect *roi = NULL);
-  void SetNewImages(IplImage **new_imgs);
-
-  IplImage** m_ppOrgImgs;			/* the original images used for computing the LBP operators */
-
-  void Initialization(IplImage **first_imgs, int imgs_num,
-    int level_num, float *radius, int *neig_pt_num,
-    float robust_white_noise = 3.0f, int type = GENERAL_LBP);
-
-  CLocalBinaryPattern();
-  virtual ~CLocalBinaryPattern();
-
-  float	m_fRobustWhiteNoise;		/* the robust noise value for computing the LBP operator in each channel */
-
-private:
-  void SetShiftedMeshGrid(CvSize img_size, float offset_x, float offset_y, CvMat *grid_map_x, CvMat *grid_map_y);
-
-  float*	m_pRadiuses;			/* the circle radiuses for the LBP operator */
-  int	m_nLBPType;			/* the type of computing LBP operator */
-  int*	m_pNeigPointsNums;		/* the numbers of neighboring pixels on multi-level circles */
-  int	m_nImgsNum;			/* the number of multi-channel image */
-  int	m_nLBPLevelNum;			/* the number of multi-level LBP operator */
-  CvSize	m_cvImgSize;			/* the image size (width, height) */
-
-  CvPoint* m_pXYShifts;
-  CvPoint	m_nMaxShift;
-
-  IplImage* m_pShiftedImg;
-};
diff --git a/package_bgs/MultiLayer/OpenCvDataConversion.h b/package_bgs/MultiLayer/OpenCvDataConversion.h
deleted file mode 100644
index 18371b3bf632163ee95eda0ea280cb7d978cfc11..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/OpenCvDataConversion.h
+++ /dev/null
@@ -1,219 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// OpencvDataConversion.h: interface for the COpencvDataConversion class.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include "OpenCvLegacyIncludes.h"
-#include <stdio.h>
-
-template <class TI, class TM>		/* class TI - the type of image data, class TM - the type of matrix data */
-class COpencvDataConversion
-{
-public:
-
-  /* get the image data */
-  TI * GetImageData(IplImage *img)
-  {
-    if (!img->roi) {	/* no ROI used, i.e. the whole image */
-      int y; //, x;
-      TI* img_data = new TI[img->width*img->height*img->nChannels];
-      TI* temp = img_data;
-      TI* x_data;
-
-      for (y = 0; y < img->height; y++) {
-        x_data = (TI*)(img->imageData + img->widthStep*y);
-        int row_length = img->width*img->nChannels;
-        memcpy(temp, x_data, sizeof(TI)*row_length);
-        temp += row_length;
-        /*
-        for ( x = 0 ; x < img->width*img->nChannels ; x++ )
-        *temp++ = *x_data++;
-        */
-      }
-
-      return img_data;
-    }
-    else {	/* get image data only in ROI */
-      int y;//, x;
-      TI* img_data = new TI[img->roi->width*img->roi->height*img->nChannels];
-      TI* temp = img_data;
-      TI* x_data;
-      for (y = img->roi->yOffset; y < img->roi->yOffset + img->roi->height; y++) {
-        x_data = (TI*)(img->imageData + img->widthStep*y + img->roi->xOffset*sizeof(TI)*img->nChannels);
-        int row_length = img->roi->width*img->nChannels;
-        memcpy(temp, x_data, sizeof(TI)*row_length);
-        temp += row_length;
-        /*
-        for ( x = 0 ; x < img->roi->width*img->nChannels ; x++ )
-        *temp++ = *x_data++;
-        */
-      }
-      return img_data;
-    }
-  };
-
-  /* set the image data */
-  void SetImageData(IplImage *img, TI *img_data)
-  {
-    if (!img->roi) {	/* no ROI used, i.e. the whole image */
-      int y;//, x;
-      TI* temp = img_data;
-      TI* x_data;
-      for (y = 0; y < img->height; y++) {
-        x_data = (TI*)(img->imageData + img->widthStep*y);
-        int row_length = img->width*img->nChannels;
-        memcpy(x_data, temp, sizeof(TI)*row_length);
-        temp += row_length;
-        /*
-        for ( x = 0 ; x < img->width*img->nChannels ; x++ )
-        *x_data++ = *temp++;
-        */
-      }
-    }
-    else {	/* set image data only in ROI */
-      int y;//, x;
-      TI* temp = img_data;
-      TI* x_data;
-      for (y = img->roi->yOffset; y < img->roi->yOffset + img->roi->height; y++) {
-        x_data = (TI*)(img->imageData + img->widthStep*y + img->roi->xOffset*sizeof(TI)*img->nChannels);
-        int row_length = img->roi->width*img->nChannels;
-        memcpy(x_data, temp, sizeof(TI)*row_length);
-        temp += row_length;
-        /*
-        for ( x = 0 ; x < img->roi->width*img->nChannels ; x++ )
-        *x_data++ = *temp++;
-        */
-      }
-    }
-  }
-
-  /* get the matrix data */
-  TM * GetMatData(CvMat *mat)
-  {
-    TM* mat_data = new TM[mat->width*mat->height];
-    memcpy(mat_data, mat->data.ptr, sizeof(TM)*mat->width*mat->height);
-    return mat_data;
-
-    /*
-    int y, x;
-    TM* mat_data = new TM[mat->width*mat->height];
-    TM* temp = mat_data;
-    TM* x_data;
-    for ( y = 0 ; y < mat->height ; y++ ) {
-    x_data = (TM*)(mat->data.ptr + mat->step*y);
-    for ( x = 0 ; x < mat->width ; x++ )
-    *temp++ = *x_data++;
-    }
-    return mat_data;
-    */
-  };
-
-  /* set the matrix data */
-  void SetMatData(CvMat *mat, TM *mat_data)
-  {
-    memcpy(mat->data.ptr, mat_data, sizeof(TM)*mat->width*mat->height);
-
-    /*
-    int y, x;
-    TM* temp = mat_data;
-    TM* x_data;
-    for ( y = 0 ; y < mat->height ; y++ ) {
-    x_data = (TM*)(mat->data.ptr + mat->step*y);
-    for ( x = 0 ; x < mat->width ; x++ )
-    *x_data++ = *temp++;
-    }
-    */
-  }
-
-  /* convert the image data to the matrix data */
-  void ConvertData(IplImage *img_src, CvMat *mat_dst)
-  {
-    if (img_src->nChannels > 1) {
-      printf("Must be one-channel image for ConvertImageData!\n");
-      exit(1);
-    }
-
-    TI* _img_data = GetImageData(img_src);
-    TM* _mat_data = new TM[img_src->width*img_src->height];
-
-    TI* img_data = _img_data;
-    TM* mat_data = _mat_data;
-    int i;
-    for (i = 0; i < img_src->width*img_src->height; i++)
-      *mat_data++ = (TM)(*img_data++);
-
-    SetMatData(mat_dst, _mat_data);
-
-    delete[] _img_data;
-    delete[] _mat_data;
-  }
-
-  /* convert the matrix data to the image data */
-  void ConvertData(CvMat *mat_src, IplImage *img_dst)
-  {
-    if (img_dst->nChannels > 1) {
-      printf("Must be one-channel image for ConvertImageData!\n");
-      exit(1);
-    }
-
-    TM* _mat_data = GetMatData(mat_src);
-    TI* _img_data = new TI[mat_src->width*mat_src->height];
-
-    TM* mat_data = _mat_data;
-    TI* img_data = _img_data;
-
-    int i;
-    for (i = 0; i < mat_src->width*mat_src->height; i++)
-      *img_data++ = (TI)(*mat_data++);
-
-    SetImageData(img_dst, _img_data);
-
-    delete[] _img_data;
-    delete[] _mat_data;
-  }
-
-  COpencvDataConversion() {};
-  virtual ~COpencvDataConversion() {};
-};
diff --git a/package_bgs/MultiLayer/OpenCvLegacyIncludes.h b/package_bgs/MultiLayer/OpenCvLegacyIncludes.h
deleted file mode 100644
index 9d30c0ef28c2fd8d15e4daf933b0dd79cfa14441..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/OpenCvLegacyIncludes.h
+++ /dev/null
@@ -1,50 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// OpenCvLegacyIncludes.h: necessary includes to compile with OpenCV 3.
-//
-//////////////////////////////////////////////////////////////////////
-#pragma once
-
-#include "opencv2/core/core_c.h"
-#include "opencv2/core/types_c.h"
-#include "opencv2/imgproc/imgproc_c.h"
diff --git a/package_bgs/MultiLayer/blob.cpp b/package_bgs/MultiLayer/blob.cpp
deleted file mode 100644
index 5e0fa45fac0ee03a3ffa6c33e2f89ea82df5a9b7..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/blob.cpp
+++ /dev/null
@@ -1,1148 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/************************************************************************
-Blob.cpp
-
-- FUNCIONALITAT: Implementació de la classe CBlob
-- AUTOR: Inspecta S.L.
-MODIFICACIONS (Modificació, Autor, Data):
-
-
-FUNCTIONALITY: Implementation of the CBlob class and some helper classes to perform
-some calculations on it
-AUTHOR: Inspecta S.L.
-MODIFICATIONS (Modification, Author, Date):
-
-**************************************************************************/
-
-
-#include <limits.h>
-#include "blob.h"
-
-namespace Blob
-{
-
-  /**
-    - FUNCIÓ: CBlob
-    - FUNCIONALITAT: Constructor estàndard
-    - PARÀMETRES:
-    - RESULTAT:
-    - inicialització de totes les variables internes i de l'storage i la sequencia
-    per a les cantonades del blob
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlob
-      - FUNCTIONALITY: Standard constructor
-      - PARAMETERS:
-      - RESULT:
-      - memory allocation for the blob edges and initialization of member variables
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlob::CBlob()
-  {
-    etiqueta = -1;		// Flag indicates null region
-    exterior = 0;
-    area = 0.0f;
-    perimeter = 0.0f;
-    parent = -1;
-    minx = LONG_MAX;
-    maxx = 0;
-    miny = LONG_MAX;
-    maxy = 0;
-    sumx = 0;
-    sumy = 0;
-    sumxx = 0;
-    sumyy = 0;
-    sumxy = 0;
-    mean = 0;
-    stddev = 0;
-    externPerimeter = 0;
-
-    m_storage = cvCreateMemStorage(0);
-    edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
-      sizeof(CvContour),
-      sizeof(CvPoint), m_storage);
-  }
-
-  /**
-    - FUNCIÓ: CBlob
-    - FUNCIONALITAT: Constructor de còpia
-    - PARÀMETRES:
-    - RESULTAT:
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlob
-      - FUNCTIONALITY: Copy constructor
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlob::CBlob(const CBlob &src)
-  {
-    // copiem les propietats del blob origen a l'actual
-    etiqueta = src.etiqueta;
-    exterior = src.exterior;
-    area = src.Area();
-    perimeter = src.Perimeter();
-    parent = src.parent;
-    minx = src.minx;
-    maxx = src.maxx;
-    miny = src.miny;
-    maxy = src.maxy;
-    sumx = src.sumx;
-    sumy = src.sumy;
-    sumxx = src.sumxx;
-    sumyy = src.sumyy;
-    sumxy = src.sumxy;
-    mean = src.mean;
-    stddev = src.stddev;
-    externPerimeter = src.externPerimeter;
-
-    // copiem els edges del blob origen a l'actual
-    CvSeqReader reader;
-    CvSeqWriter writer;
-    CvPoint edgeactual;
-
-    // creem una sequencia buida per als edges
-    m_storage = cvCreateMemStorage(0);
-    edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
-      sizeof(CvContour),
-      sizeof(CvPoint), m_storage);
-
-    cvStartReadSeq(src.Edges(), &reader);
-    cvStartAppendToSeq(edges, &writer);
-
-    for (int i = 0; i < src.Edges()->total; i++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      CV_WRITE_SEQ_ELEM(edgeactual, writer);
-    }
-
-    cvEndWriteSeq(&writer);
-  }
-  CBlob::CBlob(const CBlob *src)
-  {
-    // copiem les propietats del blob origen a l'actual
-    etiqueta = src->etiqueta;
-    exterior = src->exterior;
-    area = src->Area();
-    perimeter = src->Perimeter();
-    parent = src->parent;
-    minx = src->minx;
-    maxx = src->maxx;
-    miny = src->miny;
-    maxy = src->maxy;
-    sumx = src->sumx;
-    sumy = src->sumy;
-    sumxx = src->sumxx;
-    sumyy = src->sumyy;
-    sumxy = src->sumxy;
-    mean = src->mean;
-    stddev = src->stddev;
-    externPerimeter = src->externPerimeter;
-
-    // copiem els edges del blob origen a l'actual
-    CvSeqReader reader;
-    CvSeqWriter writer;
-    CvPoint edgeactual;
-
-    // creem una sequencia buida per als edges
-    m_storage = cvCreateMemStorage(0);
-    edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
-      sizeof(CvContour),
-      sizeof(CvPoint), m_storage);
-
-    cvStartReadSeq(src->Edges(), &reader);
-    cvStartAppendToSeq(edges, &writer);
-
-    for (int i = 0; i < src->Edges()->total; i++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      CV_WRITE_SEQ_ELEM(edgeactual, writer);
-    }
-
-    cvEndWriteSeq(&writer);
-  }
-
-  /**
-    - FUNCIÓ: ~CBlob
-    - FUNCIONALITAT: Destructor estàndard
-    - PARÀMETRES:
-    - RESULTAT:
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlob
-      - FUNCTIONALITY: Standard destructor
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlob::~CBlob()
-  {
-    // Eliminar vèrtexs del blob
-    cvClearSeq(edges);
-    // i la zona de memòria on són
-    cvReleaseMemStorage(&m_storage);
-  }
-
-  /**
-    - FUNCIÓ: operator=
-    - FUNCIONALITAT: Operador d'assignació
-    - PARÀMETRES:
-    - src: blob a assignar a l'actual
-    - RESULTAT:
-    - Substitueix el blob actual per el src
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: Assigment operator
-      - FUNCTIONALITY: Assigns a blob to the current
-      - PARAMETERS:
-      - src: blob to assign
-      - RESULT:
-      - the current blob is replaced by the src blob
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CBlob& CBlob::operator=(const CBlob &src)
-  {
-    // si ja són el mateix, no cal fer res
-    if (this != &src)
-    {
-      // Eliminar vèrtexs del blob
-      cvClearSeq(edges);
-      // i la zona de memòria on són
-      cvReleaseMemStorage(&m_storage);
-
-      // creem una sequencia buida per als edges
-      m_storage = cvCreateMemStorage(0);
-      edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
-        sizeof(CvContour),
-        sizeof(CvPoint), m_storage);
-
-      // copiem les propietats del blob origen a l'actual
-      etiqueta = src.etiqueta;
-      exterior = src.exterior;
-      area = src.Area();
-      perimeter = src.Perimeter();
-      parent = src.parent;
-      minx = src.minx;
-      maxx = src.maxx;
-      miny = src.miny;
-      maxy = src.maxy;
-      sumx = src.sumx;
-      sumy = src.sumy;
-      sumxx = src.sumxx;
-      sumyy = src.sumyy;
-      sumxy = src.sumxy;
-      mean = src.mean;
-      stddev = src.stddev;
-      externPerimeter = src.externPerimeter;
-
-      // copiem els edges del blob origen a l'actual
-      CvSeqReader reader;
-      CvSeqWriter writer;
-      CvPoint edgeactual;
-
-      cvStartReadSeq(src.Edges(), &reader);
-      cvStartAppendToSeq(edges, &writer);
-
-      for (int i = 0; i < src.Edges()->total; i++)
-      {
-        CV_READ_SEQ_ELEM(edgeactual, reader);
-        CV_WRITE_SEQ_ELEM(edgeactual, writer);
-      }
-
-      cvEndWriteSeq(&writer);
-    }
-    return *this;
-  }
-
-  /**
-    - FUNCIÓ: FillBlob
-    - FUNCIONALITAT: Pinta l'interior d'un blob amb el color especificat
-    - PARÀMETRES:
-    - imatge: imatge on es vol pintar el el blob
-    - color: color amb que es vol pintar el blob
-    - RESULTAT:
-    - retorna la imatge d'entrada amb el blob pintat
-    - RESTRICCIONS:
-    - AUTOR:
-    - Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: FillBlob
-      - FUNCTIONALITY:
-      - Fills the blob with a specified colour
-      - PARAMETERS:
-      - imatge: where to paint
-      - color: colour to paint the blob
-      - RESULT:
-      - modifies input image and returns the seed point used to fill the blob
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlob::FillBlob(IplImage *imatge, CvScalar color, int offsetX /*=0*/, int offsetY /*=0*/) const
-  {
-
-    //verifiquem que existeixi el blob i que tingui cantonades
-    if (edges == NULL || edges->total == 0) return;
-
-    CvPoint edgeactual, pt1, pt2;
-    CvSeqReader reader;
-    vectorPunts vectorEdges = vectorPunts(edges->total);
-    vectorPunts::iterator itEdges, itEdgesSeguent;
-    bool dinsBlob;
-    int yActual;
-
-    // passem els punts del blob a un vector de punts de les STL
-    cvStartReadSeq(edges, &reader);
-    itEdges = vectorEdges.begin();
-    while (itEdges != vectorEdges.end())
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      *itEdges = edgeactual;
-      ++itEdges;
-    }
-    // ordenem el vector per les Y's i les X's d'esquerra a dreta
-    std::sort(vectorEdges.begin(), vectorEdges.end(), comparaCvPoint());
-
-    // recorrem el vector ordenat i fem linies entre punts consecutius
-    itEdges = vectorEdges.begin();
-    itEdgesSeguent = vectorEdges.begin() + 1;
-    dinsBlob = true;
-    while (itEdges != (vectorEdges.end() - 1))
-    {
-      yActual = (*itEdges).y;
-
-      if (((*itEdges).x != (*itEdgesSeguent).x) &&
-        ((*itEdgesSeguent).y == yActual)
-        )
-      {
-        if (dinsBlob)
-        {
-          pt1 = *itEdges;
-          pt1.x += offsetX;
-          pt1.y += offsetY;
-
-          pt2 = *itEdgesSeguent;
-          pt2.x += offsetX;
-          pt2.y += offsetY;
-
-          cvLine(imatge, pt1, pt2, color);
-        }
-        dinsBlob = !dinsBlob;
-      }
-      ++itEdges;
-      ++itEdgesSeguent;
-      if ((*itEdges).y != yActual) dinsBlob = true;
-    }
-    vectorEdges.clear();
-  }
-
-  /**
-    - FUNCIÓ: CopyEdges
-    - FUNCIONALITAT: Afegeix els vèrtexs del blob al blob destination
-    - PARÀMETRES:
-    - destination: blob al que volem afegir els vèrtexs
-    - RESULTAT:
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CopyEdges
-      - FUNCTIONALITY: Adds the blob edges to destination
-      - PARAMETERS:
-      - destination: where to add the edges
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlob::CopyEdges(CBlob &destination) const
-  {
-    CvSeqReader reader;
-    CvSeqWriter writer;
-    CvPoint edgeactual;
-
-    cvStartReadSeq(edges, &reader);
-    cvStartAppendToSeq(destination.Edges(), &writer);
-
-    for (int i = 0; i < edges->total; i++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      CV_WRITE_SEQ_ELEM(edgeactual, writer);
-    }
-
-    cvEndWriteSeq(&writer);
-  }
-
-  /**
-    - FUNCIÓ: ClearEdges
-    - FUNCIONALITAT: Elimina els vèrtexs del blob
-    - PARÀMETRES:
-    - RESULTAT:
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: ClearEdges
-      - FUNCTIONALITY: Delete current blob edges
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  void CBlob::ClearEdges()
-  {
-    // Eliminar vèrtexs del blob eliminat
-    cvClearSeq(edges);
-  }
-
-  /**
-    - FUNCIÓ: GetConvexHull
-    - FUNCIONALITAT: Retorna el poligon convex del blob
-    - PARÀMETRES:
-    - dst: sequencia on desarem el resultat (no ha d'estar inicialitzada)
-    - RESULTAT:
-    - true si tot ha anat bé
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: GetConvexHull
-      - FUNCTIONALITY: Calculates the convex hull polygon of the blob
-      - PARAMETERS:
-      - dst: where to store the result
-      - RESULT:
-      - true if no error ocurred
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  bool CBlob::GetConvexHull(CvSeq **dst) const
-  {
-    if (edges != NULL && edges->total > 0)
-    {
-      *dst = cvConvexHull2(edges, 0, CV_CLOCKWISE, 0);
-      return true;
-    }
-    return false;
-  }
-
-  /**
-    - FUNCIÓ: GetEllipse
-    - FUNCIONALITAT: Retorna l'ellipse que s'ajusta millor a les cantonades del blob
-    - PARÀMETRES:
-    - RESULTAT:
-    - estructura amb l'ellipse
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 25-05-2005.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: GetEllipse
-      - FUNCTIONALITY: Calculates the ellipse that best fits the edges of the blob
-      - PARAMETERS:
-      - RESULT:
-      - CvBox2D struct with the calculated ellipse
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  CvBox2D CBlob::GetEllipse() const
-  {
-    CvBox2D elipse;
-    // necessitem 6 punts per calcular l'elipse
-    if (edges != NULL && edges->total > 6)
-    {
-      elipse = cvFitEllipse2(edges);
-    }
-    else
-    {
-      elipse.center.x = 0.0;
-      elipse.center.y = 0.0;
-      elipse.size.width = 0.0;
-      elipse.size.height = 0.0;
-      elipse.angle = 0.0;
-    }
-    return elipse;
-  }
-
-
-
-  /***************************************************************************
-    Implementació de les classes per al càlcul de característiques sobre el blob
-
-    Implementation of the helper classes to perform operations on blobs
-    **************************************************************************/
-
-    /**
-      - FUNCIÓ: Moment
-      - FUNCIONALITAT: Calcula el moment pq del blob
-      - RESULTAT:
-      - retorna el moment pq especificat o 0 si el moment no està implementat
-      - RESTRICCIONS:
-      - Implementats els moments pq: 00, 01, 10, 20, 02
-      - AUTOR: Ricard Borràs
-      - DATA DE CREACIÓ: 20-07-2004.
-      - MODIFICACIÓ: Data. Autor. Descripció.
-      */
-      /**
-        - FUNCTION: Moment
-        - FUNCTIONALITY: Calculates the pq moment of the blob
-        - PARAMETERS:
-        - RESULT:
-        - returns the pq moment or 0 if the moment it is not implemented
-        - RESTRICTIONS:
-        - Currently, only implemented the 00, 01, 10, 20, 02 pq moments
-        - AUTHOR: Ricard Borràs
-        - CREATION DATE: 20-07-2004.
-        - MODIFICATION: Date. Author. Description.
-        */
-  double CBlobGetMoment::operator()(const CBlob &blob) const
-  {
-    //Moment 00
-    if ((m_p == 0) && (m_q == 0))
-      return blob.Area();
-
-    //Moment 10
-    if ((m_p == 1) && (m_q == 0))
-      return blob.SumX();
-
-    //Moment 01
-    if ((m_p == 0) && (m_q == 1))
-      return blob.SumY();
-
-    //Moment 20
-    if ((m_p == 2) && (m_q == 0))
-      return blob.SumXX();
-
-    //Moment 02
-    if ((m_p == 0) && (m_q == 2))
-      return blob.SumYY();
-
-    return 0;
-  }
-
-  /**
-    - FUNCIÓ: HullPerimeter
-    - FUNCIONALITAT: Calcula la longitud del perimetre convex del blob.
-    Fa servir la funció d'OpenCV cvConvexHull2 per a
-    calcular el perimetre convex.
-
-    - PARÀMETRES:
-    - RESULTAT:
-    - retorna la longitud del perímetre convex del blob. Si el blob no té coordenades
-    associades retorna el perímetre normal del blob.
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobGetHullPerimeter
-      - FUNCTIONALITY: Calculates the convex hull perimeter of the blob
-      - PARAMETERS:
-      - RESULT:
-      - returns the convex hull perimeter of the blob or the perimeter if the
-      blob edges could not be retrieved
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetHullPerimeter::operator()(const CBlob &blob) const
-  {
-    if (blob.Edges() != NULL && blob.Edges()->total > 0)
-    {
-      CvSeq *hull = cvConvexHull2(blob.Edges(), 0, CV_CLOCKWISE, 1);
-      return fabs(cvArcLength(hull, CV_WHOLE_SEQ, 1));
-    }
-    return blob.Perimeter();
-  }
-
-  double CBlobGetHullArea::operator()(const CBlob &blob) const
-  {
-    if (blob.Edges() != NULL && blob.Edges()->total > 0)
-    {
-      CvSeq *hull = cvConvexHull2(blob.Edges(), 0, CV_CLOCKWISE, 1);
-      return fabs(cvContourArea(hull));
-    }
-    return blob.Perimeter();
-  }
-
-  /**
-    - FUNCIÓ: MinX_at_MinY
-    - FUNCIONALITAT: Calcula el valor MinX a MinY.
-    - PARÀMETRES:
-    - blob: blob del que volem calcular el valor
-    - RESULTAT:
-    - retorna la X minima en la Y minima.
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobGetMinXatMinY
-      - FUNCTIONALITY: Calculates the minimum X on the minimum Y
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetMinXatMinY::operator()(const CBlob &blob) const
-  {
-    double MinX_at_MinY = LONG_MAX;
-
-    CvSeqReader reader;
-    CvPoint edgeactual;
-
-    cvStartReadSeq(blob.Edges(), &reader);
-
-    for (int j = 0; j < blob.Edges()->total; j++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      if ((edgeactual.y == blob.MinY()) && (edgeactual.x < MinX_at_MinY))
-      {
-        MinX_at_MinY = edgeactual.x;
-      }
-    }
-
-    return MinX_at_MinY;
-  }
-
-  /**
-    - FUNCIÓ: MinY_at_MaxX
-    - FUNCIONALITAT: Calcula el valor MinX a MaxX.
-    - PARÀMETRES:
-    - blob: blob del que volem calcular el valor
-    - RESULTAT:
-    - retorna la Y minima en la X maxima.
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobGetMinXatMinY
-      - FUNCTIONALITY: Calculates the minimum Y on the maximum X
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetMinYatMaxX::operator()(const CBlob &blob) const
-  {
-    double MinY_at_MaxX = LONG_MAX;
-
-    CvSeqReader reader;
-    CvPoint edgeactual;
-
-    cvStartReadSeq(blob.Edges(), &reader);
-
-    for (int j = 0; j < blob.Edges()->total; j++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      if ((edgeactual.x == blob.MaxX()) && (edgeactual.y < MinY_at_MaxX))
-      {
-        MinY_at_MaxX = edgeactual.y;
-      }
-    }
-
-    return MinY_at_MaxX;
-  }
-
-  /**
-    - FUNCIÓ: MaxX_at_MaxY
-    - FUNCIONALITAT: Calcula el valor MaxX a MaxY.
-    - PARÀMETRES:
-    - blob: blob del que volem calcular el valor
-    - RESULTAT:
-    - retorna la X maxima en la Y maxima.
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobGetMaxXatMaxY
-      - FUNCTIONALITY: Calculates the maximum X on the maximum Y
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetMaxXatMaxY::operator()(const CBlob &blob) const
-  {
-    double MaxX_at_MaxY = LONG_MIN;
-
-    CvSeqReader reader;
-    CvPoint edgeactual;
-
-    cvStartReadSeq(blob.Edges(), &reader);
-
-    for (int j = 0; j < blob.Edges()->total; j++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      if ((edgeactual.y == blob.MaxY()) && (edgeactual.x > MaxX_at_MaxY))
-      {
-        MaxX_at_MaxY = edgeactual.x;
-      }
-    }
-
-    return MaxX_at_MaxY;
-  }
-
-  /**
-    - FUNCIÓ: MaxY_at_MinX
-    - FUNCIONALITAT: Calcula el valor MaxY a MinX.
-    - PARÀMETRES:
-    - blob: blob del que volem calcular el valor
-    - RESULTAT:
-    - retorna la Y maxima en la X minima.
-    - RESTRICCIONS:
-    - AUTOR: Ricard Borràs
-    - DATA DE CREACIÓ: 20-07-2004.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: CBlobGetMaxYatMinX
-      - FUNCTIONALITY: Calculates the maximum Y on the minimum X
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetMaxYatMinX::operator()(const CBlob &blob) const
-  {
-    double MaxY_at_MinX = LONG_MIN;
-
-    CvSeqReader reader;
-    CvPoint edgeactual;
-
-    cvStartReadSeq(blob.Edges(), &reader);
-
-    for (int j = 0; j < blob.Edges()->total; j++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      if ((edgeactual.x == blob.MinY()) && (edgeactual.y > MaxY_at_MinX))
-      {
-        MaxY_at_MinX = edgeactual.y;
-      }
-    }
-
-    return MaxY_at_MinX;
-  }
-
-  /**
-    Retorna l'elongació del blob (longitud/amplada)
-    */
-    /**
-      - FUNCTION: CBlobGetElongation
-      - FUNCTIONALITY: Calculates the elongation of the blob ( length/breadth )
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - See below to see how the lenght and the breadth are aproximated
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetElongation::operator()(const CBlob &blob) const
-  {
-    double ampladaC, longitudC, amplada, longitud;
-
-    ampladaC = (double)(blob.Perimeter() + sqrt(pow(blob.Perimeter(), 2) - 16 * blob.Area())) / 4;
-    if (ampladaC <= 0.0) return 0;
-    longitudC = (double)blob.Area() / ampladaC;
-
-    longitud = MAX(longitudC, ampladaC);
-    amplada = MIN(longitudC, ampladaC);
-
-    return (double)longitud / amplada;
-  }
-
-  /**
-    Retorna la compacitat del blob
-    */
-    /**
-      - FUNCTION: CBlobGetCompactness
-      - FUNCTIONALITY: Calculates the compactness of the blob
-      ( maximum for circle shaped blobs, minimum for the rest)
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetCompactness::operator()(const CBlob &blob) const
-  {
-    if (blob.Area() != 0.0)
-      return (double)pow(blob.Perimeter(), 2) / (4 * CV_PI*blob.Area());
-    else
-      return 0.0;
-  }
-
-  /**
-    Retorna la rugositat del blob
-    */
-    /**
-      - FUNCTION: CBlobGetRoughness
-      - FUNCTIONALITY: Calculates the roughness of the blob
-      ( ratio between perimeter and convex hull perimeter)
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetRoughness::operator()(const CBlob &blob) const
-  {
-    CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter();
-
-    double hullPerimeter = getHullPerimeter(blob);
-
-    if (hullPerimeter != 0.0)
-      return blob.Perimeter() / hullPerimeter;//HullPerimeter();
-
-    return 0.0;
-  }
-
-  /**
-    Retorna la longitud del blob
-    */
-    /**
-      - FUNCTION: CBlobGetLength
-      - FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the blob)
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - The lenght is an aproximation to the real lenght
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetLength::operator()(const CBlob &blob) const
-  {
-    double ampladaC, longitudC;
-    double tmp;
-
-    tmp = blob.Perimeter()*blob.Perimeter() - 16 * blob.Area();
-
-    if (tmp > 0.0)
-      ampladaC = (double)(blob.Perimeter() + sqrt(tmp)) / 4;
-    // error intrínsec en els càlculs de l'àrea i el perímetre
-    else
-      ampladaC = (double)(blob.Perimeter()) / 4;
-
-    if (ampladaC <= 0.0) return 0;
-    longitudC = (double)blob.Area() / ampladaC;
-
-    return MAX(longitudC, ampladaC);
-  }
-
-  /**
-    Retorna l'amplada del blob
-    */
-    /**
-      - FUNCTION: CBlobGetBreadth
-      - FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the blob)
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - The breadth is an aproximation to the real breadth
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetBreadth::operator()(const CBlob &blob) const
-  {
-    double ampladaC, longitudC;
-    double tmp;
-
-    tmp = blob.Perimeter()*blob.Perimeter() - 16 * blob.Area();
-
-    if (tmp > 0.0)
-      ampladaC = (double)(blob.Perimeter() + sqrt(tmp)) / 4;
-    // error intrínsec en els càlculs de l'àrea i el perímetre
-    else
-      ampladaC = (double)(blob.Perimeter()) / 4;
-
-    if (ampladaC <= 0.0) return 0;
-    longitudC = (double)blob.Area() / ampladaC;
-
-    return MIN(longitudC, ampladaC);
-  }
-
-  /**
-    Calcula la distància entre un punt i el centre del blob
-    */
-    /**
-      - FUNCTION: CBlobGetDistanceFromPoint
-      - FUNCTIONALITY: Calculates the euclidean distance between the blob center and
-      the point specified in the constructor
-      - PARAMETERS:
-      - RESULT:
-      - RESTRICTIONS:
-      - AUTHOR: Ricard Borràs
-      - CREATION DATE: 25-05-2005.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetDistanceFromPoint::operator()(const CBlob &blob) const
-  {
-    double xmitjana, ymitjana;
-    CBlobGetXCenter getXCenter;
-    CBlobGetYCenter getYCenter;
-
-    xmitjana = m_x - getXCenter(blob);
-    ymitjana = m_y - getYCenter(blob);
-
-    return sqrt((xmitjana*xmitjana) + (ymitjana*ymitjana));
-  }
-
-  /**
-    - FUNCIÓ: BlobGetXYInside
-    - FUNCIONALITAT: Calcula si un punt cau dins de la capsa rectangular
-    del blob
-    - RESULTAT:
-    - retorna 1 si hi està; 0 si no
-    - RESTRICCIONS:
-    - AUTOR: Francesc Pinyol Margalef
-    - DATA DE CREACIÓ: 16-01-2006.
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-    /**
-      - FUNCTION: BlobGetXYInside
-      - FUNCTIONALITY: Calculates whether a point is inside the
-      rectangular bounding box of a blob
-      - PARAMETERS:
-      - RESULT:
-      - returns 1 if it is inside; o if not
-      - RESTRICTIONS:
-      - AUTHOR: Francesc Pinyol Margalef
-      - CREATION DATE: 16-01-2006.
-      - MODIFICATION: Date. Author. Description.
-      */
-  double CBlobGetXYInside::operator()(const CBlob &blob) const
-  {
-    if (blob.Edges() == NULL || blob.Edges()->total == 0) return 0.0;
-
-    // passem els punts del blob a un vector de punts de les STL
-    CvSeqReader reader;
-    CBlob::vectorPunts vectorEdges;
-    CBlob::vectorPunts::iterator itEdges, itEdgesSeguent;
-    CvPoint edgeactual;
-    bool dinsBlob;
-
-    // agafem tots els punts amb la mateixa y que l'actual
-    cvStartReadSeq(blob.Edges(), &reader);
-
-    for (int i = 0; i < blob.Edges()->total; i++)
-    {
-      CV_READ_SEQ_ELEM(edgeactual, reader);
-      if (edgeactual.y == m_p.y)
-        vectorEdges.push_back(edgeactual);
-    }
-
-    if (vectorEdges.empty()) return 0.0;
-
-    // ordenem el vector per les Y's i les X's d'esquerra a dreta
-    std::sort(vectorEdges.begin(), vectorEdges.end(), CBlob::comparaCvPoint());
-
-    // recorrem el punts del blob de la mateixa fila que el punt d'entrada
-    // i mirem si la X del punt d'entrada està entre dos coordenades "plenes"
-    // del blob
-    itEdges = vectorEdges.begin();
-    itEdgesSeguent = vectorEdges.begin() + 1;
-    dinsBlob = true;
-
-    while (itEdges != (vectorEdges.end() - 1))
-    {
-      if ((*itEdges).x <= m_p.x && (*itEdgesSeguent).x >= m_p.x && dinsBlob)
-      {
-        vectorEdges.clear();
-        return 1.0;
-      }
-
-      ++itEdges;
-      ++itEdgesSeguent;
-      dinsBlob = !dinsBlob;
-    }
-
-    vectorEdges.clear();
-    return 0.0;
-  }
-
-#ifdef BLOB_OBJECT_FACTORY
-
-  /**
-    - FUNCIÓ: RegistraTotsOperadors
-    - FUNCIONALITAT: Registrar tots els operadors definits a blob.h
-    - PARÀMETRES:
-    - fabricaOperadorsBlob: fàbrica on es registraran els operadors
-    - RESULTAT:
-    - Modifica l'objecte fabricaOperadorsBlob
-    - RESTRICCIONS:
-    - Només es registraran els operadors de blob.h. Si se'n volen afegir, cal afegir-los amb
-    el mètode Register de la fàbrica.
-    - AUTOR: rborras
-    - DATA DE CREACIÓ: 2006/05/18
-    - MODIFICACIÓ: Data. Autor. Descripció.
-    */
-  void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob)
-  {
-    // blob shape
-    fabricaOperadorsBlob.Register(CBlobGetArea().GetNom(), Type2Type<CBlobGetArea>());
-    fabricaOperadorsBlob.Register(CBlobGetBreadth().GetNom(), Type2Type<CBlobGetBreadth>());
-    fabricaOperadorsBlob.Register(CBlobGetCompactness().GetNom(), Type2Type<CBlobGetCompactness>());
-    fabricaOperadorsBlob.Register(CBlobGetElongation().GetNom(), Type2Type<CBlobGetElongation>());
-    fabricaOperadorsBlob.Register(CBlobGetExterior().GetNom(), Type2Type<CBlobGetExterior>());
-    fabricaOperadorsBlob.Register(CBlobGetLength().GetNom(), Type2Type<CBlobGetLength>());
-    fabricaOperadorsBlob.Register(CBlobGetPerimeter().GetNom(), Type2Type<CBlobGetPerimeter>());
-    fabricaOperadorsBlob.Register(CBlobGetRoughness().GetNom(), Type2Type<CBlobGetRoughness>());
-
-    // extern pixels
-    fabricaOperadorsBlob.Register(CBlobGetExternPerimeterRatio().GetNom(), Type2Type<CBlobGetExternPerimeterRatio>());
-    fabricaOperadorsBlob.Register(CBlobGetExternHullPerimeterRatio().GetNom(), Type2Type<CBlobGetExternHullPerimeterRatio>());
-    fabricaOperadorsBlob.Register(CBlobGetExternPerimeter().GetNom(), Type2Type<CBlobGetExternPerimeter>());
-
-
-    // hull
-    fabricaOperadorsBlob.Register(CBlobGetHullPerimeter().GetNom(), Type2Type<CBlobGetHullPerimeter>());
-    fabricaOperadorsBlob.Register(CBlobGetHullArea().GetNom(), Type2Type<CBlobGetHullArea>());
-
-
-    // elipse info
-    fabricaOperadorsBlob.Register(CBlobGetMajorAxisLength().GetNom(), Type2Type<CBlobGetMajorAxisLength>());
-    fabricaOperadorsBlob.Register(CBlobGetMinorAxisLength().GetNom(), Type2Type<CBlobGetMinorAxisLength>());
-    fabricaOperadorsBlob.Register(CBlobGetAxisRatio().GetNom(), Type2Type<CBlobGetAxisRatio>());
-    fabricaOperadorsBlob.Register(CBlobGetOrientation().GetNom(), Type2Type<CBlobGetOrientation>());
-    fabricaOperadorsBlob.Register(CBlobGetOrientationCos().GetNom(), Type2Type<CBlobGetOrientationCos>());
-    fabricaOperadorsBlob.Register(CBlobGetAreaElipseRatio().GetNom(), Type2Type<CBlobGetAreaElipseRatio>());
-
-    // min an max
-    fabricaOperadorsBlob.Register(CBlobGetMaxX().GetNom(), Type2Type<CBlobGetMaxX>());
-    fabricaOperadorsBlob.Register(CBlobGetMaxY().GetNom(), Type2Type<CBlobGetMaxY>());
-    fabricaOperadorsBlob.Register(CBlobGetMinX().GetNom(), Type2Type<CBlobGetMinX>());
-    fabricaOperadorsBlob.Register(CBlobGetMinY().GetNom(), Type2Type<CBlobGetMinY>());
-
-    fabricaOperadorsBlob.Register(CBlobGetMaxXatMaxY().GetNom(), Type2Type<CBlobGetMaxXatMaxY>());
-    fabricaOperadorsBlob.Register(CBlobGetMaxYatMinX().GetNom(), Type2Type<CBlobGetMaxYatMinX>());
-    fabricaOperadorsBlob.Register(CBlobGetMinXatMinY().GetNom(), Type2Type<CBlobGetMinXatMinY>());
-    fabricaOperadorsBlob.Register(CBlobGetMinYatMaxX().GetNom(), Type2Type<CBlobGetMinYatMaxX>());
-
-    // grey level stats
-    fabricaOperadorsBlob.Register(CBlobGetMean().GetNom(), Type2Type<CBlobGetMean>());
-    fabricaOperadorsBlob.Register(CBlobGetStdDev().GetNom(), Type2Type<CBlobGetStdDev>());
-
-    // coordinate info
-    fabricaOperadorsBlob.Register(CBlobGetXYInside().GetNom(), Type2Type<CBlobGetXYInside>());
-    fabricaOperadorsBlob.Register(CBlobGetDiffY().GetNom(), Type2Type<CBlobGetDiffY>());
-    fabricaOperadorsBlob.Register(CBlobGetDiffX().GetNom(), Type2Type<CBlobGetDiffX>());
-    fabricaOperadorsBlob.Register(CBlobGetXCenter().GetNom(), Type2Type<CBlobGetXCenter>());
-    fabricaOperadorsBlob.Register(CBlobGetYCenter().GetNom(), Type2Type<CBlobGetYCenter>());
-    fabricaOperadorsBlob.Register(CBlobGetDistanceFromPoint().GetNom(), Type2Type<CBlobGetDistanceFromPoint>());
-
-    // moments
-    fabricaOperadorsBlob.Register(CBlobGetMoment().GetNom(), Type2Type<CBlobGetMoment>());
-
-  }
-
-#endif
-
-}
-
diff --git a/package_bgs/MultiLayer/blob.h b/package_bgs/MultiLayer/blob.h
deleted file mode 100644
index b7d5fe1ce788cf21d5e978807243f8f2847027e3..0000000000000000000000000000000000000000
--- a/package_bgs/MultiLayer/blob.h
+++ /dev/null
@@ -1,838 +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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/************************************************************************
-Blob.h
-
-FUNCIONALITAT: Definició de la classe CBlob
-AUTOR: Inspecta S.L.
-MODIFICACIONS (Modificació, Autor, Data):
-
-FUNCTIONALITY: Definition of the CBlob class and some helper classes to perform
-some calculations on it
-AUTHOR: Inspecta S.L.
-MODIFICATIONS (Modification, Author, Date):
-
-**************************************************************************/
-#pragma once
-
-//#include "cxcore.h"
-#include "BlobLibraryConfiguration.h"
-#include <functional>
-#include <vector>
-#include <algorithm>
-#include "OpenCvLegacyIncludes.h"
-//! Factor de conversió de graus a radians
-#define DEGREE2RAD		(CV_PI / 180.0)
-
-namespace Blob
-{
-
-  /**
-    Classe que representa un blob, entés com un conjunt de pixels del
-    mateix color contigus en una imatge binaritzada.
-
-    Class to represent a blob, a group of connected pixels in a binary image
-    */
-  class CBlob
-  {
-  public:
-    //! Constructor estàndard
-    //! Standard constructor
-    CBlob();
-    //! Constructor de còpia
-    //! Copy constructor
-    CBlob(const CBlob &src);
-    CBlob(const CBlob *src);
-
-    //! Destructor estàndard
-    //! Standard Destructor
-    ~CBlob();
-
-    //! Operador d'assignació
-    //! Assigment operator
-    CBlob& operator=(const CBlob &src);
-
-    //! Indica si el blob està buit ( no té cap info associada )
-    //! Shows if the blob has associated information
-    bool IsEmpty() const
-    {
-      return (area == 0.0 && perimeter == 0.0);
-    };
-
-    //! Neteja les cantonades del blob
-    //! Clears the edges of the blob
-    void ClearEdges();
-    //! Copia les cantonades del blob a un altre (les afegeix al destí)
-    //! Adds the blob edges to another blob
-    void CopyEdges(CBlob &destination) const;
-    //! Retorna el poligon convex del blob
-    //! Calculates the convex hull of the blob
-    bool GetConvexHull(CvSeq **dst) const;
-    //! Calcula l'elipse que s'adapta als vèrtexs del blob
-    //! Fits an ellipse to the blob edges
-    CvBox2D GetEllipse() const;
-
-    //! Pinta l'interior d'un blob d'un color determinat
-    //! Paints the blob in an image
-    void FillBlob(IplImage *imatge, CvScalar color, int offsetX = 0, int offsetY = 0) const;
-
-    //! Funcions GET sobre els valors dels blobs
-    //! Get functions
-
-    inline int Label() const { return etiqueta; }
-    inline int Parent() const { return parent; }
-    inline double Area() const { return area; }
-    inline double Perimeter() const { return perimeter; }
-    inline double ExternPerimeter() const { return externPerimeter; }
-    inline int	  Exterior() const { return exterior; }
-    inline double Mean() const { return mean; }
-    inline double StdDev() const { return stddev; }
-    inline double MinX() const { return minx; }
-    inline double MinY() const { return miny; }
-    inline double MaxX() const { return maxx; }
-    inline double MaxY() const { return maxy; }
-    inline CvSeq *Edges() const { return edges; }
-    inline double SumX() const { return sumx; }
-    inline double SumY() const { return sumy; }
-    inline double SumXX() const { return sumxx; }
-    inline double SumYY() const { return sumyy; }
-    inline double SumXY() const { return sumxy; }
-
-    //! etiqueta del blob
-    //! label of the blob
-    int etiqueta;
-    //! flag per indicar si es exterior o no
-    //! true for extern blobs
-    int exterior;
-    //! area del blob
-    //! Blob area
-    double area;
-    //! perimetre del blob
-    //! Blob perimeter
-    double perimeter;
-    //! quantitat de perimetre del blob extern
-    //! amount of blob perimeter which is exterior
-    double externPerimeter;
-    //! etiqueta del blob pare
-    //! label of the parent blob
-    int parent;
-    //! moments
-    double sumx;
-    double sumy;
-    double sumxx;
-    double sumyy;
-    double sumxy;
-    //! Bounding rect
-    double minx;
-    double maxx;
-    double miny;
-    double maxy;
-
-    //! mitjana
-    //! mean of the grey scale values of the blob pixels
-    double mean;
-    //! desviació standard
-    //! standard deviation of the grey scale values of the blob pixels
-    double stddev;
-
-    //! àrea de memòria on es desaran els punts de contorn del blob
-    //! storage which contains the edges of the blob
-    CvMemStorage *m_storage;
-    //!	Sequència de punts del contorn del blob
-    //! Sequence with the edges of the blob
-    CvSeq *edges;
-
-
-    //! Point datatype for plotting (FillBlob)
-    typedef std::vector<CvPoint> vectorPunts;
-
-    //! Helper class to compare two CvPoints (for sorting in FillBlob)
-    struct comparaCvPoint : public std::binary_function<CvPoint, CvPoint, bool>
-    {
-      //! Definim que un punt és menor com més amunt a la dreta estigui
-      bool operator()(CvPoint a, CvPoint b)
-      {
-        if (a.y == b.y)
-          return a.x < b.x;
-        else
-          return a.y < b.y;
-      }
-    };
-  };
-
-
-
-  /**************************************************************************
-    Definició de les classes per a fer operacions sobre els blobs
-
-    Helper classes to perform operations on blobs
-    **************************************************************************/
-
-
-    //! Classe d'on derivarem totes les operacions sobre els blobs
-    //! Interface to derive all blob operations
-  class COperadorBlob
-  {
-  public:
-    virtual ~COperadorBlob() {};
-
-    //! Aplica l'operació al blob
-    virtual double operator()(const CBlob &blob) const = 0;
-    //! Obté el nom de l'operador
-    virtual const char *GetNom() const = 0;
-
-    operator COperadorBlob*() const
-    {
-      return (COperadorBlob*)this;
-    }
-  };
-
-  typedef COperadorBlob funcio_calculBlob;
-
-#ifdef BLOB_OBJECT_FACTORY
-  /**
-    Funció per comparar dos identificadors dins de la fàbrica de COperadorBlobs
-    */
-  struct functorComparacioIdOperador
-  {
-    bool operator()(const char* s1, const char* s2) const
-    {
-      return strcmp(s1, s2) < 0;
-    }
-  };
-
-  //! Definition of Object factory type for COperadorBlob objects
-  typedef ObjectFactory<COperadorBlob, const char *, functorComparacioIdOperador > t_OperadorBlobFactory;
-
-  //! Funció global per a registrar tots els operadors definits a blob.h
-  void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob);
-
-#endif
-
-  //! Classe per calcular l'àrea d'un blob
-  //! Class to get the area of a blob
-  class CBlobGetArea : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.Area();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetArea";
-    }
-  };
-
-  //! Classe per calcular el perimetre d'un blob
-  //! Class to get the perimeter of a blob
-  class CBlobGetPerimeter : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.Perimeter();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetPerimeter";
-    }
-  };
-
-  //! Classe que diu si un blob és extern o no
-  //! Class to get the extern flag of a blob
-  class CBlobGetExterior : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.Exterior();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetExterior";
-    }
-  };
-
-  //! Classe per calcular la mitjana de nivells de gris d'un blob
-  //! Class to get the mean grey level of a blob
-  class CBlobGetMean : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.Mean();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMean";
-    }
-  };
-
-  //! Classe per calcular la desviació estàndard dels nivells de gris d'un blob
-  //! Class to get the standard deviation of the grey level values of a blob
-  class CBlobGetStdDev : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.StdDev();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetStdDev";
-    }
-  };
-
-  //! Classe per calcular la compacitat d'un blob
-  //! Class to calculate the compactness of a blob
-  class CBlobGetCompactness : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetCompactness";
-    }
-  };
-
-  //! Classe per calcular la longitud d'un blob
-  //! Class to calculate the length of a blob
-  class CBlobGetLength : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetLength";
-    }
-  };
-
-  //! Classe per calcular l'amplada d'un blob
-  //! Class to calculate the breadth of a blob
-  class CBlobGetBreadth : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetBreadth";
-    }
-  };
-
-  //! Classe per calcular la diferència en X del blob
-  class CBlobGetDiffX : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.maxx - blob.minx;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetDiffX";
-    }
-  };
-
-  //! Classe per calcular la diferència en X del blob
-  class CBlobGetDiffY : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.maxy - blob.miny;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetDiffY";
-    }
-  };
-
-  //! Classe per calcular el moment PQ del blob
-  //! Class to calculate the P,Q moment of a blob
-  class CBlobGetMoment : public COperadorBlob
-  {
-  public:
-    //! Constructor estàndard
-    //! Standard constructor (gets the 00 moment)
-    CBlobGetMoment()
-    {
-      m_p = m_q = 0;
-    }
-    //! Constructor: indiquem el moment p,q a calcular
-    //! Constructor: gets the PQ moment
-    CBlobGetMoment(int p, int q)
-    {
-      m_p = p;
-      m_q = q;
-    };
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetMoment";
-    }
-
-  private:
-    //! moment que volem calcular
-    int m_p, m_q;
-  };
-
-  //! Classe per calcular el perimetre del poligon convex d'un blob
-  //! Class to calculate the convex hull perimeter of a blob
-  class CBlobGetHullPerimeter : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetHullPerimeter";
-    }
-  };
-
-  //! Classe per calcular l'àrea del poligon convex d'un blob
-  //! Class to calculate the convex hull area of a blob
-  class CBlobGetHullArea : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetHullArea";
-    }
-  };
-
-  //! Classe per calcular la x minima en la y minima
-  //! Class to calculate the minimum x on the minimum y
-  class CBlobGetMinXatMinY : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetMinXatMinY";
-    }
-  };
-
-  //! Classe per calcular la y minima en la x maxima
-  //! Class to calculate the minimum y on the maximum x
-  class CBlobGetMinYatMaxX : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetMinYatMaxX";
-    }
-  };
-
-  //! Classe per calcular la x maxima en la y maxima
-  //! Class to calculate the maximum x on the maximum y
-  class CBlobGetMaxXatMaxY : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetMaxXatMaxY";
-    }
-  };
-
-  //! Classe per calcular la y maxima en la x minima
-  //! Class to calculate the maximum y on the minimum y
-  class CBlobGetMaxYatMinX : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetMaxYatMinX";
-    }
-  };
-
-  //! Classe per a calcular la x mínima
-  //! Class to get the minimum x
-  class CBlobGetMinX : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MinX();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMinX";
-    }
-  };
-
-  //! Classe per a calcular la x màxima
-  //! Class to get the maximum x
-  class CBlobGetMaxX : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MaxX();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMaxX";
-    }
-  };
-
-  //! Classe per a calcular la y mínima
-  //! Class to get the minimum y
-  class CBlobGetMinY : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MinY();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMinY";
-    }
-  };
-
-  //! Classe per a calcular la y màxima
-  //! Class to get the maximum y
-  class CBlobGetMaxY : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MaxY();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMax";
-    }
-  };
-
-
-  //! Classe per calcular l'elongacio d'un blob
-  //! Class to calculate the elongation of the blob
-  class CBlobGetElongation : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetElongation";
-    }
-  };
-
-  //! Classe per calcular la rugositat d'un blob
-  //! Class to calculate the roughness of the blob
-  class CBlobGetRoughness : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetRoughness";
-    }
-  };
-
-  //! Classe per calcular la distància entre el centre del blob i un punt donat
-  //! Class to calculate the euclidean distance between the center of a blob and a given point
-  class CBlobGetDistanceFromPoint : public COperadorBlob
-  {
-  public:
-    //! Standard constructor (distance to point 0,0)
-    CBlobGetDistanceFromPoint()
-    {
-      m_x = m_y = 0.0;
-    }
-    //! Constructor (distance to point x,y)
-    CBlobGetDistanceFromPoint(const double x, const double y)
-    {
-      m_x = x;
-      m_y = y;
-    }
-
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetDistanceFromPoint";
-    }
-
-  private:
-    // coordenades del punt on volem calcular la distància
-    double m_x, m_y;
-  };
-
-  //! Classe per calcular el nombre de pixels externs d'un blob
-  //! Class to get the number of extern pixels of a blob
-  class CBlobGetExternPerimeter : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.ExternPerimeter();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetExternPerimeter";
-    }
-  };
-
-  //! Classe per calcular el ratio entre el perimetre i nombre pixels externs
-  //! valors propers a 0 indiquen que la majoria del blob és intern
-  //! valors propers a 1 indiquen que la majoria del blob és extern
-  //! Class to calculate the ratio between the perimeter and the number of extern pixels
-  class CBlobGetExternPerimeterRatio : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      if (blob.Perimeter() != 0)
-        return blob.ExternPerimeter() / blob.Perimeter();
-      else
-        return blob.ExternPerimeter();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetExternPerimeterRatio";
-    }
-  };
-
-  //! Classe per calcular el ratio entre el perimetre convex i nombre pixels externs
-  //! valors propers a 0 indiquen que la majoria del blob és intern
-  //! valors propers a 1 indiquen que la majoria del blob és extern
-  //! Class to calculate the ratio between the perimeter and the number of extern pixels
-  class CBlobGetExternHullPerimeterRatio : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CBlobGetHullPerimeter getHullPerimeter;
-      double hullPerimeter;
-
-      if ((hullPerimeter = getHullPerimeter(blob)) != 0)
-        return blob.ExternPerimeter() / hullPerimeter;
-      else
-        return blob.ExternPerimeter();
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetExternHullPerimeterRatio";
-    }
-  };
-
-  //! Classe per calcular el centre en el eix X d'un blob
-  //! Class to calculate the center in the X direction
-  class CBlobGetXCenter : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MinX() + ((blob.MaxX() - blob.MinX()) / 2.0);
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetXCenter";
-    }
-  };
-
-  //! Classe per calcular el centre en el eix Y d'un blob
-  //! Class to calculate the center in the Y direction
-  class CBlobGetYCenter : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      return blob.MinY() + ((blob.MaxY() - blob.MinY()) / 2.0);
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetYCenter";
-    }
-  };
-
-  //! Classe per calcular la longitud de l'eix major d'un blob
-  //! Class to calculate the length of the major axis of the ellipse that fits the blob edges
-  class CBlobGetMajorAxisLength : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CvBox2D elipse = blob.GetEllipse();
-
-      return elipse.size.width;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMajorAxisLength";
-    }
-  };
-
-  //! Classe per calcular el ratio entre l'area de la elipse i la de la taca
-  //! Class
-  class CBlobGetAreaElipseRatio : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      if (blob.Area() == 0.0) return 0.0;
-
-      CvBox2D elipse = blob.GetEllipse();
-      double ratioAreaElipseAreaTaca = ((elipse.size.width / 2.0)
-        *
-        (elipse.size.height / 2.0)
-        *CV_PI
-        )
-        /
-        blob.Area();
-
-      return ratioAreaElipseAreaTaca;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetAreaElipseRatio";
-    }
-  };
-
-  //! Classe per calcular la longitud de l'eix menor d'un blob
-  //! Class to calculate the length of the minor axis of the ellipse that fits the blob edges
-  class CBlobGetMinorAxisLength : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CvBox2D elipse = blob.GetEllipse();
-
-      return elipse.size.height;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetMinorAxisLength";
-    }
-  };
-
-  //! Classe per calcular l'orientació de l'ellipse del blob en radians
-  //! Class to calculate the orientation of the ellipse that fits the blob edges in radians
-  class CBlobGetOrientation : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CvBox2D elipse = blob.GetEllipse();
-
-      if (elipse.angle > 180.0)
-        return ((elipse.angle - 180.0)* DEGREE2RAD);
-      else
-        return (elipse.angle * DEGREE2RAD);
-
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetOrientation";
-    }
-  };
-
-  //! Classe per calcular el cosinus de l'orientació de l'ellipse del blob
-  //! Class to calculate the cosinus of the orientation of the ellipse that fits the blob edges
-  class CBlobGetOrientationCos : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CBlobGetOrientation getOrientation;
-      return fabs(cos(getOrientation(blob)));
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetOrientationCos";
-    }
-  };
-
-
-  //! Classe per calcular el ratio entre l'eix major i menor de la el·lipse
-  //! Class to calculate the ratio between both axes of the ellipse
-  class CBlobGetAxisRatio : public COperadorBlob
-  {
-  public:
-    double operator()(const CBlob &blob) const
-    {
-      CvBox2D elipse = blob.GetEllipse();
-
-      return elipse.size.height / elipse.size.width;
-    }
-    const char *GetNom() const
-    {
-      return "CBlobGetAxisRatio";
-    }
-  };
-
-
-  //! Classe per calcular si un punt cau dins del blob
-  //! Class to calculate whether a point is inside a blob
-  class CBlobGetXYInside : public COperadorBlob
-  {
-  public:
-    //! Constructor estàndard
-    //! Standard constructor
-    CBlobGetXYInside()
-    {
-      m_p = cvPoint(0, 0);
-    }
-    //! Constructor: indiquem el punt
-    //! Constructor: sets the point
-    CBlobGetXYInside(CvPoint p)
-    {
-      m_p = p;
-    };
-    double operator()(const CBlob &blob) const;
-    const char *GetNom() const
-    {
-      return "CBlobGetXYInside";
-    }
-
-  private:
-    //! punt que considerem
-    //! point to be considered
-    CvPoint m_p;
-  };
-
-}
diff --git a/package_bgs/PAWCS.cpp b/package_bgs/PAWCS.cpp
deleted file mode 100644
index 908b3aeb83769663b1bf3f2219b78de64e4492e5..0000000000000000000000000000000000000000
--- a/package_bgs/PAWCS.cpp
+++ /dev/null
@@ -1,93 +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 "PAWCS.h"
-
-using namespace bgslibrary::algorithms;
-
-PAWCS::PAWCS() : pPAWCS(nullptr),
-fRelLBSPThreshold(BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
-nDescDistThresholdOffset(BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET),
-nMinColorDistThreshold(BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD),
-nMaxNbWords(BGSPAWCS_DEFAULT_MAX_NB_WORDS),
-nSamplesForMovingAvgs(BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS)
-{
-  std::cout << "PAWCS()" << std::endl;
-  setup("./config/PAWCS.xml");
-}
-PAWCS::~PAWCS()
-{
-  if (pPAWCS)
-    delete pPAWCS;
-  std::cout << "~PAWCS()" << std::endl;
-}
-
-void PAWCS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    pPAWCS = new BackgroundSubtractorPAWCS(
-      fRelLBSPThreshold, nDescDistThresholdOffset, nMinColorDistThreshold,
-      nMaxNbWords, nSamplesForMovingAvgs);
-
-    pPAWCS->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
-    firstTime = false;
-  }
-
-  pPAWCS->apply(img_input, img_foreground);
-  pPAWCS->getBackgroundImage(img_background);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    imshow("PAWCS FG", img_foreground);
-    imshow("PAWCS BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-}
-
-void PAWCS::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "fRelLBSPThreshold", fRelLBSPThreshold);
-  cvWriteInt(fs, "nDescDistThresholdOffset", nDescDistThresholdOffset);
-  cvWriteInt(fs, "nMinColorDistThreshold", nMinColorDistThreshold);
-  cvWriteInt(fs, "nMaxNbWords", nMaxNbWords);
-  cvWriteInt(fs, "nSamplesForMovingAvgs", nSamplesForMovingAvgs);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void PAWCS::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  fRelLBSPThreshold = cvReadRealByName(fs, nullptr, "fRelLBSPThreshold", BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD);
-  nDescDistThresholdOffset = cvReadIntByName(fs, nullptr, "nDescDistThresholdOffset", BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET);
-  nMinColorDistThreshold = cvReadIntByName(fs, nullptr, "nMinColorDistThreshold", BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD);
-  nMaxNbWords = cvReadIntByName(fs, nullptr, "nMaxNbWords", BGSPAWCS_DEFAULT_MAX_NB_WORDS);
-  nSamplesForMovingAvgs = cvReadIntByName(fs, nullptr, "nSamplesForMovingAvgs", BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/PAWCS.h b/package_bgs/PAWCS.h
deleted file mode 100644
index 173bcf6917a2c6c253ca933538609be416feee63..0000000000000000000000000000000000000000
--- a/package_bgs/PAWCS.h
+++ /dev/null
@@ -1,48 +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
-
-#include "IBGS.h"
-#include "LBSP/BackgroundSubtractorPAWCS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class PAWCS : public IBGS
-    {
-    private:
-      BackgroundSubtractorPAWCS* pPAWCS;
-
-      float fRelLBSPThreshold;
-      size_t nDescDistThresholdOffset;
-      size_t nMinColorDistThreshold;
-      size_t nMaxNbWords;
-      size_t nSamplesForMovingAvgs;
-
-    public:
-      PAWCS();
-      ~PAWCS();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/PBAS/PBAS.h b/package_bgs/PBAS/PBAS.h
deleted file mode 100644
index 9014a280bb9fc2e762813d2f02470377fc4b6c9a..0000000000000000000000000000000000000000
--- a/package_bgs/PBAS/PBAS.h
+++ /dev/null
@@ -1,207 +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/>.
-*/
-//Implementation of the PBAS from:
-//
-//M. Hofmann, P. Tiefenbacher, G. Rigoll 
-//"Background Segmentation with Feedback: The Pixel-Based Adaptive Segmenter", 
-//in proc of IEEE Workshop on Change Detection, 2012
-//
-//Note: some changes, to improve the speed and memory requirements, were achieved in comparison to the 
-//described PBAS algorithm in the paper above.
-//
-//Example usage:
-// //Somewhere during initalization:
-// #include "PBAS.h"
-// #include <opencv2/opencv.hpp>
-// PBAS pbas;
-//
-// //you might want to change some parameters of the PBAS here...
-// ....
-//
-// //repeat for each frame
-// //make gaussian blur for reducing image noise
-//cv::Mat bluredImage;
-//cv::Mat pbastResult;
-//cv::GaussianBlur(singleFrame, bluredImage, cv::Size(5,5), 1.5);
-// 
-// //process image and receive segmentation in pbasResult
-//pbas.process(&bluredImage, &pbasResult);
-//
-// //make medianBlur on the result to reduce "salt and pepper noise"
-// //of the per pixel wise segmentation
-//cv::medianBlur(pbasResult, pbasResult, 5);
-//
-//
-//
-//Author: P.Tiefenbacher, https://sites.google.com/site/pbassegmenter/
-//Technische Universität München, Germany
-//Date: 22-May-2012, Version:0.1
-///////////
-#pragma once
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-//#include <highgui.h>
-
-class PBAS
-{
-public:
-  PBAS(void);
-  ~PBAS(void);
-  bool process(cv::Mat* input, cv::Mat* output);
-
-  void setN(int);
-  void setRaute_min(int);
-  void setR_lower(double);
-  void setR_incdec(double);
-  void setR_scale(double);
-  void setT_init(double);
-  void setT_lower(double);
-  void setT_upper(double);
-  void setT_dec(double);
-  void setT_inc(double);
-  void setAlpha(double);
-  void setBeta(double);
-
-  bool isMovement();
-
-
-private:
-  void calculateFeatures(std::vector<cv::Mat>* feature, cv::Mat* inputImage);
-  void checkValid(int *x, int *y);
-  void decisionThresholdRegulator(float* pt, float* meanDistArr);
-  void learningRateRegulator(float* pt, float* meanDist, uchar* isFore);
-  void init(cv::Mat*);
-  void newInitialization();
-
-  cv::Mat meanMinDist;
-  float* meanMinDist_Pt;
-
-
-
-  int width, height;
-  int chans;
-
-  //balance of feature pixel value to conture value
-  double alpha, beta;
-  //##################################################################################
-
-  double formerMeanNorm;
-
-  //define value of foreground/background pixels
-  int foregroundValue, backgroundValue;
-
-  //##################################################################################
-  //random number parameters
-
-  //random number generator
-  cv::RNG randomGenerator;
-
-  //length of random array initialization
-  long countOfRandomNumb;
-
-  //pre - initialize the randomNumbers for better performance
-  std::vector<int> randomN, randomMinDist, randomX, randomY, randomT, randomTN;
-
-  //###################################################################################
-
-  //check if something is moving
-  bool isMove;
-
-  //for init, count number of runs
-  int runs;
-
-
-  cv::Mat* resultMap;
-  std::vector<cv::Mat> currentFeatures;
-
-  std::vector<float*> currentFeaturesM_Pt;
-  std::vector<uchar*> currentFeaturesC_Pt;
-  uchar* resultMap_Pt;
-
-  std::vector<std::vector<float*>>B_Mag_Pts;
-  std::vector<std::vector<uchar*>>B_Col_Pts;
-
-  double sumMagnitude;
-  double formerMeanMag;
-  float formerDistanceBack;
-
-  //####################################################################################
-  //N - Number: Defining the size of the background-history-model
-  // number of samples per pixel
-  //size of background history B(x_i)
-  int N;
-  // background model
-  std::vector<std::vector<cv::Mat>> backgroundModel;
-  //####################################################################################
-  //####################################################################################
-  //R-Threshhold - Variables
-  //minimal Threshold for foreground and initial value of R(x_i)
-  // radius of the sphere -> lower border boundary
-  double R_lower;
-
-  //factor which defines new threshold of R(x_i) together with meanMinDist(x_i)
-  // scale for the sphere threshhold to define pixel-based Thresholds
-  double R_scale;
-
-  //decreasing / increasing factor of R(x_i)
-  // increasing/decreasing factor for the r-Threshold based on the result of rTreshScale * meanMinDistBackground
-  double R_incdec;
-
-  cv::Mat actualR;
-  float* actualR_Pt; //new pixel-based r-threshhold -> pointer to arrays
-  //#####################################################################################
-  //####################################################################################
-  //counter for minimal distance to background
-  // Defining the number of background-model-images, which have a lowerDIstance to the current Image than defined by the R-Thresholds, that are necessary
-  // to decide that this pixel is background
-  int Raute_min;
-  //#####################################################################################
-  //####################################################################################
-  //initial value of inverse update factor T(x_i)
-  // Initialize the background-model update rate
-  double T_init;
-
-  //increasing Factor of the update rate 1/T(x_i)
-  // scale that defines the increasing of the update rate of the background model, if the current pixel is background
-  //--> more frequently updates if pixel is background because, there shouln't be any change
-  double T_inc;
-
-  //upper boundary of T(x_i)
-  // defining an upper value, that nrSubsampling can achieve, thus it doesn't reach to an infinite value, where actually no update is possible
-  // at all
-  double T_upper;
-
-  //lower boundary of T(x_i)
-  // defining a minimum value for nrSubsampling --> base value 2.0
-  double T_lower;
-
-  //decreasing factor of the update rate 1/T(x_i)
-  // opposite scale to increasingRateScale, for decreasing the update rate of the background model, if the current pixel is foreground
-  //--> Thesis: Our Foreground is a real moving object -> thus the background-model is good, so don't update it
-  double T_dec;
-
-  //holds update rate of current pixel
-  cv::Mat actualT;
-  float* actualT_Pt;
-
-  //#####################################################################################
-
-
-  cv::Mat sobelX, sobelY;
-};
-
diff --git a/package_bgs/PixelBasedAdaptiveSegmenter.cpp b/package_bgs/PixelBasedAdaptiveSegmenter.cpp
deleted file mode 100644
index 8a3de97dd3413df895b05148862d484d8189982c..0000000000000000000000000000000000000000
--- a/package_bgs/PixelBasedAdaptiveSegmenter.cpp
+++ /dev/null
@@ -1,126 +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 "PixelBasedAdaptiveSegmenter.h"
-
-using namespace bgslibrary::algorithms;
-
-PixelBasedAdaptiveSegmenter::PixelBasedAdaptiveSegmenter() :
-  enableInputBlur(true), enableOutputBlur(true),
-  alpha(7.0), beta(1.0), N(20), Raute_min(2), R_incdec(0.05), R_lower(18),
-  R_scale(5), T_dec(0.05), T_inc(1), T_init(18), T_lower(2), T_upper(200)
-{
-  std::cout << "PixelBasedAdaptiveSegmenter()" << std::endl;
-  setup("./config/PixelBasedAdaptiveSegmenter.xml");
-}
-
-PixelBasedAdaptiveSegmenter::~PixelBasedAdaptiveSegmenter()
-{
-  std::cout << "~PixelBasedAdaptiveSegmenter()" << std::endl;
-}
-
-void PixelBasedAdaptiveSegmenter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    pbas.setAlpha(alpha);
-    pbas.setBeta(beta);
-    pbas.setN(N);
-    pbas.setRaute_min(Raute_min);
-    pbas.setR_incdec(R_incdec);
-    pbas.setR_lower(R_lower);
-    pbas.setR_scale(R_scale);
-    pbas.setT_dec(T_dec);
-    pbas.setT_inc(T_inc);
-    pbas.setT_init(T_init);
-    pbas.setT_lower(T_lower);
-    pbas.setT_upper(T_upper);
-  }
-
-  cv::Mat img_input_new;
-  if (enableInputBlur)
-    cv::GaussianBlur(img_input, img_input_new, cv::Size(5, 5), 1.5);
-  else
-    img_input.copyTo(img_input_new);
-
-  pbas.process(&img_input_new, &img_foreground);
-  img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-  if (enableOutputBlur)
-    cv::medianBlur(img_foreground, img_foreground, 5);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("PBAS", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void PixelBasedAdaptiveSegmenter::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableInputBlur", enableInputBlur);
-  cvWriteInt(fs, "enableOutputBlur", enableOutputBlur);
-
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "beta", beta);
-  cvWriteInt(fs, "N", N);
-  cvWriteInt(fs, "Raute_min", Raute_min);
-  cvWriteReal(fs, "R_incdec", R_incdec);
-  cvWriteInt(fs, "R_lower", R_lower);
-  cvWriteInt(fs, "R_scale", R_scale);
-  cvWriteReal(fs, "T_dec", T_dec);
-  cvWriteInt(fs, "T_inc", T_inc);
-  cvWriteInt(fs, "T_init", T_init);
-  cvWriteInt(fs, "T_lower", T_lower);
-  cvWriteInt(fs, "T_upper", T_upper);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void PixelBasedAdaptiveSegmenter::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableInputBlur = cvReadIntByName(fs, nullptr, "enableInputBlur", true);
-  enableOutputBlur = cvReadIntByName(fs, nullptr, "enableOutputBlur", true);
-
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 7.0);
-  beta = cvReadRealByName(fs, nullptr, "beta", 1.0);
-  N = cvReadIntByName(fs, nullptr, "N", 20);
-  Raute_min = cvReadIntByName(fs, nullptr, "Raute_min", 2);
-  R_incdec = cvReadRealByName(fs, nullptr, "R_incdec", 0.05);
-  R_lower = cvReadIntByName(fs, nullptr, "R_lower", 18);
-  R_scale = cvReadIntByName(fs, nullptr, "R_scale", 5);
-  T_dec = cvReadRealByName(fs, nullptr, "T_dec", 0.05);
-  T_inc = cvReadIntByName(fs, nullptr, "T_inc", 1);
-  T_init = cvReadIntByName(fs, nullptr, "T_init", 18);
-  T_lower = cvReadIntByName(fs, nullptr, "T_lower", 2);
-  T_upper = cvReadIntByName(fs, nullptr, "T_upper", 200);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/PixelBasedAdaptiveSegmenter.h b/package_bgs/PixelBasedAdaptiveSegmenter.h
deleted file mode 100644
index 36dd0ad03a206ff7858dafe0279e3ed280a0f6d4..0000000000000000000000000000000000000000
--- a/package_bgs/PixelBasedAdaptiveSegmenter.h
+++ /dev/null
@@ -1,58 +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
-
-#include "IBGS.h"
-#include "PBAS/PBAS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class PixelBasedAdaptiveSegmenter : public IBGS
-    {
-    private:
-      PBAS pbas;
-
-      bool enableInputBlur;
-      bool enableOutputBlur;
-
-      float alpha;
-      float beta;
-      int N;
-      int Raute_min;
-      float R_incdec;
-      int R_lower;
-      int R_scale;
-      float T_dec;
-      int T_inc;
-      int T_init;
-      int T_lower;
-      int T_upper;
-
-    public:
-      PixelBasedAdaptiveSegmenter();
-      ~PixelBasedAdaptiveSegmenter();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/SigmaDelta.cpp b/package_bgs/SigmaDelta.cpp
deleted file mode 100644
index d3052265052e1429745f1905fc2b354bf6ffd834..0000000000000000000000000000000000000000
--- a/package_bgs/SigmaDelta.cpp
+++ /dev/null
@@ -1,101 +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 "SigmaDelta.h"
-
-using namespace bgslibrary::algorithms;
-
-SigmaDelta::SigmaDelta() :
-  ampFactor(1), minVar(15), maxVar(255), algorithm(sdLaMa091New())
-{
-  applyParams();
-  std::cout << "SigmaDelta()" << std::endl;
-  setup("./config/SigmaDelta.xml");
-}
-
-SigmaDelta::~SigmaDelta()
-{
-  sdLaMa091Free(algorithm);
-  std::cout << "~SigmaDelta()" << std::endl;
-}
-
-void SigmaDelta::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    sdLaMa091AllocInit_8u_C3R(algorithm, img_input.data, img_input.cols, img_input.rows, img_input.step);
-    img_foreground = cv::Mat(img_input.size(), CV_8UC1);
-    img_background = cv::Mat(img_input.size(), CV_8UC3);
-    firstTime = false;
-  }
-  else
-  {
-    cv::Mat img_output_tmp(img_input.rows, img_input.cols, CV_8UC3);
-    sdLaMa091Update_8u_C3R(algorithm, img_input.data, img_output_tmp.data);
-
-    unsigned char* tmpBuffer = (unsigned char*)img_output_tmp.data;
-    unsigned char* outBuffer = (unsigned char*)img_foreground.data;
-
-    for (size_t i = 0; i < img_foreground.total(); ++i) {
-      *outBuffer = *tmpBuffer;
-      ++outBuffer;
-      tmpBuffer += img_output_tmp.channels();
-    }
-  }
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Sigma-Delta", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-}
-
-void SigmaDelta::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "ampFactor", ampFactor);
-  cvWriteInt(fs, "minVar", minVar);
-  cvWriteInt(fs, "maxVar", maxVar);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void SigmaDelta::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  ampFactor = cvReadIntByName(fs, nullptr, "ampFactor", 1);
-  minVar = cvReadIntByName(fs, nullptr, "minVar", 15);
-  maxVar = cvReadIntByName(fs, nullptr, "maxVar", 255);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  applyParams();
-
-  cvReleaseFileStorage(&fs);
-}
-
-void SigmaDelta::applyParams()
-{
-  sdLaMa091SetAmplificationFactor(algorithm, ampFactor);
-  sdLaMa091SetMinimalVariance(algorithm, minVar);
-  sdLaMa091SetMaximalVariance(algorithm, maxVar);
-}
diff --git a/package_bgs/SigmaDelta.h b/package_bgs/SigmaDelta.h
deleted file mode 100644
index c7b1a2c660323a11672fb399a092b81139392d2a..0000000000000000000000000000000000000000
--- a/package_bgs/SigmaDelta.h
+++ /dev/null
@@ -1,49 +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
-
-#include "IBGS.h"
-
-//extern "C" {
-#include "SigmaDelta/sdLaMa091.h"
-//}
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class SigmaDelta : public IBGS
-    {
-    private:
-      unsigned int ampFactor;
-      unsigned int minVar;
-      unsigned int maxVar;
-      sdLaMa091_t* algorithm;
-
-    public:
-      SigmaDelta();
-      ~SigmaDelta();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-      void applyParams();
-    };
-  }
-}
diff --git a/package_bgs/SigmaDelta/sdLaMa091.cpp b/package_bgs/SigmaDelta/sdLaMa091.cpp
deleted file mode 100644
index 286556be49ff77e7d7f5b406bc40e675c4dfafa6..0000000000000000000000000000000000000000
--- a/package_bgs/SigmaDelta/sdLaMa091.cpp
+++ /dev/null
@@ -1,658 +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 "sdLaMa091.h"
-
-#define DEFAULT_N 1
-#define DEFAULT_VMIN 2
-#define DEFAULT_VMAX 255
-
-#define LIB "sdLaMa091 - "
-#define RED 0
-#define GREEN 1
-#define BLUE 2
-#define CHANNELS 3
-
-typedef enum {
-  UNKNOWN,
-  C1R,
-  C3R
-} image_t;
-
-struct sdLaMa091 {
-  image_t  imageType;
-
-  uint32_t width;
-  uint32_t rgbWidth;
-  uint32_t height;
-  uint32_t stride;
-  uint32_t numBytes;
-  uint32_t unusedBytes;
-  uint32_t rgbUnusedBytes;
-
-  uint32_t N;
-  uint32_t Vmin;
-  uint32_t Vmax;
-
-  uint8_t* Mt;
-  uint8_t* Ot;
-  uint8_t* Vt;
-};
-
-#if defined(DEFENSIVE_ALLOC) || defined(DEFENSIVE_POINTER) || \
-  defined(DEFENSIVE_PARAM)
-static inline void outputError(char* error);
-#endif
-
-static inline uint8_t absVal(int8_t num);
-static inline uint8_t min(uint8_t a, uint8_t b);
-static inline uint8_t max(uint8_t a, uint8_t b);
-
-#if defined(DEFENSIVE_ALLOC) || defined(DEFENSIVE_POINTER) || \
-  defined(DEFENSIVE_PARAM)
-
-static inline void outputError(char* error) {
-  fprintf(stderr, "%s%s\n", LIB, error);
-}
-#endif
-
-
-static inline uint8_t absVal(int8_t num) {
-  return (num < 0) ? (uint8_t)-num : (uint8_t)num;
-}
-
-static inline uint8_t min(uint8_t a, uint8_t b) {
-  return (a < b) ? a : b;
-}
-
-static inline uint8_t max(uint8_t a, uint8_t b) {
-  return (a > b) ? a : b;
-}
-
-sdLaMa091_t* sdLaMa091New(void) {
-  sdLaMa091_t* sdLaMa091 = (sdLaMa091_t*)malloc(sizeof(*sdLaMa091));
-
-#ifdef DEFENSIVE_ALLOC
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot allocate sdLaMa091 structure");
-    return NULL;
-  }
-#endif
-
-  sdLaMa091->imageType = UNKNOWN;
-
-  sdLaMa091->width = 0;
-  sdLaMa091->rgbWidth = 0;
-  sdLaMa091->height = 0;
-  sdLaMa091->stride = 0;
-  sdLaMa091->numBytes = 0;
-  sdLaMa091->unusedBytes = 0;
-  sdLaMa091->rgbUnusedBytes = 0;
-
-  sdLaMa091->N = DEFAULT_N;
-  sdLaMa091->Vmin = DEFAULT_VMIN;
-  sdLaMa091->Vmax = DEFAULT_VMAX;
-
-  sdLaMa091->Mt = NULL;
-  sdLaMa091->Ot = NULL;
-  sdLaMa091->Vt = NULL;
-
-  return sdLaMa091;
-}
-
-int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  const uint32_t width,
-  const uint32_t height,
-  const uint32_t stride) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot initialize a NULL structure");
-    return EXIT_FAILURE;
-  }
-
-  if (image_data == NULL) {
-    outputError("Cannot allocate ressources for a NULL image");
-    return EXIT_FAILURE;
-  }
-#endif
-
-#ifdef DEFENSIVE_PARAM
-  if (width == 0 || height == 0 || stride == 0) {
-    outputError("Cannot allocate ressources for zero values");
-    return EXIT_FAILURE;
-  }
-
-  if (stride < width) {
-    outputError("Cannot allocate ressources for a stride lower than the width");
-    return EXIT_FAILURE;
-  }
-#endif
-
-  sdLaMa091->imageType = C1R;
-
-  sdLaMa091->width = width;
-  sdLaMa091->height = height;
-  sdLaMa091->stride = stride;
-  sdLaMa091->numBytes = stride * height;
-  sdLaMa091->unusedBytes = stride - sdLaMa091->width;
-
-  sdLaMa091->Mt = (uint8_t*)malloc(sdLaMa091->numBytes);
-#ifdef DEFENSIVE_ALLOC
-  if (sdLaMa091->Mt == NULL) {
-    outputError("Cannot allocate sdLaMa091->Mt table");
-    return EXIT_FAILURE;
-  }
-#endif 
-  memcpy(sdLaMa091->Mt, image_data, sdLaMa091->numBytes);
-
-  sdLaMa091->Ot = (uint8_t*)malloc(sdLaMa091->numBytes);
-#ifdef DEFENSIVE_ALLOC
-  if (sdLaMa091->Ot == NULL) {
-    outputError("Cannot allocate sdLaMa091->Ot table");
-    return EXIT_FAILURE;
-  }
-#endif 
-  uint8_t* workOt = sdLaMa091->Ot;
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workOt)
-      *workOt = 0;
-
-
-    if (sdLaMa091->unusedBytes > 0)
-      workOt += sdLaMa091->unusedBytes;
-  }
-
-  sdLaMa091->Vt = (uint8_t*)malloc(sdLaMa091->numBytes);
-#ifdef DEFENSIVE_ALLOC
-  if (sdLaMa091->Vt == NULL) {
-    outputError("Cannot allocate sdLaMa091->Vt table");
-    return EXIT_FAILURE;
-  }
-#endif
-  uint8_t* workVt = sdLaMa091->Vt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workVt)
-      *workVt = sdLaMa091->Vmin;
-
-
-    if (sdLaMa091->unusedBytes > 0)
-      workVt += sdLaMa091->unusedBytes;
-  }
-
-  return EXIT_SUCCESS;
-}
-
-int32_t sdLaMa091AllocInit_8u_C3R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  const uint32_t width,
-  const uint32_t height,
-  const uint32_t stride) {
-  int32_t success = sdLaMa091AllocInit_8u_C1R(sdLaMa091, image_data, width,
-    height, stride);
-
-  if (success == EXIT_SUCCESS) {
-    sdLaMa091->imageType = C3R;
-    sdLaMa091->rgbWidth = sdLaMa091->width * CHANNELS;
-    sdLaMa091->rgbUnusedBytes = stride - sdLaMa091->rgbWidth;
-    sdLaMa091->width = 0;
-    sdLaMa091->unusedBytes = 0;
-  }
-
-  return success;
-}
-
-int32_t sdLaMa091SetAmplificationFactor(sdLaMa091_t* sdLaMa091,
-  const uint32_t amplificationFactor) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot set a parameter of a NULL structure");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-#ifdef DEFENSIVE_PARAM
-  if (amplificationFactor == 0) {
-    outputError("Cannot set a parameter with a zero value");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-  sdLaMa091->N = amplificationFactor;
-
-  return EXIT_SUCCESS;
-}
-
-uint32_t sdLaMa091GetAmplificationFactor(const sdLaMa091_t* sdLaMa091) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot get a parameter of a NULL structure");
-    errno = ERROR_OCCURED;
-
-    return EXIT_FAILURE;
-  }
-#endif 
-
-  return sdLaMa091->N;
-}
-
-int32_t sdLaMa091SetMaximalVariance(sdLaMa091_t* sdLaMa091,
-  const uint32_t maximalVariance) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot set a parameter of a NULL structure");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-#ifdef DEFENSIVE_PARAM
-  if (maximalVariance == 0) {
-    outputError("Cannot set a parameter with a zero value");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-  sdLaMa091->Vmax = maximalVariance;
-
-  return EXIT_SUCCESS;
-}
-
-uint32_t sdLaMa091GetMaximalVariance(const sdLaMa091_t* sdLaMa091) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot get a parameter of a NULL structure");
-    errno = ERROR_OCCURED;
-
-    return EXIT_FAILURE;
-  }
-#endif
-
-  return sdLaMa091->Vmax;
-}
-
-int32_t sdLaMa091SetMinimalVariance(sdLaMa091_t* sdLaMa091,
-  const uint32_t minimalVariance) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot set a parameter of a NULL structure");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-  sdLaMa091->Vmin = minimalVariance;
-
-  return EXIT_SUCCESS;
-}
-
-uint32_t sdLaMa091GetMinimalVariance(const sdLaMa091_t* sdLaMa091) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot get a parameter of a NULL structure");
-    errno = ERROR_OCCURED;
-
-    return EXIT_FAILURE;
-  }
-#endif 
-
-  return sdLaMa091->Vmin;
-}
-
-
-int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  uint8_t* segmentation_map) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot update a NULL structure");
-    return EXIT_FAILURE;
-  }
-
-  if (image_data == NULL) {
-    outputError("Cannot update a structure with a NULL image");
-    return EXIT_FAILURE;
-  }
-
-  if (segmentation_map == NULL) {
-    outputError("Cannot update a structure with a NULL segmentation map");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Mt == NULL) {
-    outputError("Cannot update a structure with a NULL Mt table");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Ot == NULL) {
-    outputError("Cannot update a structure with a NULL Ot table");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Vt == NULL) {
-    outputError("Cannot update a structure with a NULL Vt table");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-#ifdef DEFENSIVE_PARAM
-  if (sdLaMa091->imageType != C1R) {
-    outputError("Cannot update a structure which is not C1R");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->width == 0 || sdLaMa091->height == 0 ||
-    sdLaMa091->stride == 0) {
-    outputError("Cannot update a structure with zero values");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->stride < sdLaMa091->width) {
-    outputError("Cannot update a structure with a stride lower than the width");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Vmax < sdLaMa091->Vmin) {
-    outputError("Cannot update a structure with Vmax inferior to Vmin");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-
-  const uint8_t* workImage = image_data;
-  uint8_t* workMt = sdLaMa091->Mt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workImage, ++workMt) {
-      if (*workMt < *workImage)
-        ++(*workMt);
-      else if (*workMt > *workImage)
-        --(*workMt);
-    }
-
-
-    if (sdLaMa091->unusedBytes > 0) {
-      workImage += sdLaMa091->unusedBytes;
-      workMt += sdLaMa091->unusedBytes;
-    }
-  }
-
-  workImage = image_data;
-  workMt = sdLaMa091->Mt;
-  uint8_t* workOt = sdLaMa091->Ot;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workImage, ++workMt,
-      ++workOt)
-      *workOt = absVal(*workMt - *workImage);
-
-
-    if (sdLaMa091->unusedBytes > 0) {
-      workImage += sdLaMa091->unusedBytes;
-      workMt += sdLaMa091->unusedBytes;
-      workOt += sdLaMa091->unusedBytes;
-    }
-  }
-
-
-  workOt = sdLaMa091->Ot;
-  uint8_t* workVt = sdLaMa091->Vt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workOt, ++workVt) {
-      uint32_t ampOt = sdLaMa091->N * *workOt;
-
-      if (*workVt < ampOt)
-        ++(*workVt);
-      else if (*workVt > ampOt)
-        --(*workVt);
-
-      *workVt = max(min(*workVt, sdLaMa091->Vmax), sdLaMa091->Vmin);
-    }
-
-
-    if (sdLaMa091->unusedBytes > 0) {
-      workOt += sdLaMa091->unusedBytes;
-      workVt += sdLaMa091->unusedBytes;
-    }
-  }
-
-
-  workOt = sdLaMa091->Ot;
-  workVt = sdLaMa091->Vt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++segmentation_map,
-      ++workOt, ++workVt) {
-
-      if (*workOt < *workVt)
-        *segmentation_map = BACKGROUND;
-      else
-        *segmentation_map = FOREGROUND;
-    }
-
-
-    if (sdLaMa091->unusedBytes > 0) {
-      segmentation_map += sdLaMa091->unusedBytes;
-      workOt += sdLaMa091->unusedBytes;
-      workVt += sdLaMa091->unusedBytes;
-    }
-  }
-
-  return EXIT_SUCCESS;
-}
-
-int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  uint8_t* segmentation_map) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot update a NULL structure");
-    return EXIT_FAILURE;
-  }
-
-  if (image_data == NULL) {
-    outputError("Cannot update a structure with a NULL image");
-    return EXIT_FAILURE;
-  }
-
-  if (segmentation_map == NULL) {
-    outputError("Cannot update a structure with a NULL segmentation map");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Mt == NULL) {
-    outputError("Cannot update a structure with a NULL Mt table");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Ot == NULL) {
-    outputError("Cannot update a structure with a NULL Ot table");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Vt == NULL) {
-    outputError("Cannot update a structure with a NULL Vt table");
-    return EXIT_FAILURE;
-  }
-#endif
-
-#ifdef DEFENSIVE_PARAM
-  if (sdLaMa091->imageType != C3R) {
-    outputError("Cannot update a structure which is not C3R");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->rgbWidth == 0 || sdLaMa091->height == 0 ||
-    sdLaMa091->stride == 0) {
-    outputError("Cannot update a structure with zero values");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->stride < sdLaMa091->rgbWidth) {
-    outputError("Cannot update a structure with a stride lower than the width");
-    return EXIT_FAILURE;
-  }
-
-  if (sdLaMa091->Vmax < sdLaMa091->Vmin) {
-    outputError("Cannot update a structure with Vmax inferior to Vmin");
-    return EXIT_FAILURE;
-  }
-#endif 
-
-
-  const uint8_t* workImage = image_data;
-  uint8_t* workMt = sdLaMa091->Mt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workImage, ++workMt) {
-      if (*workMt < *workImage)
-        ++(*workMt);
-      else if (*workMt > *workImage)
-        --(*workMt);
-    }
-
-
-    if (sdLaMa091->rgbUnusedBytes > 0) {
-      workImage += sdLaMa091->rgbUnusedBytes;
-      workMt += sdLaMa091->rgbUnusedBytes;
-    }
-  }
-
-
-  workImage = image_data;
-  workMt = sdLaMa091->Mt;
-  uint8_t* workOt = sdLaMa091->Ot;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workImage, ++workMt,
-      ++workOt)
-      *workOt = absVal(*workMt - *workImage);
-
-
-    if (sdLaMa091->rgbUnusedBytes > 0) {
-      workImage += sdLaMa091->rgbUnusedBytes;
-      workMt += sdLaMa091->rgbUnusedBytes;
-      workOt += sdLaMa091->rgbUnusedBytes;
-    }
-  }
-
-  workOt = sdLaMa091->Ot;
-  uint8_t* workVt = sdLaMa091->Vt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workOt, ++workVt) {
-      uint32_t ampOt = sdLaMa091->N * *workOt;
-
-      if (*workVt < ampOt)
-        ++(*workVt);
-      else if (*workVt > ampOt)
-        --(*workVt);
-
-      *workVt = max(min(*workVt, sdLaMa091->Vmax), sdLaMa091->Vmin);
-    }
-
-
-    if (sdLaMa091->rgbUnusedBytes > 0) {
-      workOt += sdLaMa091->rgbUnusedBytes;
-      workVt += sdLaMa091->rgbUnusedBytes;
-    }
-  }
-
-  workOt = sdLaMa091->Ot;
-  workVt = sdLaMa091->Vt;
-
-
-  for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
-
-    uint32_t numColor = 0;
-
-    bool isForeground = false;
-
-
-    for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workOt, ++workVt) {
-      if (*workOt >= *workVt)
-        isForeground = true;
-
-
-      if (numColor == BLUE) {
-        if (isForeground) {
-          *segmentation_map = FOREGROUND;
-          *(++segmentation_map) = FOREGROUND;
-          *(++segmentation_map) = FOREGROUND;
-          ++segmentation_map;
-        }
-        else {
-          *segmentation_map = BACKGROUND;
-          *(++segmentation_map) = BACKGROUND;
-          *(++segmentation_map) = BACKGROUND;
-          ++segmentation_map;
-        }
-
-        isForeground = false;
-      }
-
-      numColor = (numColor + 1) % CHANNELS;
-    }
-
-
-    if (sdLaMa091->rgbUnusedBytes > 0) {
-      segmentation_map += sdLaMa091->rgbUnusedBytes;
-      workOt += sdLaMa091->rgbUnusedBytes;
-      workVt += sdLaMa091->rgbUnusedBytes;
-    }
-  }
-
-  return EXIT_SUCCESS;
-}
-
-int32_t sdLaMa091Free(sdLaMa091_t* sdLaMa091) {
-#ifdef DEFENSIVE_POINTER
-  if (sdLaMa091 == NULL) {
-    outputError("Cannot free a NULL strucutre");
-    return EXIT_FAILURE;
-  }
-#endif
-
-  if (sdLaMa091->Mt != NULL)
-    free(sdLaMa091->Mt);
-  if (sdLaMa091->Ot != NULL)
-    free(sdLaMa091->Ot);
-  if (sdLaMa091->Vt != NULL)
-    free(sdLaMa091->Vt);
-
-  free(sdLaMa091);
-
-  return EXIT_SUCCESS;
-}
diff --git a/package_bgs/SigmaDelta/sdLaMa091.h b/package_bgs/SigmaDelta/sdLaMa091.h
deleted file mode 100644
index cf9e777d913a35d9bd5fa79e7baf62f4cdfb9f78..0000000000000000000000000000000000000000
--- a/package_bgs/SigmaDelta/sdLaMa091.h
+++ /dev/null
@@ -1,68 +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
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define BACKGROUND 0
-#define FOREGROUND 255
-#define ERROR_OCCURED 1
-
-typedef struct sdLaMa091 sdLaMa091_t;
-
-sdLaMa091_t* sdLaMa091New(void);
-
-int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  const uint32_t width,
-  const uint32_t height,
-  const uint32_t stride);
-
-int32_t sdLaMa091AllocInit_8u_C3R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  const uint32_t width,
-  const uint32_t height,
-  const uint32_t stride);
-
-int32_t sdLaMa091SetAmplificationFactor(sdLaMa091_t* sdLaMa091,
-  const uint32_t amplificationFactor);
-
-uint32_t sdLaMa091GetAmplificationFactor(const sdLaMa091_t* sdLaMa091);
-
-int32_t sdLaMa091SetMaximalVariance(sdLaMa091_t* sdLaMa091,
-  const uint32_t maximalVariance);
-
-uint32_t sdLaMa091GetMaximalVariance(const sdLaMa091_t* sdLaMa091);
-
-int32_t sdLaMa091SetMinimalVariance(sdLaMa091_t* sdLaMa091,
-  const uint32_t minimalVariance);
-
-uint32_t sdLaMa091GetMinimalVariance(const sdLaMa091_t* sdLaMa091);
-
-int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  uint8_t* segmentation_map);
-
-int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091,
-  const uint8_t* image_data,
-  uint8_t* segmentation_map);
-
-int32_t sdLaMa091Free(sdLaMa091_t* sdLaMa091);
diff --git a/package_bgs/StaticFrameDifference.cpp b/package_bgs/StaticFrameDifference.cpp
deleted file mode 100644
index 2faa40c71f103b5b233ca223f1fd351cc2125f3e..0000000000000000000000000000000000000000
--- a/package_bgs/StaticFrameDifference.cpp
+++ /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/>.
-*/
-#include "StaticFrameDifference.h"
-
-using namespace bgslibrary::algorithms;
-
-StaticFrameDifference::StaticFrameDifference() :
-  enableThreshold(true), threshold(15)
-{
-  std::cout << "StaticFrameDifference()" << std::endl;
-  setup("./config/StaticFrameDifference.xml");
-}
-
-StaticFrameDifference::~StaticFrameDifference()
-{
-  std::cout << "~StaticFrameDifference()" << std::endl;
-}
-
-void StaticFrameDifference::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_background.empty())
-    img_input.copyTo(img_background);
-
-  cv::absdiff(img_input, img_background, img_foreground);
-
-  if (img_foreground.channels() == 3)
-    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
-
-  if (enableThreshold)
-    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("Static Frame Difference", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  firstTime = false;
-}
-
-void StaticFrameDifference::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void StaticFrameDifference::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/StaticFrameDifference.h b/package_bgs/StaticFrameDifference.h
deleted file mode 100644
index 8c8474c6ed065178f1275e23baa826caaab5fb36..0000000000000000000000000000000000000000
--- a/package_bgs/StaticFrameDifference.h
+++ /dev/null
@@ -1,42 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class StaticFrameDifference : public IBGS
-    {
-    private:
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      StaticFrameDifference();
-      ~StaticFrameDifference();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/SuBSENSE.cpp b/package_bgs/SuBSENSE.cpp
deleted file mode 100644
index c8a0e5d11b8a952d72c721ae55d8793b642a2294..0000000000000000000000000000000000000000
--- a/package_bgs/SuBSENSE.cpp
+++ /dev/null
@@ -1,96 +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 "SuBSENSE.h"
-
-using namespace bgslibrary::algorithms;
-
-SuBSENSE::SuBSENSE() :
-  pSubsense(0),
-  fRelLBSPThreshold(BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
-  nDescDistThresholdOffset(BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET),
-  nMinColorDistThreshold(BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD),
-  nBGSamples(BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES),
-  nRequiredBGSamples(BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES),
-  nSamplesForMovingAvgs(BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS)
-{
-  std::cout << "SuBSENSE()" << std::endl;
-}
-
-SuBSENSE::~SuBSENSE() {
-  if (pSubsense)
-    delete pSubsense;
-  std::cout << "~SuBSENSE()" << std::endl;
-}
-
-void SuBSENSE::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (firstTime)
-  {
-    pSubsense = new BackgroundSubtractorSuBSENSE(
-      fRelLBSPThreshold, nDescDistThresholdOffset, nMinColorDistThreshold,
-      nBGSamples, nRequiredBGSamples, nSamplesForMovingAvgs);
-
-    pSubsense->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
-    firstTime = false;
-  }
-
-  pSubsense->apply(img_input, img_foreground);
-  pSubsense->getBackgroundImage(img_background);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    imshow("SuBSENSE FG", img_foreground);
-    imshow("SuBSENSE BG", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-}
-
-void SuBSENSE::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "fRelLBSPThreshold", fRelLBSPThreshold);
-  cvWriteInt(fs, "nDescDistThresholdOffset", nDescDistThresholdOffset);
-  cvWriteInt(fs, "nMinColorDistThreshold", nMinColorDistThreshold);
-  cvWriteInt(fs, "nBGSamples", nBGSamples);
-  cvWriteInt(fs, "nRequiredBGSamples", nRequiredBGSamples);
-  cvWriteInt(fs, "nSamplesForMovingAvgs", nSamplesForMovingAvgs);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void SuBSENSE::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  fRelLBSPThreshold = cvReadRealByName(fs, nullptr, "fRelLBSPThreshold", BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD);
-  nDescDistThresholdOffset = cvReadIntByName(fs, nullptr, "nDescDistThresholdOffset", BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET);
-  nMinColorDistThreshold = cvReadIntByName(fs, nullptr, "nMinColorDistThreshold", BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD);
-  nBGSamples = cvReadIntByName(fs, nullptr, "nBGSamples", BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES);
-  nRequiredBGSamples = cvReadIntByName(fs, nullptr, "nRequiredBGSamples", BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES);
-  nSamplesForMovingAvgs = cvReadIntByName(fs, nullptr, "nSamplesForMovingAvgs", BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/SuBSENSE.h b/package_bgs/SuBSENSE.h
deleted file mode 100644
index 9ac9aa6f2fcbe04592b1abf5682245885238d07a..0000000000000000000000000000000000000000
--- a/package_bgs/SuBSENSE.h
+++ /dev/null
@@ -1,49 +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
-
-#include "IBGS.h"
-#include "LBSP/BackgroundSubtractorSuBSENSE.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class SuBSENSE : public IBGS
-    {
-    private:
-      BackgroundSubtractorSuBSENSE* pSubsense;
-
-      float fRelLBSPThreshold;
-      size_t nDescDistThresholdOffset;
-      size_t nMinColorDistThreshold;
-      size_t nBGSamples;
-      size_t nRequiredBGSamples;
-      size_t nSamplesForMovingAvgs;
-
-    public:
-      SuBSENSE();
-      ~SuBSENSE();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/T2F/FuzzyUtils.h b/package_bgs/T2F/FuzzyUtils.h
deleted file mode 100644
index 9a53a83f23d06742be9c5d33c7ff4fc5b776bce8..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/FuzzyUtils.h
+++ /dev/null
@@ -1,43 +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
-
-#include "../../package_analysis/PixelUtils.h"
-
-class FuzzyUtils
-{
-public:
-  FuzzyUtils(void);
-  ~FuzzyUtils(void);
-
-  void LBP(IplImage* InputImage, IplImage* LBP);
-  void getBinValue(float* neighberGrayPixel, float* BinaryValue, int m, int n);
-
-  void SimilarityDegreesImage(IplImage* CurrentImage, IplImage* BGImage, IplImage* DeltaImage, int n, int color_space);
-  void RatioPixels(float* CurrentPixel, float* BGPixel, float* DeltaPixel, int n);
-
-  void getFuzzyIntegralSugeno(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage);
-  void getFuzzyIntegralChoquet(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage);
-  void FuzzyMeasureG(float g1, float g2, float g3, float *G);
-  void Trier(float* g, int n, int* index);
-  float min(float *a, float *b);
-  float max(float *g, int n);
-  void gDeDeux(float* a, float* b, float* lambda);
-  void getLambda(float* g);
-
-  void AdaptativeSelectiveBackgroundModelUpdate(IplImage* CurrentImage, IplImage* BGImage, IplImage* OutputImage, IplImage* Integral, float seuil, float alpha);
-};
diff --git a/package_bgs/T2F/MRF.h b/package_bgs/T2F/MRF.h
deleted file mode 100644
index 1276a30da751e5ee936b19235b72338b1ea2bef8..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/MRF.h
+++ /dev/null
@@ -1,104 +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
-
-#include "T2FMRF.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    // base class
-    class MRF
-    {
-    public:
-      IplImage *in_image, *out_image;
-      //image's width and height
-      int width, height;
-
-    public:
-      MRF();
-
-    protected:
-
-      //////////////////////////////////////////////////////////////////////////
-      //the number of labeling
-      int no_regions;
-      //potential of Space  Constraint
-      double beta;
-      //terminal condition when (deltaE < t)
-      double t;
-
-      //////////////////////////////////////////////////////////////////////////
-      //for gibbs
-      double T0;
-      //current temperature
-      double T;
-      double c;
-
-      //////////////////////////////////////////////////////////////////////////
-      // alpha value for MMD
-      double alpha;
-
-      //////////////////////////////////////////////////////////////////////////
-      //current global energy
-      double E;
-      //old global energy
-      double E_old;
-      //number of iteration
-      int K;
-
-      //////////////////////////////////////////////////////////////////////////
-      //labeling image
-      int **classes;
-      //input image
-      int **in_image_data;
-      //evidence
-      float ** local_evidence;
-    };
-
-    /************************************************************************/
-    /* the Markov Random Field with time constraints for T2FGMM   */
-    /************************************************************************/
-    class MRF_TC : public MRF
-    {
-    private:
-      double beta_time;
-
-    public:
-      IplImage *background2;
-      RgbImage background;
-      int **old_labeling;
-
-    public:
-      MRF_TC();
-      ~MRF_TC();
-      double TimeEnergy2(int i, int j, int label);
-      void OnIterationOver2(void);
-      void Build_Classes_OldLabeling_InImage_LocalEnergy();
-      void InitEvidence2(GMM *gmm, HMM *hmm, IplImage *labeling);
-      void CreateOutput2();
-      double CalculateEnergy2();
-      double LocalEnergy2(int i, int j, int label);
-      double Doubleton2(int i, int j, int label);
-
-      void Gibbs2();
-      void ICM2();
-      void Metropolis2(bool mmd);
-    };
-  }
-}
diff --git a/package_bgs/T2F/T2FGMM.cpp b/package_bgs/T2F/T2FGMM.cpp
deleted file mode 100644
index 6ff99978d2804c3530e4950379ddf2506ed5e034..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/T2FGMM.cpp
+++ /dev/null
@@ -1,336 +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/>.
-*/
-/****************************************************************************
-*
-* T2FGMM.cpp
-*
-* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs)
-* "Modeling of Dynamic Backgrounds by Type-2 Fuzzy Gaussians Mixture Models"
-* Author: Fida El Baf, Thierry Bouwmans, September 2008.
-
-******************************************************************************/
-
-#include "T2FGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-int compareT2FGMM(const void* _gmm1, const void* _gmm2)
-{
-  GMM gmm1 = *(GMM*)_gmm1;
-  GMM gmm2 = *(GMM*)_gmm2;
-
-  if (gmm1.significants < gmm2.significants)
-    return 1;
-  else if (gmm1.significants == gmm2.significants)
-    return 0;
-  else
-    return -1;
-}
-
-T2FGMM::T2FGMM()
-{
-  m_modes = NULL;
-}
-
-T2FGMM::~T2FGMM()
-{
-  delete[] m_modes;
-}
-
-void T2FGMM::Initalize(const BgsParams& param)
-{
-  m_params = (T2FGMMParams&)param;
-
-  // Tbf - the threshold
-  m_bg_threshold = 0.75f;	// 1-cf from the paper
-
-  // Tgenerate - the threshold
-  m_variance = 36.0f;		// sigma for the new mode
-
-  // GMM for each pixel
-  m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
-
-  // used modes per pixel
-  m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
-
-  m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
-
-  // Factor control for the T2FGMM-UM [0,3]
-  //km = (float) 1.5;
-  km = (float)m_params.KM();
-
-  // Factor control for the T2FGMM-UV [0.3,1]
-  //kv = (float) 0.6;
-  kv = (float)m_params.KV();
-}
-
-RgbImage* T2FGMM::Background()
-{
-  return &m_background;
-}
-
-void T2FGMM::InitModel(const RgbImage& data)
-{
-  m_modes_per_pixel.Clear();
-
-  for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
-  {
-    m_modes[i].weight = 0;
-    m_modes[i].variance = 0;
-    m_modes[i].muR = 0;
-    m_modes[i].muG = 0;
-    m_modes[i].muB = 0;
-    m_modes[i].significants = 0;
-  }
-}
-
-void T2FGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
-{
-  // it doesn't make sense to have conditional updates in the GMM framework
-}
-
-void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
-  unsigned char& low_threshold, unsigned char& high_threshold)
-{
-  // calculate distances to the modes (+ sort???)
-  // here we need to go in descending order!!!
-  long pos;
-  bool bFitsPDF = false;
-  bool bBackgroundLow = false;
-  bool bBackgroundHigh = false;
-
-  float fOneMinAlpha = 1 - m_params.Alpha();
-  float totalWeight = 0.0f;
-
-  // calculate number of Gaussians to include in the background model
-  int backgroundGaussians = 0;
-  double sum = 0.0;
-  for (int i = 0; i < numModes; ++i)
-  {
-    if (sum < m_bg_threshold)
-    {
-      backgroundGaussians++;
-      sum += m_modes[posPixel + i].weight;
-    }
-    else
-      break;
-  }
-
-  // update all distributions and check for match with current pixel
-  for (int iModes = 0; iModes < numModes; iModes++)
-  {
-    pos = posPixel + iModes;
-    float weight = m_modes[pos].weight;
-
-    // fit not found yet
-    if (!bFitsPDF)
-    {
-      //check if it belongs to some of the modes
-      //calculate distance
-      float var = m_modes[pos].variance;
-      float muR = m_modes[pos].muR;
-      float muG = m_modes[pos].muG;
-      float muB = m_modes[pos].muB;
-
-      //float km = 2;
-      //float kv = 0.9;
-
-      float dR = fabs(muR - pixel(0));
-      float dG = fabs(muG - pixel(1));
-      float dB = fabs(muB - pixel(2));
-
-      // calculate the squared distance
-      float HR;
-      float HG;
-      float HB;
-
-      // T2FGMM-UM
-      if (m_params.Type() == TYPE_T2FGMM_UM)
-      {
-        if ((pixel(0) < muR - km*var) || (pixel(0) > muR + km*var))
-          HR = 2 * km*dR / var;
-        else
-          HR = dR*dR / (2 * var*var) + km*dR / var + km*km / 2;
-
-        if ((pixel(1) < muG - km*var) || (pixel(1) > muG + km*var))
-          HG = 2 * km*dG / var;
-        else
-          HG = dG*dG / (2 * var*var) + km*dG / var + km*km / 2;
-
-        if ((pixel(2) < muB - km*var) || (pixel(2) > muB + km*var))
-          HB = 2 * km*dB / var;
-        else
-          HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2;
-      }
-
-      // T2FGMM-UV
-      if (m_params.Type() == TYPE_T2FGMM_UV)
-      {
-        HR = (1 / (kv*kv) - kv*kv) * (pixel(0) - muR) * (pixel(0) - muR) / (2 * var);
-        HG = (1 / (kv*kv) - kv*kv) * (pixel(1) - muG) * (pixel(1) - muG) / (2 * var);
-        HB = (1 / (kv*kv) - kv*kv) * (pixel(2) - muB) * (pixel(2) - muB) / (2 * var);
-      }
-
-      // calculate the squared distance
-      float dist = (HR*HR + HG*HG + HB*HB);
-
-      if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
-        bBackgroundHigh = true;
-
-      // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
-      if (dist < m_params.LowThreshold()*var)
-      {
-        bFitsPDF = true;
-
-        // check if this Gaussian is part of the background model
-        if (iModes < backgroundGaussians)
-          bBackgroundLow = true;
-
-        //update distribution
-        float k = m_params.Alpha() / weight;
-        weight = fOneMinAlpha*weight + m_params.Alpha();
-        m_modes[pos].weight = weight;
-        m_modes[pos].muR = muR - k*(dR);
-        m_modes[pos].muG = muG - k*(dG);
-        m_modes[pos].muB = muB - k*(dB);
-
-        //limit the variance
-        float sigmanew = var + k*(dist - var);
-        m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-      else
-      {
-        weight = fOneMinAlpha*weight;
-        if (weight < 0.0)
-        {
-          weight = 0.0;
-          numModes--;
-        }
-
-        m_modes[pos].weight = weight;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-    }
-    else
-    {
-      weight = fOneMinAlpha*weight;
-      if (weight < 0.0)
-      {
-        weight = 0.0;
-        numModes--;
-      }
-      m_modes[pos].weight = weight;
-      m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-    }
-
-    totalWeight += weight;
-  }
-
-  // renormalize weights so they add to one
-  double invTotalWeight = 1.0 / totalWeight;
-  for (int iLocal = 0; iLocal < numModes; iLocal++)
-  {
-    m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
-    m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
-      / sqrt(m_modes[posPixel + iLocal].variance);
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&m_modes[posPixel], numModes, sizeof(GMM), compareT2FGMM);
-
-  // make new mode if needed and exit
-  if (!bFitsPDF)
-  {
-    if (numModes < m_params.MaxModes())
-      numModes++;
-    //else
-    // the weakest mode will be replaced
-
-    pos = posPixel + numModes - 1;
-
-    m_modes[pos].muR = pixel.ch[0];
-    m_modes[pos].muG = pixel.ch[1];
-    m_modes[pos].muB = pixel.ch[2];
-    m_modes[pos].variance = m_variance;
-    m_modes[pos].significants = 0;			// will be set below
-
-    if (numModes == 1)
-      m_modes[pos].weight = 1;
-    else
-      m_modes[pos].weight = m_params.Alpha();
-
-    //renormalize weights
-    int iLocal;
-    float sum = 0.0;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-      sum += m_modes[posPixel + iLocal].weight;
-
-    double invSum = 1.0 / sum;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-    {
-      m_modes[posPixel + iLocal].weight *= (float)invSum;
-      m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight / sqrt(m_modes[posPixel + iLocal].variance);
-    }
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareT2FGMM);
-
-  if (bBackgroundLow)
-    low_threshold = BACKGROUND;
-  else
-    low_threshold = FOREGROUND;
-
-  if (bBackgroundHigh)
-    high_threshold = BACKGROUND;
-  else
-    high_threshold = FOREGROUND;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//Input:
-//  data - a pointer to the data of a RGB image of the same size
-//Output:
-//  output - a pointer to the data of a gray value image of the same size 
-//					(the memory should already be reserved) 
-//					values: 255-foreground, 125-shadow, 0-background
-///////////////////////////////////////////////////////////////////////////////
-void T2FGMM::Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask)
-{
-  unsigned char low_threshold, high_threshold;
-  long posPixel;
-
-  // update each pixel of the image
-  for (unsigned int r = 0; r < m_params.Height(); ++r)
-  {
-    for (unsigned int c = 0; c < m_params.Width(); ++c)
-    {
-      // update model + background subtract
-      posPixel = (r*m_params.Width() + c) * m_params.MaxModes();
-
-      SubtractPixel(posPixel, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
-
-      low_threshold_mask(r, c) = low_threshold;
-      high_threshold_mask(r, c) = high_threshold;
-
-      m_background(r, c, 0) = (unsigned char)m_modes[posPixel].muR;
-      m_background(r, c, 1) = (unsigned char)m_modes[posPixel].muG;
-      m_background(r, c, 2) = (unsigned char)m_modes[posPixel].muB;
-    }
-  }
-}
diff --git a/package_bgs/T2F/T2FGMM.h b/package_bgs/T2F/T2FGMM.h
deleted file mode 100644
index 203c3509275b72a85b90226d9ada0ce0791dcce5..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/T2FGMM.h
+++ /dev/null
@@ -1,131 +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/>.
-*/
-/****************************************************************************
-*
-* T2FGMM.h
-*
-* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs)
-* "Modeling of Dynamic Backgrounds by Type-2 Fuzzy Gaussians Mixture Models"
-* Author: Fida El Baf, Thierry Bouwmans, September 2008
-*
-* This code is based on code by Z. Zivkovic's written for his enhanced GMM
-* background subtraction algorithm:
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-******************************************************************************/
-#pragma once
-
-#include "../dp/Bgs.h"
-#include "../dp/GrimsonGMM.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    const int TYPE_T2FGMM_UM = 0;
-    const int TYPE_T2FGMM_UV = 1;
-
-    // --- User adjustable parameters used by the T2F GMM BGS algorithm ---
-    class T2FGMMParams : public BgsParams
-    {
-    public:
-      float &LowThreshold() { return m_low_threshold; }
-      float &HighThreshold() { return m_high_threshold; }
-
-      float &Alpha() { return m_alpha; }
-      int &MaxModes() { return m_max_modes; }
-      int &Type() { return m_type; }
-      float &KM() { return m_km; }
-      float &KV() { return m_kv; }
-
-    private:
-      // Threshold on the squared dist. to decide when a sample is close to an existing
-      // components. If it is not close to any a new component will be generated.
-      // Smaller threshold values lead to more generated components and higher threshold values
-      // lead to a small number of components but they can grow too large.
-      //
-      // It is usual easiest to think of these thresholds as being the number of variances away
-      // from the mean of a pixel before it is considered to be from the foreground.
-      float m_low_threshold;
-      float m_high_threshold;
-
-      // alpha - speed of update - if the time interval you want to average over is T
-      // set alpha=1/T.
-      float m_alpha;
-
-      // Maximum number of modes (Gaussian components) that will be used per pixel
-      int m_max_modes;
-
-      // T2FGMM_UM / T2FGMM_UV
-      int m_type;
-
-      // Factor control for the T2FGMM-UM
-      float m_km;
-
-      // Factor control for the T2FGMM-UV
-      float m_kv;
-    };
-
-    // --- T2FGMM BGS algorithm ---
-    class T2FGMM : public Bgs
-    {
-    public:
-      T2FGMM();
-      ~T2FGMM();
-
-      void Initalize(const BgsParams& param);
-
-      void InitModel(const RgbImage& data);
-      void Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask);
-      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
-
-      RgbImage* Background();
-
-    private:
-      void SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold);
-
-      // User adjustable parameters
-      T2FGMMParams m_params;
-
-      // Threshold when the component becomes significant enough to be included into
-      // the background model. It is the TB = 1-cf from the paper. So I use cf=0.1 => TB=0.9
-      // For alpha=0.001 it means that the mode should exist for approximately 105 frames before
-      // it is considered foreground
-      float m_bg_threshold; //1-cf from the paper
-
-      // Initial variance for the newly generated components.
-      // It will will influence the speed of adaptation. A good guess should be made.
-      // A simple way is to estimate the typical standard deviation from the images.
-      float m_variance;
-
-      // Dynamic array for the mixture of Gaussians
-      GMM* m_modes;
-
-      // Number of Gaussian components per pixel
-      BwImage m_modes_per_pixel;
-
-      // Current background model
-      RgbImage m_background;
-
-      // Factor control for the T2FGMM-UM
-      float km;
-
-      // Factor control for the T2FGMM-UV
-      float kv;
-    };
-  }
-}
diff --git a/package_bgs/T2F/T2FMRF.cpp b/package_bgs/T2F/T2FMRF.cpp
deleted file mode 100644
index e722d0240e7da9d898d37ce5b8f726201bcb95bd..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/T2FMRF.cpp
+++ /dev/null
@@ -1,431 +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/>.
-*/
-/****************************************************************************
-*
-* T2FMRF.cpp
-*
-* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs)
-* "Modeling of Dynamic Backgrounds by Type-2 Fuzzy Gaussians Mixture Models"
-* Author: Fida El Baf, Thierry Bouwmans, September 2008
-*
-* This code is based on code by Z. Zivkovic's written for his enhanced GMM
-* background subtraction algorithm:
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-******************************************************************************/
-
-#include "T2FMRF.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-int compareT2FMRF(const void* _gmm1, const void* _gmm2)
-{
-  GMM gmm1 = *(GMM*)_gmm1;
-  GMM gmm2 = *(GMM*)_gmm2;
-
-  if (gmm1.significants < gmm2.significants)
-    return 1;
-  else if (gmm1.significants == gmm2.significants)
-    return 0;
-  else
-    return -1;
-}
-
-GMM* T2FMRF::gmm()
-{
-  return m_modes;
-}
-HMM* T2FMRF::hmm()
-{
-  return m_state;
-}
-
-T2FMRF::T2FMRF()
-{
-  m_modes = NULL;
-}
-
-T2FMRF::~T2FMRF()
-{
-  delete[] m_modes;
-}
-
-void T2FMRF::Initalize(const BgsParams& param)
-{
-  m_params = (T2FMRFParams&)param;
-
-  // Tbf - the threshold
-  m_bg_threshold = 0.75f;	// 1-cf from the paper
-
-  // Tgenerate - the threshold
-  m_variance = 36.0f;		// sigma for the new mode
-
-  // GMM for each pixel
-  m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
-
-  //HMM for each pixel
-  m_state = new HMM[m_params.Size()];
-
-  // used modes per pixel
-  m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
-
-  m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
-
-  // Factor control for the T2FGMM-UM [0,3]
-  // km = (float) 2; //1.5;
-  km = (float)m_params.KM();
-
-  // Factor control for the T2FGMM-UV [0.3,1]
-  // kv = (float) 0.9; //0.6;
-  kv = (float)m_params.KV();
-}
-
-RgbImage* T2FMRF::Background()
-{
-  return &m_background;
-}
-
-void T2FMRF::InitModel(const RgbImage& data)
-{
-  m_modes_per_pixel.Clear();
-
-  for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
-  {
-    m_modes[i].weight = 0;
-    m_modes[i].variance = 0;
-    m_modes[i].muR = 0;
-    m_modes[i].muG = 0;
-    m_modes[i].muB = 0;
-    m_modes[i].significants = 0;
-  }
-
-  for (unsigned int j = 0; j < m_params.Size(); ++j)
-  {
-    m_state[j].State = background;
-    m_state[j].Ab2b = 0.7f;
-    m_state[j].Ab2f = 0.3f;
-    m_state[j].Af2b = 0.4f;
-    m_state[j].Af2f = 0.6f;
-    m_state[j].T = 0.7f;
-  }
-}
-
-void T2FMRF::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
-{
-  // it doesn't make sense to have conditional updates in the GMM framework
-}
-
-void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, unsigned char& numModes,
-  unsigned char& low_threshold, unsigned char& high_threshold)
-{
-  // calculate distances to the modes (+ sort???)
-  // here we need to go in descending order!!!
-  long pos;
-  bool bFitsPDF = false;
-  bool bBackgroundLow = false;
-  bool bBackgroundHigh = false;
-
-  HiddenState CurrentState = m_state[posPixel].State;
-  float Ab2b = m_state[posPixel].Ab2b;
-  float Ab2f = m_state[posPixel].Ab2f;
-  float Af2b = m_state[posPixel].Af2b;
-  float Af2f = m_state[posPixel].Af2f;
-  //float T = m_state[posPixel].T;
-
-  float fOneMinAlpha = 1 - m_params.Alpha();
-  float totalWeight = 0.0f;
-
-  // calculate number of Gaussians to include in the background model
-  int backgroundGaussians = 0;
-  double sum = 0.0;
-  for (int i = 0; i < numModes; ++i)
-  {
-    if (sum < m_bg_threshold)
-    {
-      backgroundGaussians++;
-      sum += m_modes[posGMode + i].weight;
-    }
-    else
-      break;
-  }
-
-  // update all distributions and check for match with current pixel
-  for (int iModes = 0; iModes < numModes; iModes++)
-  {
-    pos = posGMode + iModes;
-    float weight = m_modes[pos].weight;
-
-    // fit not found yet
-    if (!bFitsPDF)
-    {
-      //check if it belongs to some of the modes
-      //calculate distance
-      float var = m_modes[pos].variance;
-      float muR = m_modes[pos].muR;
-      float muG = m_modes[pos].muG;
-      float muB = m_modes[pos].muB;
-
-      //float km = 2;
-      //float kv = 0.9;
-
-      float dR = fabs(muR - pixel(0));
-      float dG = fabs(muG - pixel(1));
-      float dB = fabs(muB - pixel(2));
-
-      // calculate the squared distance
-      float HR;
-      float HG;
-      float HB;
-
-      // T2FMRF-UM
-      if (m_params.Type() == TYPE_T2FMRF_UM)
-      {
-        if ((pixel(0) < muR - km*var) || (pixel(0) > muR + km*var))
-          HR = 2 * km*dR / var;
-        else
-          HR = dR*dR / (2 * var*var) + km*dR / var + km*km / 2;
-
-        if ((pixel(1) < muG - km*var) || (pixel(1) > muG + km*var))
-          HG = 2 * km*dG / var;
-        else
-          HG = dG*dG / (2 * var*var) + km*dG / var + km*km / 2;
-
-        if ((pixel(2) < muB - km*var) || (pixel(2) > muB + km*var))
-          HB = 2 * km*dB / var;
-        else
-          HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2;
-      }
-
-      // T2FGMM-UV
-      if (m_params.Type() == TYPE_T2FMRF_UV)
-      {
-        HR = (1 / (kv*kv) - kv*kv) * (pixel(0) - muR) * (pixel(0) - muR) / (2 * var);
-        HG = (1 / (kv*kv) - kv*kv) * (pixel(1) - muG) * (pixel(1) - muG) / (2 * var);
-        HB = (1 / (kv*kv) - kv*kv) * (pixel(2) - muB) * (pixel(2) - muB) / (2 * var);
-      }
-
-      float ro;
-      if (CurrentState == background)
-      {
-        if (Ab2b != 0) ro = (Ab2f / Ab2b);
-        else ro = 10;
-      }
-      else
-      {
-        if (Af2b != 0) ro = (Af2f / Af2b);
-        else ro = 10;
-      }
-
-      // calculate the squared distance
-      float dist = (HR*HR + HG*HG + HB*HB);
-
-      if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
-        bBackgroundHigh = true;
-
-      // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
-      if (dist < m_params.LowThreshold()*var)
-      {
-        bFitsPDF = true;
-
-        // check if this Gaussian is part of the background model
-        if (iModes < backgroundGaussians)
-          bBackgroundLow = true;
-
-        //update distribution
-        float k = m_params.Alpha() / weight;
-        weight = fOneMinAlpha*weight + m_params.Alpha();
-        m_modes[pos].weight = weight;
-        m_modes[pos].muR = muR - k*(dR);
-        m_modes[pos].muG = muG - k*(dG);
-        m_modes[pos].muB = muB - k*(dB);
-
-        //limit the variance
-        float sigmanew = var + k*(dist - var);
-        m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-      else
-      {
-        weight = fOneMinAlpha*weight;
-        if (weight < 0.0)
-        {
-          weight = 0.0;
-          numModes--;
-        }
-
-        m_modes[pos].weight = weight;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-    }
-    else
-    {
-      weight = fOneMinAlpha*weight;
-      if (weight < 0.0)
-      {
-        weight = 0.0;
-        numModes--;
-      }
-      m_modes[pos].weight = weight;
-      m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-    }
-
-    totalWeight += weight;
-  }
-
-  // renormalize weights so they add to one
-  double invTotalWeight = 1.0 / totalWeight;
-  for (int iLocal = 0; iLocal < numModes; iLocal++)
-  {
-    m_modes[posGMode + iLocal].weight *= (float)invTotalWeight;
-    m_modes[posGMode + iLocal].significants = m_modes[posGMode + iLocal].weight / sqrt(m_modes[posGMode + iLocal].variance);
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&m_modes[posGMode], numModes, sizeof(GMM), compareT2FMRF);
-
-  // make new mode if needed and exit
-  if (!bFitsPDF)
-  {
-    if (numModes < m_params.MaxModes())
-      numModes++;
-    //else
-    // the weakest mode will be replaced
-
-    pos = posGMode + numModes - 1;
-
-    m_modes[pos].muR = pixel.ch[0];
-    m_modes[pos].muG = pixel.ch[1];
-    m_modes[pos].muB = pixel.ch[2];
-    m_modes[pos].variance = m_variance;
-    m_modes[pos].significants = 0;			// will be set below
-
-    if (numModes == 1)
-      m_modes[pos].weight = 1;
-    else
-      m_modes[pos].weight = m_params.Alpha();
-
-    //renormalize weights
-    int iLocal;
-    float sum = 0.0;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-      sum += m_modes[posGMode + iLocal].weight;
-
-    double invSum = 1.0 / sum;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-    {
-      m_modes[posGMode + iLocal].weight *= (float)invSum;
-      m_modes[posGMode + iLocal].significants = m_modes[posPixel + iLocal].weight / sqrt(m_modes[posGMode + iLocal].variance);
-    }
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&(m_modes[posGMode]), numModes, sizeof(GMM), compareT2FMRF);
-
-  if (bBackgroundLow)
-  {
-    low_threshold = BACKGROUND;
-    m_state[posPixel].State = background;
-
-    if (CurrentState == background)
-    {
-      float b2b = fOneMinAlpha*Ab2b + m_params.Alpha();
-      float b2f = fOneMinAlpha*Ab2f;
-
-      float b = b2b + b2f;
-      m_state[posPixel].Ab2b = b2b / b;
-      m_state[posPixel].Ab2f = b2f / b;
-      m_state[posPixel].T = m_state[posPixel].Ab2b;
-    }
-    else
-    {
-      float f2b = fOneMinAlpha*Af2b + m_params.Alpha();
-      float f2f = fOneMinAlpha*Af2f;
-
-      float f = f2b + f2f;
-      m_state[posPixel].Af2b = f2b / f;
-      m_state[posPixel].Af2f = f2f / f;
-      m_state[posPixel].T = m_state[posPixel].Af2b;
-    }
-  }
-  else
-  {
-    low_threshold = FOREGROUND;
-    m_state[posPixel].State = foreground;
-
-    if (CurrentState == background)
-    {
-      float b2b = fOneMinAlpha*Ab2b;
-      float b2f = fOneMinAlpha*Ab2f + m_params.Alpha();
-
-      float b = b2b + b2f;
-      m_state[posPixel].Ab2b = b2b / b;
-      m_state[posPixel].Ab2f = b2f / b;
-      m_state[posPixel].T = m_state[posPixel].Ab2b;
-    }
-    else
-    {
-      float f2b = fOneMinAlpha*Af2b;
-      float f2f = fOneMinAlpha*Af2f + m_params.Alpha();
-
-      float f = f2b + f2f;
-      m_state[posPixel].Af2b = f2b / f;
-      m_state[posPixel].Af2f = f2f / f;
-      m_state[posPixel].T = m_state[posPixel].Af2b;
-    }
-  }
-
-  if (bBackgroundHigh)
-    high_threshold = BACKGROUND;
-  else
-    high_threshold = FOREGROUND;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//Input:
-//  data - a pointer to the data of a RGB image of the same size
-//Output:
-//  output - a pointer to the data of a gray value image of the same size 
-//					(the memory should already be reserved) 
-//					values: 255-foreground, 125-shadow, 0-background
-///////////////////////////////////////////////////////////////////////////////
-void T2FMRF::Subtract(int frame_num, const RgbImage& data,
-  BwImage& low_threshold_mask, BwImage& high_threshold_mask)
-{
-  unsigned char low_threshold, high_threshold;
-  long posPixel;
-  long posGMode;
-
-  // update each pixel of the image
-  for (unsigned int r = 0; r < m_params.Height(); ++r)
-  {
-    for (unsigned int c = 0; c < m_params.Width(); ++c)
-    {
-      // update model + background subtract
-      posPixel = r*m_params.Width() + c;
-      posGMode = (r*m_params.Width() + c) * m_params.MaxModes();
-
-      SubtractPixel(posPixel, posGMode, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
-
-      low_threshold_mask(r, c) = low_threshold;
-      high_threshold_mask(r, c) = high_threshold;
-
-      m_background(r, c, 0) = (unsigned char)m_modes[posGMode].muR;
-      m_background(r, c, 1) = (unsigned char)m_modes[posGMode].muG;
-      m_background(r, c, 2) = (unsigned char)m_modes[posGMode].muB;
-    }
-  }
-}
diff --git a/package_bgs/T2F/T2FMRF.h b/package_bgs/T2F/T2FMRF.h
deleted file mode 100644
index 1015426eabeb83055fe3d4969c0d8fab4fda0775..0000000000000000000000000000000000000000
--- a/package_bgs/T2F/T2FMRF.h
+++ /dev/null
@@ -1,160 +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/>.
-*/
-/****************************************************************************
-*
-* T2FMRF.h
-*
-* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs)
-* "Modeling of Dynamic Backgrounds by Type-2 Fuzzy Gaussians Mixture Models"
-* Author: Fida El Baf, Thierry Bouwmans, September 2008
-*
-* This code is based on code by Z. Zivkovic's written for his enhanced GMM
-* background subtraction algorithm:
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-******************************************************************************/
-#pragma once
-
-#include "../dp/Bgs.h"
-#include "../dp/GrimsonGMM.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    const int TYPE_T2FMRF_UM = 0;
-    const int TYPE_T2FMRF_UV = 1;
-
-    enum HiddenState { background, foreground };
-
-    typedef struct HMMState
-    {
-      float T;
-      //Hidden State
-      HiddenState State;
-      //transition probability
-      float Ab2b;
-      float Ab2f;
-      float Af2f;
-      float Af2b;
-    } HMM;
-
-    //typedef struct GMMGaussian
-    //{
-    //  float variance;
-    //  float muR;
-    //  float muG;
-    //  float muB;
-    //  float weight;
-    //  float significants; // this is equal to weight / standard deviation and is used to
-    //  // determine which Gaussians should be part of the background model
-    //} GMM;
-
-    // --- User adjustable parameters used by the T2F GMM BGS algorithm ---
-    class T2FMRFParams : public BgsParams
-    {
-    public:
-      float &LowThreshold() { return m_low_threshold; }
-      float &HighThreshold() { return m_high_threshold; }
-
-      float &Alpha() { return m_alpha; }
-      int &MaxModes() { return m_max_modes; }
-      int &Type() { return m_type; }
-      float &KM() { return m_km; }
-      float &KV() { return m_kv; }
-
-    private:
-      // Threshold on the squared dist. to decide when a sample is close to an existing
-      // components. If it is not close to any a new component will be generated.
-      // Smaller threshold values lead to more generated components and higher threshold values
-      // lead to a small number of components but they can grow too large.
-      //
-      // It is usual easiest to think of these thresholds as being the number of variances away
-      // from the mean of a pixel before it is considered to be from the foreground.
-      float m_low_threshold;
-      float m_high_threshold;
-
-      // alpha - speed of update - if the time interval you want to average over is T
-      // set alpha=1/T.
-      float m_alpha;
-
-      // Maximum number of modes (Gaussian components) that will be used per pixel
-      int m_max_modes;
-
-      // T2FMRF_UM / T2FMRF_UV
-      int m_type;
-
-      // Factor control for the T2FMRF-UM
-      float m_km;
-
-      // Factor control for the T2FMRF-UV
-      float m_kv;
-    };
-
-    // --- T2FGMM BGS algorithm ---
-    class T2FMRF : public Bgs
-    {
-    public:
-      T2FMRF();
-      ~T2FMRF();
-
-      void Initalize(const BgsParams& param);
-      void InitModel(const RgbImage& data);
-      void Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask);
-      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
-
-      RgbImage* Background();
-
-      GMM *gmm(void);
-      HMM *hmm(void);
-
-    private:
-      void SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold);
-
-      // User adjustable parameters
-      T2FMRFParams m_params;
-
-      // Threshold when the component becomes significant enough to be included into
-      // the background model. It is the TB = 1-cf from the paper. So I use cf=0.1 => TB=0.9
-      // For alpha=0.001 it means that the mode should exist for approximately 105 frames before
-      // it is considered foreground
-      float m_bg_threshold; //1-cf from the paper
-
-      // Initial variance for the newly generated components.
-      // It will will influence the speed of adaptation. A good guess should be made.
-      // A simple way is to estimate the typical standard deviation from the images.
-      float m_variance;
-
-      // Dynamic array for the mixture of Gaussians
-      GMM* m_modes;
-
-      //Dynamic array for the hidden state
-      HMM* m_state;
-
-      // Number of Gaussian components per pixel
-      BwImage m_modes_per_pixel;
-
-      // Current background model
-      RgbImage m_background;
-
-      // Factor control for the T2FGMM-UM
-      float km;
-      // Factor control for the T2FGMM-UV
-      float kv;
-    };
-  }
-}
diff --git a/package_bgs/T2FGMM_UM.cpp b/package_bgs/T2FGMM_UM.cpp
deleted file mode 100644
index ad1b40e82ae8e504a7713a3f8d87afe8bc0897b8..0000000000000000000000000000000000000000
--- a/package_bgs/T2FGMM_UM.cpp
+++ /dev/null
@@ -1,113 +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 "T2FGMM_UM.h"
-
-using namespace bgslibrary::algorithms;
-
-T2FGMM_UM::T2FGMM_UM() :
-  frameNumber(0), threshold(9.0), alpha(0.01), km(1.5f), kv(0.6f), gaussians(3)
-{
-  std::cout << "T2FGMM_UM()" << std::endl;
-  setup("./config/T2FGMM_UM.xml");
-}
-
-T2FGMM_UM::~T2FGMM_UM()
-{
-  std::cout << "~T2FGMM_UM()" << std::endl;
-}
-
-void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold;
-    params.HighThreshold() = 2 * params.LowThreshold();
-    params.Alpha() = alpha;
-    params.MaxModes() = gaussians;
-    params.Type() = TYPE_T2FGMM_UM;
-    params.KM() = km; // Factor control for the T2FGMM-UM [0,3] default: 1.5
-    params.KV() = kv; // Factor control for the T2FGMM-UV [0.3,1] default: 0.6
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("T2FGMM-UM", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void T2FGMM_UM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "km", km);
-  cvWriteReal(fs, "kv", kv);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void T2FGMM_UM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 9.0);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.01);
-  km = cvReadRealByName(fs, nullptr, "km", 1.5);
-  kv = cvReadRealByName(fs, nullptr, "kv", 0.6);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/T2FGMM_UM.h b/package_bgs/T2FGMM_UM.h
deleted file mode 100644
index c58aeb756e40f43ba838901d5ff691df25338666..0000000000000000000000000000000000000000
--- a/package_bgs/T2FGMM_UM.h
+++ /dev/null
@@ -1,57 +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
-
-#include "IBGS.h"
-#include "T2F/T2FGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class T2FGMM_UM : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      T2FGMMParams params;
-      T2FGMM bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      float km;
-      float kv;
-      int gaussians;
-
-    public:
-      T2FGMM_UM();
-      ~T2FGMM_UM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/T2FGMM_UV.cpp b/package_bgs/T2FGMM_UV.cpp
deleted file mode 100644
index 4e9708f68ef88b82f5495e8185c310858d982fa1..0000000000000000000000000000000000000000
--- a/package_bgs/T2FGMM_UV.cpp
+++ /dev/null
@@ -1,113 +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 "T2FGMM_UV.h"
-
-using namespace bgslibrary::algorithms;
-
-T2FGMM_UV::T2FGMM_UV() :
-  frameNumber(0), threshold(9.0), alpha(0.01), km(1.5f), kv(0.6f), gaussians(3)
-{
-  std::cout << "T2FGMM_UV()" << std::endl;
-  setup("./config/T2FGMM_UV.xml");
-}
-
-T2FGMM_UV::~T2FGMM_UV()
-{
-  std::cout << "~T2FGMM_UV()" << std::endl;
-}
-
-void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-    frame_data.ReleaseMemory(false);
-  frame_data = frame;
-
-  if (firstTime)
-  {
-    int width = img_input.size().width;
-    int height = img_input.size().height;
-
-    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
-    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
-
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = threshold;
-    params.HighThreshold() = 2 * params.LowThreshold();
-    params.Alpha() = alpha;
-    params.MaxModes() = gaussians;
-    params.Type() = TYPE_T2FGMM_UV;
-    params.KM() = km; // Factor control for the T2FGMM-UM [0,3] default: 1.5
-    params.KV() = kv; // Factor control for the T2FGMM-UV [0.3,1] default: 0.6
-
-    bgs.Initalize(params);
-    bgs.InitModel(frame_data);
-  }
-
-  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
-  lowThresholdMask.Clear();
-  bgs.Update(frameNumber, frame_data, lowThresholdMask);
-
-  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
-  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
-  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    cv::imshow("T2FGMM-UV", img_foreground);
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-  frameNumber++;
-}
-
-void T2FGMM_UV::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "km", km);
-  cvWriteReal(fs, "kv", kv);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void T2FGMM_UV::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 9.0);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.01);
-  km = cvReadRealByName(fs, nullptr, "km", 1.5);
-  kv = cvReadRealByName(fs, nullptr, "kv", 0.6);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/T2FGMM_UV.h b/package_bgs/T2FGMM_UV.h
deleted file mode 100644
index 6102f3a21c99939d0b71316768378b01e7e983f9..0000000000000000000000000000000000000000
--- a/package_bgs/T2FGMM_UV.h
+++ /dev/null
@@ -1,57 +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
-
-#include "IBGS.h"
-#include "T2F/T2FGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class T2FGMM_UV : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage* frame;
-      RgbImage frame_data;
-
-      T2FGMMParams params;
-      T2FGMM bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      float km;
-      float kv;
-      int gaussians;
-
-    public:
-      T2FGMM_UV();
-      ~T2FGMM_UV();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/T2FMRF_UM.h b/package_bgs/T2FMRF_UM.h
deleted file mode 100644
index 01f6014c44dfb33526f0c9e97646d52ccad8cb48..0000000000000000000000000000000000000000
--- a/package_bgs/T2FMRF_UM.h
+++ /dev/null
@@ -1,64 +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
-
-#include "IBGS.h"
-#include "T2F/MRF.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class T2FMRF_UM : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage *frame;
-      RgbImage frame_data;
-
-      IplImage *old_labeling;
-      IplImage *old;
-
-      T2FMRFParams params;
-      T2FMRF bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      float km;
-      float kv;
-      int gaussians;
-
-      MRF_TC mrf;
-      GMM *gmm;
-      HMM *hmm;
-
-    public:
-      T2FMRF_UM();
-      ~T2FMRF_UM();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/T2FMRF_UV.h b/package_bgs/T2FMRF_UV.h
deleted file mode 100644
index 1c6917185365563acdc11d0aec41556ddd0ab429..0000000000000000000000000000000000000000
--- a/package_bgs/T2FMRF_UV.h
+++ /dev/null
@@ -1,64 +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
-
-#include "IBGS.h"
-#include "T2F/MRF.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class T2FMRF_UV : public IBGS
-    {
-    private:
-      long frameNumber;
-      IplImage *frame;
-      RgbImage frame_data;
-
-      IplImage *old_labeling;
-      IplImage *old;
-
-      T2FMRFParams params;
-      T2FMRF bgs;
-      BwImage lowThresholdMask;
-      BwImage highThresholdMask;
-
-      double threshold;
-      double alpha;
-      float km;
-      float kv;
-      int gaussians;
-
-      MRF_TC mrf;
-      GMM *gmm;
-      HMM *hmm;
-
-    public:
-      T2FMRF_UV();
-      ~T2FMRF_UV();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/Tapter.cpp b/package_bgs/Tapter.cpp
deleted file mode 100644
index 6d2425af5f13eeb785a889d05e045276f77b64e8..0000000000000000000000000000000000000000
--- a/package_bgs/Tapter.cpp
+++ /dev/null
@@ -1,139 +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 "Tapter.h"
-
-using namespace bgslibrary::algorithms;
-
-Tapter::Tapter() :
-    sensitivity(75), trainingSensitivity(245), learningRate(62), trainingLearningRate(255), trainingSteps(55)
-{
-    std::cout << "Tapter()" << std::endl;
-    setup("./config/Tapter.xml");
-//    frameCounter = 0;
-//    //inputPath = ".";
-//    //centerFile = ".";
-//    outputPath = ".";
-//    flagWrite = -1;
-//    writeDbgPic = -1;
-
-}
-
-Tapter::~Tapter()
-{
-    delete m_pBGModel;
-    std::cout << "~Tapter()" << std::endl;
-}
-
-//void Tapter::setFlagWrite(short flag)
-//{
-//    flagWrite = flag;
-//}
-
-//void Tapter::setFlagWriteDBGpic(short flag)
-//{
-//    writeDbgPic = flag;
-//}
-
-//void Tapter::setPathOut(std::string outPath)
-//{
-//    outputPath = outPath;
-//}
-
-
-//void Tapter::setLearningRate(int rate)
-//{
-//    learningRate = rate;
-
-//}
-//void Tapter::setInitialFrameCounter(int counter)
-//{
-//    frameCounter = counter;
-//}
-
-void Tapter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-
-    //!  continue the normal
-    init(img_input, img_output, img_bgmodel);
-
-    IplImage *frame = new IplImage(img_input);
-
-    if (firstTime)
-    {
-        int w = cvGetSize(frame).width;
-        int h = cvGetSize(frame).height;
-
-        m_pBGModel = new BGModelSom(w, h);
-        m_pBGModel->InitModel(frame);
-    }
-
-    m_pBGModel->setBGModelParameter(0, sensitivity);
-    m_pBGModel->setBGModelParameter(1, trainingSensitivity);
-    m_pBGModel->setBGModelParameter(2, learningRate);
-    m_pBGModel->setBGModelParameter(3, trainingLearningRate);
-    m_pBGModel->setBGModelParameter(5, trainingSteps);
-
-    m_pBGModel->UpdateModel(frame);
-
-    img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
-    img_background = cv::cvarrToMat(m_pBGModel->GetBG());
-
-#ifndef MEX_COMPILE_FLAG
-    if (showOutput)
-    {
-        cv::imshow("SOM Mask", img_foreground);
-        cv::imshow("SOM Model", img_background);
-    }
-#endif
-
-    img_foreground.copyTo(img_output);
-    img_background.copyTo(img_bgmodel);
-
-    delete frame;
-
-    firstTime = false;
-}
-
-void Tapter::saveConfig()
-{
-    CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-    cvWriteInt(fs, "sensitivity", sensitivity);
-    cvWriteInt(fs, "trainingSensitivity", trainingSensitivity);
-    cvWriteInt(fs, "learningRate", learningRate);
-    cvWriteInt(fs, "trainingLearningRate", trainingLearningRate);
-    cvWriteInt(fs, "trainingSteps", trainingSteps);
-    cvWriteInt(fs, "showOutput", showOutput);
-
-    cvReleaseFileStorage(&fs);
-}
-
-void Tapter::loadConfig()
-{
-    CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-    sensitivity = cvReadIntByName(fs, nullptr, "sensitivity", 75);
-    trainingSensitivity = cvReadIntByName(fs, nullptr, "trainingSensitivity", 245);
-    learningRate = cvReadIntByName(fs, nullptr, "learningRate", 62);
-    trainingLearningRate = cvReadIntByName(fs, nullptr, "trainingLearningRate", 255);
-    trainingSteps = cvReadIntByName(fs, nullptr, "trainingSteps", 55);
-    showOutput = cvReadIntByName(fs, 0, "showOutput", true);
-
-    cvReleaseFileStorage(&fs);
-}
-
-
diff --git a/package_bgs/Tapter.h b/package_bgs/Tapter.h
deleted file mode 100644
index ae4ef5eca2114f95390f6a17c7900d7049a3cece..0000000000000000000000000000000000000000
--- a/package_bgs/Tapter.h
+++ /dev/null
@@ -1,88 +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
-
-//std lib
-#include <sstream>
-#include <vector>
-//opencv
-#include "opencv2/opencv.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
-//bgslib
-#include "lb/BGModelSom.h"
-#include "IBGS.h"
-
-#include "ttoolbox.h"
-
-//#define MC_SHOW_STEP_ANALYSE
-
-using namespace lb_library;
-using namespace lb_library::AdaptiveSOM;
-using namespace cv;
-using namespace std;
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class Tapter : public IBGS
-    {
-    private:
-      BGModel* m_pBGModel;
-      int sensitivity;
-      int trainingSensitivity;
-      int learningRate;
-      int trainingLearningRate;
-      int trainingSteps;
-
-//      int frameCounter; //
-//      std::string inputPath;
-////      std::string centerFile;
-//      short flagWrite;
-//      short writeDbgPic;
-//      std::string outputPath;
-
-    public:
-      Tapter();
-      ~Tapter();
-
-      void setInitialFrameCounter(int counter);
-
-//      void setPaths(std::string inPath,std::string outPath);
-      void setPathOut(std::string outPath);
-
-//      //! 1 is on
-//      //! other no write
-//      void setFlagWrite(short flag);
-
-//      //! set learning rate
-//      void setLearningRate(int rate);
-
-//      //! 1 is on
-//      //! other no write
-//      void setFlagWriteDBGpic(short flag);
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-
-
-    };
-  }
-}
diff --git a/package_bgs/TwoPoints.cpp b/package_bgs/TwoPoints.cpp
deleted file mode 100644
index aee46848fd6b87082b0d42bb2bd4849aca319b9b..0000000000000000000000000000000000000000
--- a/package_bgs/TwoPoints.cpp
+++ /dev/null
@@ -1,112 +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 "TwoPoints.h"
-
-using namespace bgslibrary::algorithms;
-
-TwoPoints::TwoPoints() :
-  matchingThreshold(DEFAULT_MATCH_THRESH),
-  updateFactor(DEFAULT_UPDATE_FACTOR), model(nullptr)
-{
-  std::cout << "TwoPoints()" << std::endl;
-  //model = static_cast<twopointsModel_t*>(libtwopointsModel_New());
-  model = libtwopointsModel_New();
-  setup("./config/TwoPoints.xml");
-}
-
-TwoPoints::~TwoPoints()
-{
-  std::cout << "~TwoPoints()" << std::endl;
-  libtwopointsModel_Free(model);
-}
-
-void TwoPoints::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_input.empty())
-    return;
-
-  cv::Mat updatingMask;
-  cv::Mat img_input_grayscale;
-
-  // Convert input image to a grayscale image
-  cvtColor(img_input, img_input_grayscale, CV_BGR2GRAY);
-
-  if (firstTime)
-  {
-    // Create a buffer for the output image.
-    //img_output = Mat(img_input.rows, img_input.cols, CV_8UC1);
-
-    // Initialization of the ViBe model.
-    libtwopointsModel_AllocInit_8u_C1R(model, img_input_grayscale.data, img_input.cols, img_input.rows);
-
-    // Sets default model values.
-    // libvibeModel_Sequential_SetMatchingThreshold(model, matchingThreshold);
-    // libvibeModel_Sequential_SetUpdateFactor(model, updateFactor);
-  }
-
-  libtwopointsModel_Segmentation_8u_C1R(model, img_input_grayscale.data, img_output.data);
-
-  updatingMask = cv::Mat(img_input.rows, img_input.cols, CV_8UC1);
-  // Work on the output and define the updating mask
-  for (int i = 0; i < img_input.cols * img_input.rows; i++)
-  {
-    if (img_output.data[i] == 0) // Foreground pixel
-    {
-      updatingMask.data[i] = 0;
-      img_output.data[i] = 255;
-    }
-    else // Background
-    {
-      updatingMask.data[i] = 255;
-      img_output.data[i] = 0;
-    }
-  }
-
-  libtwopointsModel_Update_8u_C1R(model, img_input_grayscale.data, updatingMask.data);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    imshow("Two points", img_output);
-#endif
-
-  firstTime = false;
-}
-
-void TwoPoints::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "matchingThreshold", matchingThreshold);
-  cvWriteInt(fs, "updateFactor", updateFactor);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void TwoPoints::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  matchingThreshold = cvReadRealByName(fs, nullptr, "matchingThreshold", DEFAULT_MATCH_THRESH);
-  updateFactor = cvReadRealByName(fs, nullptr, "updateFactor", DEFAULT_UPDATE_FACTOR);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", false);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/TwoPoints.h b/package_bgs/TwoPoints.h
deleted file mode 100644
index b42c2311a09c07d7ef3c4146f7c2cccc65769742..0000000000000000000000000000000000000000
--- a/package_bgs/TwoPoints.h
+++ /dev/null
@@ -1,46 +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
-
-#include "IBGS.h"
-#include "TwoPoints/two_points.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class TwoPoints : public IBGS
-    {
-    private:
-      static const int DEFAULT_MATCH_THRESH = 20;
-      static const int DEFAULT_UPDATE_FACTOR = 16;
-      int matchingThreshold;
-      int updateFactor;
-      twopointsModel_t* model;
-
-    public:
-      TwoPoints();
-      ~TwoPoints();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/TwoPoints/two_points.cpp b/package_bgs/TwoPoints/two_points.cpp
deleted file mode 100644
index d8ee86b49c7c21c82c8b47b018caff354a389d13..0000000000000000000000000000000000000000
--- a/package_bgs/TwoPoints/two_points.cpp
+++ /dev/null
@@ -1,394 +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 <assert.h>
-
-#include "two_points.h"
-
-static unsigned int abs_uint(const int i)
-{
-  return (i >= 0) ? i : -i;
-}
-
-struct twopointsModel
-{
-  /* Parameters. */
-  uint32_t width;
-  uint32_t height;
-  uint32_t numberOfSamples;
-  uint32_t matchingThreshold;
-  uint32_t matchingNumber;
-  uint32_t updateFactor;
-
-  /* Storage for the history. */
-  uint8_t *historyImage1;
-  uint8_t *historyImage2;
-
-  /* Buffers with random values. */
-  uint32_t *jump;
-  int *neighbor;
-};
-
-// -----------------------------------------------------------------------------
-// Creates the data structure
-// -----------------------------------------------------------------------------
-twopointsModel_t *libtwopointsModel_New()
-{
-  /* Model structure alloc. */
-  twopointsModel_t *model = NULL;
-  model = (twopointsModel_t*)calloc(1, sizeof(*model));
-  assert(model != NULL);
-
-  /* Default parameters values. */
-  model->matchingThreshold = 20;
-  model->updateFactor = 16;
-
-  /* Storage for the history. */
-  model->historyImage1 = NULL;
-  model->historyImage2 = NULL;
-
-  /* Buffers with random values. */
-  model->jump = NULL;
-  model->neighbor = NULL;
-
-  return(model);
-}
-
-// ----------------------------------------------------------------------------
-// Frees the structure
-// ----------------------------------------------------------------------------
-int32_t libtwopointsModel_Free(twopointsModel_t *model)
-{
-  if (model == NULL)
-    return(-1);
-
-  if (model->historyImage1 != NULL) {
-    free(model->historyImage1);
-    model->historyImage1 = NULL;
-  }
-  if (model->historyImage2 != NULL) {
-    free(model->historyImage2);
-    model->historyImage2 = NULL;
-  }
-  if (model->jump != NULL) {
-    free(model->jump);
-    model->jump = NULL;
-  }
-  if (model->neighbor != NULL) {
-    free(model->neighbor);
-    model->neighbor = NULL;
-  }
-  free(model);
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Allocates and initializes a C1R model structure
-// -----------------------------------------------------------------------------
-int32_t libtwopointsModel_AllocInit_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-)
-{
-  // Some basic checks. */
-  assert((image_data != NULL) && (model != NULL));
-  assert((width > 0) && (height > 0));
-
-  /* Finish model alloc - parameters values cannot be changed anymore. */
-  model->width = width;
-  model->height = height;
-
-  /* Creates the historyImage structure. */
-  model->historyImage1 = NULL;
-  model->historyImage1 = (uint8_t*)malloc(width * height * sizeof(uint8_t));
-  model->historyImage2 = NULL;
-  model->historyImage2 = (uint8_t*)malloc(width * height * sizeof(uint8_t));
-
-  assert(model->historyImage1 != NULL);
-  assert(model->historyImage2 != NULL);
-
-  for (int index = width * height - 1; index >= 0; --index) {
-    uint8_t value = image_data[index];
-
-    int value_plus_noise = value - 10;
-    if (value_plus_noise < 0) { value_plus_noise = 0; }
-    if (value_plus_noise > 255) { value_plus_noise = 255; }
-    model->historyImage1[index] = value_plus_noise;
-
-    value_plus_noise = value + 10;
-    if (value_plus_noise < 0) { value_plus_noise = 0; }
-    if (value_plus_noise > 255) { value_plus_noise = 255; }
-    model->historyImage2[index] = value_plus_noise;
-
-    // Swaps the two values if needed
-    if (model->historyImage1[index] > model->historyImage2[index]) {
-      uint8_t val = model->historyImage1[index];
-      model->historyImage1[index] = model->historyImage2[index];
-      model->historyImage2[index] = val;
-    }
-  }
-
-  /* Fills the buffers with random values. */
-  int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
-
-  model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
-  assert(model->jump != NULL);
-
-  model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
-  assert(model->neighbor != NULL);
-
-
-  for (int i = 0; i < size; ++i) {
-    model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
-    model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { -width - 1, ... , width + 1 }.
-  }
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Segmentation of a C1R model
-// -----------------------------------------------------------------------------
-int32_t libtwopointsModel_Segmentation_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-)
-{
-  assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert((model->jump != NULL) && (model->neighbor != NULL));
-
-  /* Some variables. */
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-  uint32_t matchingThreshold = model->matchingThreshold;
-
-  uint8_t *historyImage1 = model->historyImage1;
-  uint8_t *historyImage2 = model->historyImage2;
-
-  /* Segmentation. */
-  memset(segmentation_map, 0, width * height);
-
-  uint8_t *first = historyImage1;
-  for (int index = width * height - 1; index >= 0; --index) {
-    // We adapt the threshold
-    matchingThreshold = model->matchingThreshold;
-    if (matchingThreshold < abs_uint(historyImage2[index] - historyImage1[index])) {
-      matchingThreshold = abs_uint(historyImage2[index] - historyImage1[index]);
-    }
-    if (abs_uint(image_data[index] - first[index]) <= matchingThreshold)
-      segmentation_map[index]++;
-  }
-
-  first = historyImage2;
-  for (int index = width * height - 1; index >= 0; --index) {
-    // We adapt the threshold
-    matchingThreshold = model->matchingThreshold;
-    if (matchingThreshold < abs_uint(historyImage2[index] - historyImage1[index])) {
-      matchingThreshold = abs_uint(historyImage2[index] - historyImage1[index]);
-    }
-    if (abs_uint(image_data[index] - first[index]) <= matchingThreshold)
-      segmentation_map[index]++;
-  }
-
-  return(0);
-}
-
-// ----------------------------------------------------------------------------
-// Update a C1R model
-// ----------------------------------------------------------------------------
-int doUpdate(const uint8_t value)
-{
-  if (value == 0) return 0;
-  else return 1;
-}
-
-
-int32_t libtwopointsModel_Update_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-)
-{
-  assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert((model->jump != NULL) && (model->neighbor != NULL));
-
-  // Some variables.
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-
-  uint8_t *historyImage1 = model->historyImage1;
-  uint8_t *historyImage2 = model->historyImage2;
-
-  // Updating.
-  uint32_t *jump = model->jump;
-  int *neighbor = model->neighbor;
-
-  // All the frame, except the border.
-  uint32_t shift, indX, indY;
-  unsigned int x, y;
-
-  for (y = 1; y < height - 1; ++y) {
-    shift = rand() % width;
-    indX = jump[shift]; // index_jump should never be zero (> 1).
-
-    while (indX < width - 1) {
-      int index = indX + y * width;
-
-      if (doUpdate(updating_mask[index])) {
-        uint8_t value = image_data[index];
-        // In-place substitution.
-        // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
-        if (rand() % 2 == 0) {
-          historyImage1[index] = value;
-        }
-        else {
-          historyImage2[index] = value;
-        }
-
-        // Propagation
-        int index_neighbor = index + neighbor[shift];
-        if (2 * value < (historyImage1[index_neighbor] + historyImage2[index_neighbor])) {
-          // if (rand()%2 == 0 ) {
-          historyImage1[index_neighbor] = value;
-        }
-        else {
-          historyImage2[index_neighbor] = value;
-        }
-      }
-
-      ++shift;
-      indX += jump[shift];
-    }
-  }
-
-  // First row.
-  y = 0;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    if (doUpdate(updating_mask[index])) {
-      uint8_t value = image_data[index];
-      // In-place substitution.
-      // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
-      if (rand() % 2 == 0) {
-        historyImage1[index] = value;
-      }
-      else {
-        historyImage2[index] = value;
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  // Last row.
-  y = height - 1;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    if (doUpdate(updating_mask[index])) {
-      uint8_t value = image_data[index];
-      // In-place substitution.
-      // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
-      if (rand() % 2 == 0) {
-        historyImage1[index] = value;
-      }
-      else {
-        historyImage2[index] = value;
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  // First column.
-  x = 0;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    if (doUpdate(updating_mask[index])) {
-      uint8_t value = image_data[index];
-      // In-place substitution.
-      // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
-      if (rand() % 2 == 0) {
-        historyImage1[index] = value;
-      }
-      else {
-        historyImage2[index] = value;
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  // Last column.
-  x = width - 1;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    if (doUpdate(updating_mask[index])) {
-      uint8_t value = image_data[index];
-      // In-place substitution.
-      // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
-      if (rand() % 2 == 0) {
-        historyImage1[index] = value;
-      }
-      else {
-        historyImage2[index] = value;
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  // The first pixel!
-  if (rand() % model->updateFactor == 0) {
-    if (doUpdate(updating_mask[0])) {
-      uint8_t value = image_data[0];
-      // In-place substitution.
-      if (rand() % 2 == 0) {
-        historyImage1[0] = value;
-      }
-      else {
-        historyImage2[0] = value;
-      }
-    }
-  }
-
-  return(0);
-}
diff --git a/package_bgs/TwoPoints/two_points.h b/package_bgs/TwoPoints/two_points.h
deleted file mode 100644
index a64152a2b6ca84857775ffd68c64461ab1fbe940..0000000000000000000000000000000000000000
--- a/package_bgs/TwoPoints/two_points.h
+++ /dev/null
@@ -1,50 +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
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#define COLOR_BACKGROUND   0 /*!< Default label for background pixels */
-#define COLOR_FOREGROUND 255 /*!< Default label for foreground pixels. Note that some authors chose any value different from 0 instead */
-
-typedef struct twopointsModel twopointsModel_t;
-
-twopointsModel_t *libtwopointsModel_New();
-
-int32_t libtwopointsModel_Free(twopointsModel_t *model);
-
-int32_t libtwopointsModel_AllocInit_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-);
-
-int32_t libtwopointsModel_Segmentation_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-);
-
-int32_t libtwopointsModel_Update_8u_C1R(
-  twopointsModel_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-);
diff --git a/package_bgs/ViBe.cpp b/package_bgs/ViBe.cpp
deleted file mode 100644
index 0d3125f0759d14cc00a608350f97e8883e8a8c22..0000000000000000000000000000000000000000
--- a/package_bgs/ViBe.cpp
+++ /dev/null
@@ -1,98 +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 "ViBe.h"
-
-using namespace bgslibrary::algorithms;
-
-ViBe::ViBe() :
-  //numberOfSamples(DEFAULT_NUM_SAMPLES),
-  matchingThreshold(DEFAULT_MATCH_THRESH),
-  matchingNumber(DEFAULT_MATCH_NUM),
-  updateFactor(DEFAULT_UPDATE_FACTOR),
-  model(nullptr)
-{
-  std::cout << "ViBe()" << std::endl;
-  model = libvibeModel_Sequential_New();
-  setup("./config/ViBe.xml");
-}
-
-ViBe::~ViBe()
-{
-  std::cout << "~ViBe()" << std::endl;
-  libvibeModel_Sequential_Free(model);
-}
-
-void ViBe::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_input.empty())
-    return;
-
-  if (firstTime)
-  {
-    /* Create a buffer for the output image. */
-    //img_output = cv::Mat(img_input.rows, img_input.cols, CV_8UC1);
-
-    /* Initialization of the ViBe model. */
-    libvibeModel_Sequential_AllocInit_8u_C3R(model, img_input.data, img_input.cols, img_input.rows);
-
-    /* Sets default model values. */
-    //libvibeModel_Sequential_SetNumberOfSamples(model, numberOfSamples);
-    libvibeModel_Sequential_SetMatchingThreshold(model, matchingThreshold);
-    libvibeModel_Sequential_SetMatchingNumber(model, matchingNumber);
-    libvibeModel_Sequential_SetUpdateFactor(model, updateFactor);
-  }
-
-  libvibeModel_Sequential_Segmentation_8u_C3R(model, img_input.data, img_output.data);
-  //libvibeModel_Sequential_Update_8u_C3R(model, model_img_input.data, img_output.data);
-  libvibeModel_Sequential_Update_8u_C3R(model, img_input.data, img_output.data);
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    imshow("ViBe", img_output);
-#endif
-
-  firstTime = false;
-}
-
-void ViBe::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  //cvWriteInt(fs, "numberOfSamples", numberOfSamples);
-  cvWriteInt(fs, "matchingThreshold", matchingThreshold);
-  cvWriteInt(fs, "matchingNumber", matchingNumber);
-  cvWriteInt(fs, "updateFactor", updateFactor);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void ViBe::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  //numberOfSamples = cvReadIntByName(fs, nullptr, "numberOfSamples", DEFAULT_NUM_SAMPLES);
-  matchingThreshold = cvReadRealByName(fs, nullptr, "matchingThreshold", DEFAULT_MATCH_THRESH);
-  matchingNumber = cvReadRealByName(fs, nullptr, "matchingNumber", DEFAULT_MATCH_NUM);
-  updateFactor = cvReadRealByName(fs, nullptr, "updateFactor", DEFAULT_UPDATE_FACTOR);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", false);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/ViBe.h b/package_bgs/ViBe.h
deleted file mode 100644
index c8014cbc15b99175947ed1115f3bd8b4144249d4..0000000000000000000000000000000000000000
--- a/package_bgs/ViBe.h
+++ /dev/null
@@ -1,52 +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
-
-#include "IBGS.h"
-#include "ViBe/vibe-background-sequential.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class ViBe : public IBGS
-    {
-    private:
-      static const int DEFAULT_NUM_SAMPLES = 20;
-      static const int DEFAULT_MATCH_THRESH = 20;
-      static const int DEFAULT_MATCH_NUM = 2;
-      static const int DEFAULT_UPDATE_FACTOR = 16;
-
-    private:
-      //int numberOfSamples;
-      int matchingThreshold;
-      int matchingNumber;
-      int updateFactor;
-      vibeModel_Sequential_t* model;
-
-    public:
-      ViBe();
-      ~ViBe();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/ViBe/vibe-background-sequential.cpp b/package_bgs/ViBe/vibe-background-sequential.cpp
deleted file mode 100644
index c4b91781d4662220f54eec84a6d74b1669d94ce7..0000000000000000000000000000000000000000
--- a/package_bgs/ViBe/vibe-background-sequential.cpp
+++ /dev/null
@@ -1,929 +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/>.
-*/
-/**
-@file vibe-background-sequential.c
-@brief Implementation of vibe-background-sequential.h
-@author Marc Van Droogenbroeck
-@date May 2014
-*/
-#include <assert.h>
-#include <time.h>
-
-#include "vibe-background-sequential.h"
-
-#define NUMBER_OF_HISTORY_IMAGES 2
-
-uint32_t distance_Han2014Improved(uint8_t pixel, uint8_t bg)
-{
-  uint8_t min, max;
-
-  // Computes R = 0.13 min{ max[bg,26], 230}
-  max = 26;
-  if (bg > max) { max = bg; }
-
-  min = 230;
-  if (min > max) { min = max; }
-
-  return (uint32_t)(0.13*min);
-}
-
-static int abs_uint(const int i)
-{
-  return (i >= 0) ? i : -i;
-}
-
-static int32_t distance_is_close_8u_C3R(uint8_t r1, uint8_t g1, uint8_t b1, uint8_t r2, uint8_t g2, uint8_t b2, uint32_t threshold)
-{
-  return (abs_uint(r1 - r2) + abs_uint(g1 - g2) + abs_uint(b1 - b2) <= 4.5 * threshold);
-}
-
-struct vibeModel_Sequential
-{
-  /* Parameters. */
-  uint32_t width;
-  uint32_t height;
-  uint32_t numberOfSamples;
-  uint32_t matchingThreshold;
-  uint32_t matchingNumber;
-  uint32_t updateFactor;
-
-  /* Storage for the history. */
-  uint8_t *historyImage;
-  uint8_t *historyBuffer;
-  uint32_t lastHistoryImageSwapped;
-
-  /* Buffers with random values. */
-  uint32_t *jump;
-  int *neighbor;
-  uint32_t *position;
-};
-
-// -----------------------------------------------------------------------------
-// Print parameters
-// -----------------------------------------------------------------------------
-uint32_t libvibeModel_Sequential_PrintParameters(const vibeModel_Sequential_t *model)
-{
-  printf(
-    "Using ViBe background subtraction algorithm\n"
-    "  - Number of samples per pixel:       %03d\n"
-    "  - Number of matches needed:          %03d\n"
-    "  - Matching threshold:                %03d\n"
-    "  - Model update subsampling factor:   %03d\n",
-    libvibeModel_Sequential_GetNumberOfSamples(model),
-    libvibeModel_Sequential_GetMatchingNumber(model),
-    libvibeModel_Sequential_GetMatchingThreshold(model),
-    libvibeModel_Sequential_GetUpdateFactor(model)
-  );
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Creates the data structure
-// -----------------------------------------------------------------------------
-vibeModel_Sequential_t *libvibeModel_Sequential_New()
-{
-  /* Model structure alloc. */
-  vibeModel_Sequential_t *model = NULL;
-  model = (vibeModel_Sequential_t*)calloc(1, sizeof(*model));
-  assert(model != NULL);
-
-  /* Default parameters values. */
-  model->numberOfSamples = 20;
-  model->matchingThreshold = 20;
-  model->matchingNumber = 2;
-  model->updateFactor = 16;
-
-  /* Storage for the history. */
-  model->historyImage = NULL;
-  model->historyBuffer = NULL;
-  model->lastHistoryImageSwapped = 0;
-
-  /* Buffers with random values. */
-  model->jump = NULL;
-  model->neighbor = NULL;
-  model->position = NULL;
-
-  return(model);
-}
-
-// -----------------------------------------------------------------------------
-// Some "Get-ers"
-// -----------------------------------------------------------------------------
-uint32_t libvibeModel_Sequential_GetNumberOfSamples(const vibeModel_Sequential_t *model)
-{
-  assert(model != NULL); return(model->numberOfSamples);
-}
-
-uint32_t libvibeModel_Sequential_GetMatchingNumber(const vibeModel_Sequential_t *model)
-{
-  assert(model != NULL); return(model->matchingNumber);
-}
-
-uint32_t libvibeModel_Sequential_GetMatchingThreshold(const vibeModel_Sequential_t *model)
-{
-  assert(model != NULL); return(model->matchingThreshold);
-}
-
-uint32_t libvibeModel_Sequential_GetUpdateFactor(const vibeModel_Sequential_t *model)
-{
-  assert(model != NULL); return(model->updateFactor);
-}
-
-// -----------------------------------------------------------------------------
-// Some "Set-ers"
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_SetMatchingThreshold(
-  vibeModel_Sequential_t *model,
-  const uint32_t matchingThreshold
-) {
-  assert(model != NULL);
-  assert(matchingThreshold > 0);
-
-  model->matchingThreshold = matchingThreshold;
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_SetMatchingNumber(
-  vibeModel_Sequential_t *model,
-  const uint32_t matchingNumber
-) {
-  assert(model != NULL);
-  assert(matchingNumber > 0);
-
-  model->matchingNumber = matchingNumber;
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_SetUpdateFactor(
-  vibeModel_Sequential_t *model,
-  const uint32_t updateFactor
-) {
-  assert(model != NULL);
-  assert(updateFactor > 0);
-
-  model->updateFactor = updateFactor;
-
-  /* We also need to change the values of the jump buffer ! */
-  assert(model->jump != NULL);
-
-  /* Shifts. */
-  int size = (model->width > model->height) ? 2 * model->width + 1 : 2 * model->height + 1;
-
-  for (int i = 0; i < size; ++i)
-    model->jump[i] = (updateFactor == 1) ? 1 : (rand() % (2 * model->updateFactor)) + 1; // 1 or values between 1 and 2 * updateFactor.
-
-  return(0);
-}
-
-// ----------------------------------------------------------------------------
-// Frees the structure
-// ----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_Free(vibeModel_Sequential_t *model)
-{
-  if (model == NULL)
-    return(-1);
-
-  if (model->historyBuffer == NULL) {
-    free(model);
-    return(0);
-  }
-
-  free(model->historyImage);
-  free(model->historyBuffer);
-  free(model->jump);
-  free(model->neighbor);
-  free(model->position);
-  free(model);
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Allocates and initializes a C1R model structure
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_AllocInit_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-) {
-  // Some basic checks. */
-  assert((image_data != NULL) && (model != NULL));
-  assert((width > 0) && (height > 0));
-
-  /* Finish model alloc - parameters values cannot be changed anymore. */
-  model->width = width;
-  model->height = height;
-
-  /* Creates the historyImage structure. */
-  model->historyImage = NULL;
-  model->historyImage = (uint8_t*)malloc(NUMBER_OF_HISTORY_IMAGES * width * height * sizeof(*(model->historyImage)));
-
-  assert(model->historyImage != NULL);
-
-  for (int i = 0; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
-    for (int index = width * height - 1; index >= 0; --index)
-      model->historyImage[i * width * height + index] = image_data[index];
-  }
-
-  /* Now creates and fills the history buffer. */
-  model->historyBuffer = (uint8_t*)malloc(width * height * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) * sizeof(uint8_t));
-  assert(model->historyBuffer != NULL);
-
-  for (int index = width * height - 1; index >= 0; --index) {
-    uint8_t value = image_data[index];
-
-    for (int x = 0; x < model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES; ++x) {
-      int value_plus_noise = value + rand() % 20 - 10;
-
-      if (value_plus_noise < 0) { value_plus_noise = 0; }
-      if (value_plus_noise > 255) { value_plus_noise = 255; }
-
-      model->historyBuffer[index * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) + x] = value_plus_noise;
-    }
-  }
-
-  /* Fills the buffers with random values. */
-  int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
-
-  model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
-  assert(model->jump != NULL);
-
-  model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
-  assert(model->neighbor != NULL);
-
-  model->position = (uint32_t*)malloc(size * sizeof(*(model->position)));
-  assert(model->position != NULL);
-
-  for (int i = 0; i < size; ++i) {
-    model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
-    model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { -width - 1, ... , width + 1 }.
-    model->position[i] = rand() % (model->numberOfSamples);               // Values between 0 and numberOfSamples - 1.
-  }
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Segmentation of a C1R model
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_Segmentation_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-) {
-  /* Basic checks. */
-  assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert(model->historyBuffer != NULL);
-  assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
-
-  /* Some variables. */
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-  uint32_t matchingNumber = model->matchingNumber;
-  uint32_t matchingThreshold = model->matchingThreshold;
-
-  uint8_t *historyImage = model->historyImage;
-  uint8_t *historyBuffer = model->historyBuffer;
-
-  /* Segmentation. */
-  memset(segmentation_map, matchingNumber - 1, width * height);
-
-  /* First history Image structure. */
-  for (int index = width * height - 1; index >= 0; --index) {
-    //if (abs_uint(image_data[index] - historyImage[index]) > matchingThreshold)
-    if (abs_uint(image_data[index] - historyImage[index]) > distance_Han2014Improved(image_data[index], historyImage[index]))
-      segmentation_map[index] = matchingNumber;
-  }
-
-  /* Next historyImages. */
-  for (int i = 1; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
-    uint8_t *pels = historyImage + i * width * height;
-
-    for (int index = width * height - 1; index >= 0; --index) {
-      // if (abs_uint(image_data[index] - pels[index]) <= matchingThreshold)
-      if (abs_uint(image_data[index] - pels[index]) <= distance_Han2014Improved(image_data[index], pels[index]))
-        --segmentation_map[index];
-    }
-  }
-
-  /* For swapping. */
-  model->lastHistoryImageSwapped = (model->lastHistoryImageSwapped + 1) % NUMBER_OF_HISTORY_IMAGES;
-  uint8_t *swappingImageBuffer = historyImage + (model->lastHistoryImageSwapped) * width * height;
-
-  /* Now, we move in the buffer and leave the historyImages. */
-  int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
-
-  for (int index = width * height - 1; index >= 0; --index) {
-    if (segmentation_map[index] > 0) {
-      /* We need to check the full border and swap values with the first or second historyImage.
-       * We still need to find a match before we can stop our search.
-       */
-      uint32_t indexHistoryBuffer = index * numberOfTests;
-      uint8_t currentValue = image_data[index];
-
-      for (int i = numberOfTests; i > 0; --i, ++indexHistoryBuffer) {
-        // if (abs_uint(currentValue - historyBuffer[indexHistoryBuffer]) <= matchingThreshold) {
-        if (abs_uint(currentValue - historyBuffer[indexHistoryBuffer]) <= distance_Han2014Improved(currentValue, historyBuffer[indexHistoryBuffer])) {
-          --segmentation_map[index];
-
-          /* Swaping: Putting found value in history image buffer. */
-          uint8_t temp = swappingImageBuffer[index];
-          swappingImageBuffer[index] = historyBuffer[indexHistoryBuffer];
-          historyBuffer[indexHistoryBuffer] = temp;
-
-          /* Exit inner loop. */
-          if (segmentation_map[index] <= 0) break;
-        }
-      } // for
-    } // if
-  } // for
-
-  /* Produces the output. Note that this step is application-dependent. */
-  for (uint8_t *mask = segmentation_map; mask < segmentation_map + (width * height); ++mask)
-    if (*mask > 0) *mask = COLOR_FOREGROUND;
-
-  return(0);
-}
-
-// ----------------------------------------------------------------------------
-// Update a C1R model
-// ----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_Update_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-) {
-  /* Basic checks . */
-  assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert(model->historyBuffer != NULL);
-  assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
-
-  /* Some variables. */
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-
-  uint8_t *historyImage = model->historyImage;
-  uint8_t *historyBuffer = model->historyBuffer;
-
-  /* Some utility variable. */
-  int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
-
-  /* Updating. */
-  uint32_t *jump = model->jump;
-  int *neighbor = model->neighbor;
-  uint32_t *position = model->position;
-
-  /* All the frame, except the border. */
-  uint32_t shift, indX, indY;
-  int x, y;
-
-  for (y = 1; y < height - 1; ++y) {
-    shift = rand() % width;
-    indX = jump[shift]; // index_jump should never be zero (> 1).
-
-    while (indX < width - 1) {
-      int index = indX + y * width;
-
-      if (updating_mask[index] == COLOR_BACKGROUND) {
-        /* In-place substitution. */
-        uint8_t value = image_data[index];
-        int index_neighbor = index + neighbor[shift];
-
-        if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-          historyImage[index + position[shift] * width * height] = value;
-          historyImage[index_neighbor + position[shift] * width * height] = value;
-        }
-        else {
-          int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-          historyBuffer[index * numberOfTests + pos] = value;
-          historyBuffer[index_neighbor * numberOfTests + pos] = value;
-        }
-      }
-
-      ++shift;
-      indX += jump[shift];
-    }
-  }
-
-  /* First row. */
-  y = 0;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
-        historyImage[index + position[shift] * width * height] = image_data[index];
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[index * numberOfTests + pos] = image_data[index];
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  /* Last row. */
-  y = height - 1;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
-        historyImage[index + position[shift] * width * height] = image_data[index];
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[index * numberOfTests + pos] = image_data[index];
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  /* First column. */
-  x = 0;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
-        historyImage[index + position[shift] * width * height] = image_data[index];
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[index * numberOfTests + pos] = image_data[index];
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  /* Last column. */
-  x = width - 1;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
-        historyImage[index + position[shift] * width * height] = image_data[index];
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[index * numberOfTests + pos] = image_data[index];
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  /* The first pixel! */
-  if (rand() % model->updateFactor == 0) {
-    if (updating_mask[0] == 0) {
-      int position = rand() % model->numberOfSamples;
-
-      if (position < NUMBER_OF_HISTORY_IMAGES)
-        historyImage[position * width * height] = image_data[0];
-      else {
-        int pos = position - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[pos] = image_data[0];
-      }
-    }
-  }
-
-  return(0);
-}
-
-// ----------------------------------------------------------------------------
-// -------------------------- The same for C3R models -------------------------
-// ----------------------------------------------------------------------------
-
-// -----------------------------------------------------------------------------
-// Allocates and initializes a C3R model structure
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_AllocInit_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-) {
-  /* Some basic checks. */
-  assert((image_data != NULL) && (model != NULL));
-  assert((width > 0) && (height > 0));
-
-  /* Finish model alloc - parameters values cannot be changed anymore. */
-  model->width = width;
-  model->height = height;
-
-  /* Creates the historyImage structure. */
-  model->historyImage = NULL;
-  model->historyImage = (uint8_t*)malloc(NUMBER_OF_HISTORY_IMAGES * (3 * width) * height * sizeof(uint8_t));
-  assert(model->historyImage != NULL);
-
-  for (int i = 0; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
-    for (int index = (3 * width) * height - 1; index >= 0; --index)
-      model->historyImage[i * (3 * width) * height + index] = image_data[index];
-  }
-
-  assert(model->historyImage != NULL);
-
-  /* Now creates and fills the history buffer. */
-  model->historyBuffer = (uint8_t *)malloc((3 * width) * height * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) * sizeof(uint8_t));
-  assert(model->historyBuffer != NULL);
-
-  for (int index = (3 * width) * height - 1; index >= 0; --index) {
-    uint8_t value = image_data[index];
-
-    for (int x = 0; x < model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES; ++x) {
-      int value_plus_noise = value + rand() % 20 - 10;
-
-      if (value_plus_noise < 0) { value_plus_noise = 0; }
-      if (value_plus_noise > 255) { value_plus_noise = 255; }
-
-      model->historyBuffer[index * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) + x] = value_plus_noise;
-    }
-  }
-
-  /* Fills the buffers with random values. */
-  int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
-
-  model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
-  assert(model->jump != NULL);
-
-  model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
-  assert(model->neighbor != NULL);
-
-  model->position = (uint32_t*)malloc(size * sizeof(*(model->position)));
-  assert(model->position != NULL);
-
-  for (int i = 0; i < size; ++i) {
-    model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
-    model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { width - 1, ... , width + 1 }.
-    model->position[i] = rand() % (model->numberOfSamples);               // Values between 0 and numberOfSamples - 1.
-  }
-
-  return(0);
-}
-
-// -----------------------------------------------------------------------------
-// Segmentation of a C3R model
-// -----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_Segmentation_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-) {
-  /* Basic checks. */
-  assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert(model->historyBuffer != NULL);
-  assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
-
-  /* Some variables. */
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-  uint32_t matchingNumber = model->matchingNumber;
-  uint32_t matchingThreshold = model->matchingThreshold;
-
-  uint8_t *historyImage = model->historyImage;
-  uint8_t *historyBuffer = model->historyBuffer;
-
-  /* Segmentation. */
-  memset(segmentation_map, matchingNumber - 1, width * height);
-
-  /* First history Image structure. */
-  uint8_t *first = historyImage;
-
-  for (int index = width * height - 1; index >= 0; --index) {
-    if (
-      !distance_is_close_8u_C3R(
-        image_data[3 * index], image_data[3 * index + 1], image_data[3 * index + 2],
-        first[3 * index], first[3 * index + 1], first[3 * index + 2], matchingThreshold
-      )
-      )
-      segmentation_map[index] = matchingNumber;
-  }
-
-  /* Next historyImages. */
-  for (int i = 1; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
-    uint8_t *pels = historyImage + i * (3 * width) * height;
-
-    for (int index = width * height - 1; index >= 0; --index) {
-      if (
-        distance_is_close_8u_C3R(
-          image_data[3 * index], image_data[3 * index + 1], image_data[3 * index + 2],
-          pels[3 * index], pels[3 * index + 1], pels[3 * index + 2], matchingThreshold
-        )
-        )
-        --segmentation_map[index];
-    }
-  }
-
-  // For swapping
-  model->lastHistoryImageSwapped = (model->lastHistoryImageSwapped + 1) % NUMBER_OF_HISTORY_IMAGES;
-  uint8_t *swappingImageBuffer = historyImage + (model->lastHistoryImageSwapped) * (3 * width) * height;
-
-  // Now, we move in the buffer and leave the historyImages
-  int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
-
-  for (int index = width * height - 1; index >= 0; --index) {
-    if (segmentation_map[index] > 0) {
-      /* We need to check the full border and swap values with the first or second historyImage.
-       * We still need to find a match before we can stop our search.
-       */
-      uint32_t indexHistoryBuffer = (3 * index) * numberOfTests;
-
-      for (int i = numberOfTests; i > 0; --i, indexHistoryBuffer += 3) {
-        if (
-          distance_is_close_8u_C3R(
-            image_data[(3 * index)], image_data[(3 * index) + 1], image_data[(3 * index) + 2],
-            historyBuffer[indexHistoryBuffer], historyBuffer[indexHistoryBuffer + 1], historyBuffer[indexHistoryBuffer + 2],
-            matchingThreshold
-          )
-          )
-          --segmentation_map[index];
-
-        /* Swaping: Putting found value in history image buffer. */
-        uint8_t temp_r = swappingImageBuffer[(3 * index)];
-        uint8_t temp_g = swappingImageBuffer[(3 * index) + 1];
-        uint8_t temp_b = swappingImageBuffer[(3 * index) + 2];
-
-        swappingImageBuffer[(3 * index)] = historyBuffer[indexHistoryBuffer];
-        swappingImageBuffer[(3 * index) + 1] = historyBuffer[indexHistoryBuffer + 1];
-        swappingImageBuffer[(3 * index) + 2] = historyBuffer[indexHistoryBuffer + 2];
-
-        historyBuffer[indexHistoryBuffer] = temp_r;
-        historyBuffer[indexHistoryBuffer + 1] = temp_g;
-        historyBuffer[indexHistoryBuffer + 2] = temp_b;
-
-        /* Exit inner loop. */
-        if (segmentation_map[index] <= 0) break;
-      } // for
-    } // if
-  } // for
-
-  /* Produces the output. Note that this step is application-dependent. */
-  for (uint8_t *mask = segmentation_map; mask < segmentation_map + (width * height); ++mask)
-    if (*mask > 0) *mask = COLOR_FOREGROUND;
-
-  return(0);
-}
-
-// ----------------------------------------------------------------------------
-// Update a C3R model
-// ----------------------------------------------------------------------------
-int32_t libvibeModel_Sequential_Update_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-) {
-  /* Basic checks. */
-  assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
-  assert((model->width > 0) && (model->height > 0));
-  assert(model->historyBuffer != NULL);
-  assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
-
-  /* Some variables. */
-  uint32_t width = model->width;
-  uint32_t height = model->height;
-
-  uint8_t *historyImage = model->historyImage;
-  uint8_t *historyBuffer = model->historyBuffer;
-
-  /* Some utility variable. */
-  int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
-
-  /* Updating. */
-  uint32_t *jump = model->jump;
-  int *neighbor = model->neighbor;
-  uint32_t *position = model->position;
-
-  /* All the frame, except the border. */
-  uint32_t shift, indX, indY;
-  int x, y;
-
-  for (y = 1; y < height - 1; ++y) {
-    shift = rand() % width;
-    indX = jump[shift]; // index_jump should never be zero (> 1).
-
-    while (indX < width - 1) {
-      int index = indX + y * width;
-
-      if (updating_mask[index] == COLOR_BACKGROUND) {
-        /* In-place substitution. */
-        uint8_t r = image_data[3 * index];
-        uint8_t g = image_data[3 * index + 1];
-        uint8_t b = image_data[3 * index + 2];
-
-        int index_neighbor = 3 * (index + neighbor[shift]);
-
-        if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-          historyImage[3 * index + position[shift] * (3 * width) * height] = r;
-          historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
-          historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
-
-          historyImage[index_neighbor + position[shift] * (3 * width) * height] = r;
-          historyImage[index_neighbor + position[shift] * (3 * width) * height + 1] = g;
-          historyImage[index_neighbor + position[shift] * (3 * width) * height + 2] = r;
-        }
-        else {
-          int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-
-          historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
-          historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
-          historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
-
-          historyBuffer[index_neighbor * numberOfTests + 3 * pos] = r;
-          historyBuffer[index_neighbor * numberOfTests + 3 * pos + 1] = g;
-          historyBuffer[index_neighbor * numberOfTests + 3 * pos + 2] = b;
-        }
-      }
-
-      ++shift;
-      indX += jump[shift];
-    }
-  }
-
-  /* First row. */
-  y = 0;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    uint8_t r = image_data[3 * index];
-    uint8_t g = image_data[3 * index + 1];
-    uint8_t b = image_data[3 * index + 2];
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-        historyImage[3 * index + position[shift] * (3 * width) * height] = r;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
-      }
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  /* Last row. */
-  y = height - 1;
-  shift = rand() % width;
-  indX = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indX <= width - 1) {
-    int index = indX + y * width;
-
-    uint8_t r = image_data[3 * index];
-    uint8_t g = image_data[3 * index + 1];
-    uint8_t b = image_data[3 * index + 2];
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-        historyImage[3 * index + position[shift] * (3 * width) * height] = r;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
-      }
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
-      }
-    }
-
-    ++shift;
-    indX += jump[shift];
-  }
-
-  /* First column. */
-  x = 0;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    uint8_t r = image_data[3 * index];
-    uint8_t g = image_data[3 * index + 1];
-    uint8_t b = image_data[3 * index + 2];
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-        historyImage[3 * index + position[shift] * (3 * width) * height] = r;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
-      }
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  /* Last column. */
-  x = width - 1;
-  shift = rand() % height;
-  indY = jump[shift]; // index_jump should never be zero (> 1).
-
-  while (indY <= height - 1) {
-    int index = x + indY * width;
-
-    uint8_t r = image_data[3 * index];
-    uint8_t g = image_data[3 * index + 1];
-    uint8_t b = image_data[3 * index + 2];
-
-    if (updating_mask[index] == COLOR_BACKGROUND) {
-      if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
-        historyImage[3 * index + position[shift] * (3 * width) * height] = r;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
-        historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
-      }
-      else {
-        int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
-
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
-        historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
-      }
-    }
-
-    ++shift;
-    indY += jump[shift];
-  }
-
-  /* The first pixel! */
-  if (rand() % model->updateFactor == 0) {
-    if (updating_mask[0] == 0) {
-      int position = rand() % model->numberOfSamples;
-
-      uint8_t r = image_data[0];
-      uint8_t g = image_data[1];
-      uint8_t b = image_data[2];
-
-      if (position < NUMBER_OF_HISTORY_IMAGES) {
-        historyImage[position * (3 * width) * height] = r;
-        historyImage[position * (3 * width) * height + 1] = g;
-        historyImage[position * (3 * width) * height + 2] = b;
-      }
-      else {
-        int pos = position - NUMBER_OF_HISTORY_IMAGES;
-
-        historyBuffer[3 * pos] = r;
-        historyBuffer[3 * pos + 1] = g;
-        historyBuffer[3 * pos + 2] = b;
-      }
-    }
-  }
-
-  return(0);
-}
diff --git a/package_bgs/ViBe/vibe-background-sequential.h b/package_bgs/ViBe/vibe-background-sequential.h
deleted file mode 100644
index 068c7d1b70365d88cb9931b8ce96e337ac0ca4f1..0000000000000000000000000000000000000000
--- a/package_bgs/ViBe/vibe-background-sequential.h
+++ /dev/null
@@ -1,293 +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/>.
-*/
-/**
-  @file vibe-background-sequential.h
-  @brief Interface for the ViBe library
-  @author Marc Van Droogenbroeck
-  @date July 2014
-  @details
-
-  Full documentation is available online at:
-     http://www.ulg.ac.be/telecom/research/vibe/doc
-
-  All technical details are available in the following paper:
-<em>O. Barnich and M. Van Droogenbroeck. ViBe: A universal background subtraction algorithm for video sequences. IEEE Transactions on Image Processing, 20(6):1709-1724, June 2011.</em>
-
-\verbatim
-BiBTeX information
-
-  @article{Barnich2011ViBe,
-  title = {{ViBe}: A universal background subtraction algorithm for video sequences},
-  author = {O. Barnich and M. {Van Droogenbroeck}},
-  journal = {IEEE Transactions on Image Processing},
-  volume = {20},
-  number = {6},
-  pages = {1709-1724},
-  month = {June},
-  year = {2011},
-  keywords = {ViBe, Background, Background subtraction, Segmentation, Motion, Motion detection},
-  pdf = {http://orbi.ulg.ac.be/bitstream/2268/145853/1/Barnich2011ViBe.pdf},
-  doi = {10.1109/TIP.2010.2101613},
-  url = {http://hdl.handle.net/2268/145853}
-  }
-\endverbatim
-See
-\cite Barnich2011ViBe
-*/
-#pragma once
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#define COLOR_BACKGROUND   0 /*!< Default label for background pixels */
-#define COLOR_FOREGROUND 255 /*!< Default label for foreground pixels. Note that some authors chose any value different from 0 instead */
-
-/**
- * \typedef struct vibeModel_Sequential_t
- * \brief Data structure for the background subtraction model.
- *
- * This data structure contains the background model as well as some paramaters value.
- * The code is designed to hide all the implementation details to the user to ease its use.
- */
-typedef struct vibeModel_Sequential vibeModel_Sequential_t;
-
-/**
- * Allocation of a new data structure where the background model will be stored.
- * Please note that this function only creates the structure to host the data.
- * This data structures will only be filled with a call to \ref libvibeModel_Sequential_AllocInit_8u_C1R.
- *
- * \result A pointer to a newly allocated \ref vibeModel_Sequential_t
- * structure, or <tt>NULL</tt> in the case of an error.
- */
-vibeModel_Sequential_t *libvibeModel_Sequential_New();
-
-/**
- * ViBe uses several parameters.
- * You can print and change some of them if you want. However, default
- * value should meet your needs for most videos.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-uint32_t libvibeModel_Sequential_PrintParameters(const vibeModel_Sequential_t *model);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param numberOfSamples
- * @return
- */
-int32_t libvibeModel_Sequential_SetNumberOfSamples(
-  vibeModel_Sequential_t *model,
-  const uint32_t numberOfSamples
-);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-uint32_t libvibeModel_Sequential_GetNumberOfSamples(const vibeModel_Sequential_t *model);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param matchingThreshold
- * @return
- */
-int32_t libvibeModel_Sequential_SetMatchingThreshold(
-  vibeModel_Sequential_t *model,
-  const uint32_t matchingThreshold
-);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-uint32_t libvibeModel_Sequential_GetMatchingThreshold(const vibeModel_Sequential_t *model);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param matchingNumber
- * @return
- */
-int32_t libvibeModel_Sequential_SetMatchingNumber(
-  vibeModel_Sequential_t *model,
-  const uint32_t matchingNumber
-);
-
-/**
- * Setter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param updateFactor New value for the update factor. Please note that the update factor is to be understood as a probability of updating. More specifically, an update factor of 16 means that 1 out of every 16 background pixels is updated. Likewise, an update factor of 1 means that every background pixel is updated.
- * @return
- */
-int32_t libvibeModel_Sequential_SetUpdateFactor(
-  vibeModel_Sequential_t *model,
-  const uint32_t updateFactor
-);
-
-/**
- * Getter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-uint32_t libvibeModel_Sequential_GetMatchingNumber(const vibeModel_Sequential_t *model);
-
-
-/**
- * Getter.
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-uint32_t libvibeModel_Sequential_GetUpdateFactor(const vibeModel_Sequential_t *model);
-
-/**
- * \brief Frees all the memory used by the <tt>model</tt> and deallocates the structure.
- *
- * This function frees all the memory allocated by \ref libvibeModel_SequentialNew and
- * \ref libvibeModel_Sequential_AllocInit_8u_C1R or \ref libvibeModel_Sequential_AllocInit_8u_C3R.
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @return
- */
-int32_t libvibeModel_Sequential_Free(vibeModel_Sequential_t *model);
-
-/**
- * The two following functions allocate the required memory according to the
- * model parameters and the dimensions of the input images.
- * You must use the "C1R" function for grayscale images and the "C3R" for color
- * images.
- * These 2 functions also initialize the background model using the content
- * of *image_data which is the pixel buffer of the first image of your stream.
- */
- // -------------------------  Single channel images ----------------------------
- /**
-  *
-  * @param model The data structure with ViBe's background subtraction model and parameters.
-  * @param image_data
-  * @param width
-  * @param height
-  * @return
-  */
-int32_t libvibeModel_Sequential_AllocInit_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-);
-
-/* These 2 functions perform 2 operations:
- *   - they classify the pixels *image_data using the provided model and store
- *     the results in *segmentation_map.
- *   - they update *model according to these results and the content of
- *     *image_data.
- * You must use the "C1R" function for grayscale images and the "C3R" for color
- * images.
- */
- /**
-  *
-  * @param model The data structure with ViBe's background subtraction model and parameters.
-  * @param image_data
-  * @param segmentation_map
-  * @return
-  */
-int32_t libvibeModel_Sequential_Segmentation_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-);
-
-/**
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param image_data
- * @param updating_mask
- * @return
- */
-int32_t libvibeModel_Sequential_Update_8u_C1R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-);
-
-// -------------------------  Three channel images -----------------------------
-/**
- * The pixel values of color images are arranged in the following order
- * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param image_data
- * @param width
- * @param height
- * @return
- */
-int32_t libvibeModel_Sequential_AllocInit_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height
-);
-
-/* These 2 functions perform 2 operations:
- *   - they classify the pixels *image_data using the provided model and store
- *     the results in *segmentation_map.
- *   - they update *model according to these results and the content of
- *     *image_data.
- * You must use the "C1R" function for grayscale images and the "C3R" for color
- * images.
- */
- /**
-  * The pixel values of color images are arranged in the following order
-  * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
-  *
-  * @param model The data structure with ViBe's background subtraction model and parameters.
-  * @param image_data
-  * @param segmentation_map
-  * @return
-  */
-int32_t libvibeModel_Sequential_Segmentation_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map
-);
-
-/**
- * The pixel values of color images are arranged in the following order
- * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
- *
- * @param model The data structure with ViBe's background subtraction model and parameters.
- * @param image_data
- * @param updating_mask
- * @return
- */
-int32_t libvibeModel_Sequential_Update_8u_C3R(
-  vibeModel_Sequential_t *model,
-  const uint8_t *image_data,
-  uint8_t *updating_mask
-);
diff --git a/package_bgs/VuMeter.cpp b/package_bgs/VuMeter.cpp
deleted file mode 100644
index 99baee9c28d48391d96634dd0931624050402226..0000000000000000000000000000000000000000
--- a/package_bgs/VuMeter.cpp
+++ /dev/null
@@ -1,113 +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 "VuMeter.h"
-
-using namespace bgslibrary::algorithms;
-
-VuMeter::VuMeter() :
-  enableFilter(true), binSize(8), alpha(0.995), threshold(0.03)
-{
-  std::cout << "VuMeter()" << std::endl;
-  setup("./config/VuMeter.xml");
-}
-
-VuMeter::~VuMeter()
-{
-  cvReleaseImage(&mask);
-  cvReleaseImage(&background);
-  cvReleaseImage(&gray);
-
-  std::cout << "~VuMeter()" << std::endl;
-}
-
-void VuMeter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-  frame = new IplImage(img_input);
-
-  if (firstTime)
-  {
-    bgs.SetAlpha(alpha);
-    bgs.SetBinSize(binSize);
-    bgs.SetThreshold(threshold);
-
-    gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
-    cvCvtColor(frame, gray, CV_RGB2GRAY);
-
-    background = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1);
-    cvCopy(gray, background);
-
-    mask = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1);
-    cvZero(mask);
-  }
-  else
-    cvCvtColor(frame, gray, CV_RGB2GRAY);
-
-  bgs.UpdateBackground(gray, background, mask);
-  img_foreground = cv::cvarrToMat(mask);
-  img_background = cv::cvarrToMat(background);
-
-  if (enableFilter)
-  {
-    cv::erode(img_foreground, img_foreground, cv::Mat());
-    cv::medianBlur(img_foreground, img_foreground, 5);
-  }
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("VuMeter", img_foreground);
-    cv::imshow("VuMeter Bkg Model", img_background);
-  }
-#endif
-
-  img_foreground.copyTo(img_output);
-  img_background.copyTo(img_bgmodel);
-
-  delete frame;
-  firstTime = false;
-}
-
-void VuMeter::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableFilter", enableFilter);
-
-  cvWriteInt(fs, "binSize", binSize);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "threshold", threshold);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void VuMeter::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableFilter = cvReadIntByName(fs, nullptr, "enableFilter", true);
-
-  binSize = cvReadIntByName(fs, nullptr, "binSize", 8);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.995);
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 0.03);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/VuMeter.h b/package_bgs/VuMeter.h
deleted file mode 100644
index fefd3ec724e3d57455abc2657540c498468bc468..0000000000000000000000000000000000000000
--- a/package_bgs/VuMeter.h
+++ /dev/null
@@ -1,52 +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
-
-#include "IBGS.h"
-#include "VuMeter/TBackgroundVuMeter.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class VuMeter : public IBGS
-    {
-    private:
-      TBackgroundVuMeter bgs;
-
-      IplImage *frame;
-      IplImage *gray;
-      IplImage *background;
-      IplImage *mask;
-
-      bool enableFilter;
-      int binSize;
-      double alpha;
-      double threshold;
-
-    public:
-      VuMeter();
-      ~VuMeter();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/VuMeter/TBackground.h b/package_bgs/VuMeter/TBackground.h
deleted file mode 100644
index dbaaa6c3e672f7b3360bd7229a047e4e9351bab1..0000000000000000000000000000000000000000
--- a/package_bgs/VuMeter/TBackground.h
+++ /dev/null
@@ -1,50 +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/>.
-*/
-/*
-*  TBackground.h
-*  Framework
-*
-*  Created by Robinault Lionel on 07/12/11.
-*
-*/
-#pragma once
-
-#include <iostream>
-#include <opencv2/opencv.hpp>
-
-class TBackground
-{
-public:
-  TBackground(void);
-  virtual ~TBackground(void);
-
-  virtual void Clear(void);
-  virtual void Reset(void);
-
-  virtual int UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
-  virtual int UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd);
-  virtual IplImage *CreateTestImg();
-
-  virtual int GetParameterCount(void);
-  virtual std::string GetParameterName(int nInd);
-  virtual std::string GetParameterValue(int nInd);
-  virtual int SetParameterValue(int nInd, std::string csNew);
-
-protected:
-  virtual int Init(IplImage * pSource);
-  virtual bool isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
-};
diff --git a/package_bgs/VuMeter/TBackgroundVuMeter.cpp b/package_bgs/VuMeter/TBackgroundVuMeter.cpp
deleted file mode 100644
index c4fd7a7511fb08bd2604617a51aa775917d81a07..0000000000000000000000000000000000000000
--- a/package_bgs/VuMeter/TBackgroundVuMeter.cpp
+++ /dev/null
@@ -1,372 +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/>.
-*/
-/*
-*  TBackgroundVuMeter.cpp
-*  Framework
-*
-*  Created by Robinault Lionel on 07/12/11.
-*
-*/
-#include "TBackgroundVuMeter.h"
-
-#define PROCESS_PAR_COUNT 3
-
-TBackgroundVuMeter::TBackgroundVuMeter(void)
-  : m_pHist(NULL)
-  , m_nBinCount(0)
-  , m_nBinSize(8)
-  , m_nCount(0)
-  , m_fAlpha(0.995)
-  , m_fThreshold(0.03)
-{
-  std::cout << "TBackgroundVuMeter()" << std::endl;
-}
-
-TBackgroundVuMeter::~TBackgroundVuMeter(void)
-{
-  Clear();
-  std::cout << "~TBackgroundVuMeter()" << std::endl;
-}
-
-void TBackgroundVuMeter::Clear(void)
-{
-  TBackground::Clear();
-
-  if (m_pHist != NULL)
-  {
-    for (int i = 0; i < m_nBinCount; ++i)
-    {
-      if (m_pHist[i] != NULL)
-        cvReleaseImage(&m_pHist[i]);
-    }
-
-    delete[] m_pHist;
-    m_pHist = NULL;
-    m_nBinCount = 0;
-  }
-
-  m_nCount = 0;
-}
-
-void TBackgroundVuMeter::Reset(void)
-{
-  float fVal = 0.0;
-
-  TBackground::Reset();
-
-  if (m_pHist != NULL)
-  {
-    //		fVal = (m_nBinCount != 0) ? (float)(1.0 / (double)m_nBinCount) : (float)0.0;
-    fVal = 0.0;
-
-    for (int i = 0; i < m_nBinCount; ++i)
-    {
-      if (m_pHist[i] != NULL)
-      {
-        cvSetZero(m_pHist[i]);
-        cvAddS(m_pHist[i], cvScalar(fVal), m_pHist[i]);
-      }
-    }
-  }
-
-  m_nCount = 0;
-}
-
-int TBackgroundVuMeter::GetParameterCount(void)
-{
-  return TBackground::GetParameterCount() + PROCESS_PAR_COUNT;
-}
-
-std::string TBackgroundVuMeter::GetParameterName(int nInd)
-{
-  std::string csResult;
-  int nNb;
-
-  nNb = TBackground::GetParameterCount();
-
-  if (nInd >= nNb)
-  {
-    nInd -= nNb;
-
-    switch (nInd)
-    {
-    case 0: csResult = "Bin size"; break;
-    case 1: csResult = "Alpha"; break;
-    case 2: csResult = "Threshold"; break;
-    }
-  }
-  else
-    csResult = TBackground::GetParameterName(nInd);
-
-  return csResult;
-}
-
-std::string TBackgroundVuMeter::GetParameterValue(int nInd)
-{
-  std::string csResult;
-  int nNb;
-
-  nNb = TBackground::GetParameterCount();
-
-  if (nInd >= nNb)
-  {
-    nInd -= nNb;
-
-    char buff[100];
-
-    switch (nInd)
-    {
-    case 0: sprintf(buff, "%d", m_nBinSize); break;
-    case 1: sprintf(buff, "%.3f", m_fAlpha); break;
-    case 2: sprintf(buff, "%.2f", m_fThreshold); break;
-    }
-
-    csResult = buff;
-  }
-  else
-    csResult = TBackground::GetParameterValue(nInd);
-
-  return csResult;
-}
-
-int TBackgroundVuMeter::SetParameterValue(int nInd, std::string csNew)
-{
-  int nErr = 0;
-
-  int nNb;
-
-  nNb = TBackground::GetParameterCount();
-
-  if (nInd >= nNb)
-  {
-    nInd -= nNb;
-
-    switch (nInd)
-    {
-    case 0: SetBinSize(atoi(csNew.c_str())); break;
-    case 1: SetAlpha(atof(csNew.c_str())); break;
-    case 2: SetThreshold(atof(csNew.c_str())); break;
-    default: nErr = 1;
-    }
-  }
-  else
-    nErr = TBackground::SetParameterValue(nInd, csNew);
-
-  return nErr;
-}
-
-int TBackgroundVuMeter::Init(IplImage * pSource)
-{
-  int nErr = 0;
-  int nbl, nbc;
-
-  Clear();
-
-  nErr = TBackground::Init(pSource);
-
-  if (pSource == NULL)
-    nErr = 1;
-
-  // calcul le nb de bin
-  if (!nErr)
-  {
-    nbl = pSource->height;
-    nbc = pSource->width;
-    m_nBinCount = (m_nBinSize != 0) ? 256 / m_nBinSize : 0;
-
-    if (m_nBinCount <= 0 || m_nBinCount > 256)
-      nErr = 1;
-  }
-
-  // creation du tableau de pointeur
-  if (!nErr)
-  {
-    m_pHist = new IplImage *[m_nBinCount];
-
-    if (m_pHist == NULL)
-      nErr = 1;
-  }
-
-  // creation des images
-  if (!nErr)
-  {
-    for (int i = 0; i < m_nBinCount; ++i)
-    {
-      m_pHist[i] = cvCreateImage(cvSize(nbc, nbl), IPL_DEPTH_32F, 1);
-
-      if (m_pHist[i] == NULL)
-        nErr = 1;
-    }
-  }
-
-  if (!nErr)
-    Reset();
-  else
-    Clear();
-
-  return nErr;
-}
-
-bool TBackgroundVuMeter::isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask)
-{
-  bool bResult = true;
-  int i;
-
-  bResult = TBackground::isInitOk(pSource, pBackground, pMotionMask);
-
-  if (pSource == NULL)
-    bResult = false;
-
-  if (m_nBinSize == 0)
-    bResult = false;
-
-  if (bResult)
-  {
-    i = (m_nBinSize != 0) ? 256 / m_nBinSize : 0;
-
-    if (i != m_nBinCount || m_pHist == NULL)
-      bResult = false;
-  }
-
-  if (bResult)
-  {
-    int nbl = pSource->height;
-    int nbc = pSource->width;
-
-    for (i = 0; i < m_nBinCount; ++i)
-    {
-      if (m_pHist[i] == NULL || m_pHist[i]->width != nbc || m_pHist[i]->height != nbl)
-        bResult = false;
-    }
-  }
-
-  return bResult;
-}
-
-int TBackgroundVuMeter::UpdateBackground(IplImage *pSource, IplImage *pBackground, IplImage *pMotionMask)
-{
-  int nErr = 0;
-  unsigned char *ptrs, *ptrb, *ptrm;
-  float *ptr1, *ptr2;
-
-  if (!isInitOk(pSource, pBackground, pMotionMask))
-    nErr = Init(pSource);
-
-  if (!nErr)
-  {
-    m_nCount++;
-    int nbc = pSource->width;
-    int nbl = pSource->height;
-    unsigned char v = m_nBinSize;
-
-    // multiplie tout par alpha
-    for (int i = 0; i < m_nBinCount; ++i)
-      cvConvertScale(m_pHist[i], m_pHist[i], m_fAlpha, 0.0);
-
-    for (int l = 0; l < nbl; ++l)
-    {
-      ptrs = (unsigned char *)(pSource->imageData + pSource->widthStep * l);
-      ptrm = (unsigned char *)(pMotionMask->imageData + pMotionMask->widthStep * l);
-      ptrb = (unsigned char *)(pBackground->imageData + pBackground->widthStep * l);
-
-      for (int c = 0; c < nbc; ++c, ptrs++, ptrb++, ptrm++)
-      {
-        // recherche le bin à augmenter
-        int i = *ptrs / v;
-
-        if (i < 0 || i >= m_nBinCount)
-          i = 0;
-
-        ptr1 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l);
-        ptr1 += c;
-
-        *ptr1 += (float)(1.0 - m_fAlpha);
-        *ptrm = (*ptr1 < m_fThreshold) ? 255 : 0;
-
-        // recherche le bin du fond actuel
-        i = *ptrb / v;
-
-        if (i < 0 || i >= m_nBinCount)
-          i = 0;
-
-        ptr2 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l);
-        ptr2 += c;
-
-        if (*ptr2 < *ptr1)
-          *ptrb = *ptrs;
-      }
-    }
-
-    if (m_nCount < 5)
-      cvSetZero(pMotionMask);
-  }
-
-  return nErr;
-}
-
-IplImage *TBackgroundVuMeter::CreateTestImg()
-{
-  IplImage *pImage = NULL;
-
-  if (m_nBinCount > 0)
-    pImage = cvCreateImage(cvSize(m_nBinCount, 100), IPL_DEPTH_8U, 3);
-
-  if (pImage != NULL)
-    cvSetZero(pImage);
-
-  return pImage;
-}
-
-int TBackgroundVuMeter::UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd)
-{
-  int nErr = 0;
-  float *ptrf;
-
-  if (pTest == NULL || !isInitOk(pSource, pBackground, pSource))
-    nErr = 1;
-
-  if (!nErr)
-  {
-    int nbl = pTest->height;
-    int nbc = pTest->width;
-
-    if (nbl != 100 || nbc != m_nBinCount)
-      nErr = 1;
-
-    if (nX < 0 || nX >= pSource->width || nY < 0 || nY >= pSource->height)
-      nErr = 1;
-  }
-
-  if (!nErr)
-  {
-    cvSetZero(pTest);
-
-    for (int i = 0; i < m_nBinCount; ++i)
-    {
-      ptrf = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * nY);
-      ptrf += nX;
-
-      if (*ptrf >= 0 || *ptrf <= 1.0) {
-        cvLine(pTest, cvPoint(i, 100), cvPoint(i, (int)(100.0 * (1.0 - *ptrf))), cvScalar(0, 255, 0));
-      }
-    }
-
-    cvLine(pTest, cvPoint(0, (int)(100.0 * (1.0 - m_fThreshold))), cvPoint(m_nBinCount, (int)(100.0 * (1.0 - m_fThreshold))), cvScalar(0, 128, 0));
-  }
-
-  return nErr;
-}
diff --git a/package_bgs/VuMeter/TBackgroundVuMeter.h b/package_bgs/VuMeter/TBackgroundVuMeter.h
deleted file mode 100644
index 36fe0d0b99ad0b8da8c4696cd931ecec1713bad6..0000000000000000000000000000000000000000
--- a/package_bgs/VuMeter/TBackgroundVuMeter.h
+++ /dev/null
@@ -1,67 +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/>.
-*/
-/*
-*  TBackgroundVuMeter.h
-*  Framework
-*
-*  Created by Robinault Lionel on 07/12/11.
-*
-*/
-#pragma once
-
-#include "TBackground.h"
-
-class TBackgroundVuMeter : public TBackground
-{
-public:
-  TBackgroundVuMeter(void);
-  virtual ~TBackgroundVuMeter(void);
-
-  virtual void Clear(void);
-  virtual void Reset(void);
-
-  virtual int UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
-
-  virtual IplImage *CreateTestImg();
-  virtual int UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd);
-
-  virtual int GetParameterCount(void);
-  virtual std::string GetParameterName(int nInd);
-  virtual std::string GetParameterValue(int nInd);
-  virtual int SetParameterValue(int nInd, std::string csNew);
-
-  inline void SetBinSize(int nNew) { m_nBinSize = (nNew > 0 && nNew < 255) ? nNew : 8; }
-  inline double GetBinSize() { return m_nBinSize; }
-
-  inline void SetAlpha(double fNew) { m_fAlpha = (fNew > 0.0 && fNew < 1.0) ? fNew : 0.995; }
-  inline double GetAlpha() { return m_fAlpha; }
-
-  inline void SetThreshold(double fNew) { m_fThreshold = (fNew > 0.0 && fNew < 1.0) ? fNew : 0.03; }
-  inline double GetThreshold() { return m_fThreshold; }
-
-protected:
-  IplImage **m_pHist;
-
-  int m_nBinCount;
-  int m_nBinSize;
-  int m_nCount;
-  double m_fAlpha;
-  double m_fThreshold;
-
-  virtual int Init(IplImage * pSource);
-  virtual bool isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
-};
diff --git a/package_bgs/WeightedMovingMean.h b/package_bgs/WeightedMovingMean.h
deleted file mode 100644
index 4a1a3c5fddb5c68c5c4eb8025f2427b143ff6b3a..0000000000000000000000000000000000000000
--- a/package_bgs/WeightedMovingMean.h
+++ /dev/null
@@ -1,45 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class WeightedMovingMean : public IBGS
-    {
-    private:
-      cv::Mat img_input_prev_1;
-      cv::Mat img_input_prev_2;
-      bool enableWeight;
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      WeightedMovingMean();
-      ~WeightedMovingMean();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/WeightedMovingVariance.h b/package_bgs/WeightedMovingVariance.h
deleted file mode 100644
index 79198b4a9e2fadd0c21f701e0b45e67a9b3dc488..0000000000000000000000000000000000000000
--- a/package_bgs/WeightedMovingVariance.h
+++ /dev/null
@@ -1,46 +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
-
-#include "IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class WeightedMovingVariance : public IBGS
-    {
-    private:
-      cv::Mat img_input_prev_1;
-      cv::Mat img_input_prev_2;
-      bool enableWeight;
-      bool enableThreshold;
-      int threshold;
-
-    public:
-      WeightedMovingVariance();
-      ~WeightedMovingVariance();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-      cv::Mat computeWeightedVariance(const cv::Mat &img_input_f, const cv::Mat &img_mean_f, const double weight);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/_template_/Amber.cpp b/package_bgs/_template_/Amber.cpp
deleted file mode 100644
index 2e29ac07369b7a84c16b6bbab0e03cdcf23344d2..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/Amber.cpp
+++ /dev/null
@@ -1,112 +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 "Amber.h"
-
-using namespace bgslibrary::algorithms;
-
-Amber::Amber() : model(nullptr)
-{
-  std::cout << "Amber()" << std::endl;
-  /* Initialization of the Amber model */
-  model = libamberModelNew();
-  setup("./config/Amber.xml");
-}
-
-Amber::~Amber()
-{
-  std::cout << "~Amber()" << std::endl;
-  libamberModelFree(model);
-}
-
-void Amber::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  init(img_input, img_output, img_bgmodel);
-
-  if (img_input.empty())
-    return;
-
-  // Start the initialization
-  unsigned int width = img_input.cols;
-  unsigned int height = img_input.rows;
-
-  if (img_input.channels() != 3)
-  {
-    std::cout << "Only works for 3 channels images. Sorry for that" << std::endl;
-    return;
-  }
-
-  unsigned int stride = width * 3;
-  unsigned char* image = static_cast<unsigned char*>(img_input.data);
-
-  if (firstTime)
-  {
-    /* Create a buffer for the output image */
-    //img_output = Mat(img_input.rows, img_input.cols, CV_8UC1);
-
-    /* Sets default model values */
-    // libamberModelSetNumberOfSamples(model, nbSamples);
-    // libamberModelSetMatchingThreshold(model, matchingThreshold);
-    // libamberModelSetMatchingNumber(model, matchingNumber);
-    // libamberModelSetUpdateFactor(model, init_subsamplingFactor);
-    // libamberModelPrintParameters(model);
-
-    /* Initiliazes the Amber model */
-    libamberModelAllocInit_8u_C3R(model, image, width, height);
-  }
-
-  /* Create temporary buffers */
-  unsigned char* output_segmentationMap = static_cast<unsigned char*>(calloc(width * height, sizeof(unsigned char)));
-  libamberGetSegmentation_8u_C3R(model, image, output_segmentationMap);
-
-  unsigned char* oBuffer = static_cast<unsigned char*>(img_output.data);
-  unsigned char* tmpSegmentationMap = output_segmentationMap;
-
-  for (int i = 0; i < width * height; i++)
-  {
-    *oBuffer = *tmpSegmentationMap;
-
-    ++oBuffer;
-    ++tmpSegmentationMap;
-  }
-
-#ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-    imshow("Amber", img_output);
-#endif
-
-  firstTime = false;
-  free(output_segmentationMap);
-}
-
-void Amber::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
-}
-
-void Amber::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", false);
-
-  cvReleaseFileStorage(&fs);
-}
diff --git a/package_bgs/_template_/Amber.h b/package_bgs/_template_/Amber.h
deleted file mode 100644
index 37f0f8deca5fc5c0d32ce8614bd0820be1f3dfd2..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/Amber.h
+++ /dev/null
@@ -1,45 +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
-
-#include <math.h>
-#include <sys/types.h>
-
-#include "../IBGS.h"
-#include "amber/amber.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class Amber : public IBGS
-    {
-    private:
-      amberModel* model;
-
-    public:
-      Amber();
-      ~Amber();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig();
-      void loadConfig();
-    };
-  }
-}
diff --git a/package_bgs/_template_/MyBGS.cpp b/package_bgs/_template_/MyBGS.cpp
deleted file mode 100644
index 10d55884f8d33c9980d71f653e7c3b26227e7f8d..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/MyBGS.cpp
+++ /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/>.
-*/
-#include "MyBGS.h"
-
-using namespace bgslibrary::algorithms;
-
-MyBGS::MyBGS() {}
-MyBGS::~MyBGS() {}
-
-void MyBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
-{
-  if (img_input.empty())
-    return;
-
-  if (img_previous.empty())
-    img_input.copyTo(img_previous);
-
-  cv::Mat img_foreground;
-  cv::absdiff(img_previous, img_input, img_foreground);
-
-  if (img_foreground.channels() == 3)
-    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
-
-  cv::threshold(img_foreground, img_foreground, 15, 255, cv::THRESH_BINARY);
-
-  img_foreground.copyTo(img_output);
-  img_previous.copyTo(img_bgmodel);
-
-  img_input.copyTo(img_previous);
-}
diff --git a/package_bgs/_template_/MyBGS.h b/package_bgs/_template_/MyBGS.h
deleted file mode 100644
index dea2a2fa3bbc2163a9afc822351f8c2f9bcbfb3e..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/MyBGS.h
+++ /dev/null
@@ -1,43 +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
-
-#include <opencv2/opencv.hpp>
-
-#include "../IBGS.h"
-
-namespace bgslibrary
-{
-  namespace algorithms
-  {
-    class MyBGS : public IBGS
-    {
-    private:
-      cv::Mat img_previous;
-
-    public:
-      MyBGS();
-      ~MyBGS();
-
-      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
-
-    private:
-      void saveConfig() {}
-      void loadConfig() {}
-    };
-  }
-}
diff --git a/package_bgs/_template_/amber/amber.c b/package_bgs/_template_/amber/amber.c
deleted file mode 100644
index 00bdfb14a5006b825448657d8f565469eaa6dc93..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/amber/amber.c
+++ /dev/null
@@ -1,80 +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 "amber.h"
-
-#define COLOR_BACKGROUND   0
-#define COLOR_FOREGROUND 255
-
-amberModel* libamberModelNew()
-{
-  /* model structure alloc */
-  amberModel* model = NULL;
-  model = (amberModel*)calloc(1, sizeof(amberModel));
-  assert(model != NULL);
-
-  /* default parameters values */
-  model->height = 0;
-
-  return(model);
-}
-
-// --------------------------------------------------
-int32_t libamberModelAllocInit_8u_C3R(amberModel* model,
-  const uint8_t *image_data,
-  const uint32_t width,
-  const uint32_t height)
-{
-
-  /* basic checks */
-  assert((image_data != NULL) && (model != NULL));
-  assert((model->width > 0) && (model->height > 0));
-
-  /* finish model alloc - parameters values cannot be changed anymore */
-  model->width = width;
-  model->height = height;
-
-  return(0);
-}
-
-// --------------------------------------------------
-int32_t libamberGetSegmentation_8u_C3R(amberModel* model,
-  const uint8_t *image_data,
-  uint8_t *segmentation_map)
-{
-  /* basic checks */
-  assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
-  assert((model->width > 0) && (model->height > 0));
-
-  return(0);
-}
-
-// --------------------------------------------------
-int32_t libamberModelFree(amberModel* model)
-{
-  if (model == NULL)
-    return(-1);
-
-  free(model);
-
-  return(0);
-}
-
-/* For compilation with g++ */
-#ifdef __cplusplus
-}
-#endif
diff --git a/package_bgs/_template_/amber/amber.h b/package_bgs/_template_/amber/amber.h
deleted file mode 100644
index 02061795f1ef211b8907c3d16f43123e6099d380..0000000000000000000000000000000000000000
--- a/package_bgs/_template_/amber/amber.h
+++ /dev/null
@@ -1,64 +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
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#define COLOR_BACKGROUND   0
-#define COLOR_FOREGROUND 255
-
-/* For compilation with g++ */
-#ifdef __cplusplus
-extern "C"
-{
-#endif 
-  /* end of addition for compilation with g++ */
-
-#ifndef _STDINT_H  
-// This is used to make it compatible for cross-compilation
-  typedef unsigned char uint8_t;
-  typedef int int32_t;
-  typedef unsigned int uint32_t;
-#endif // _STDINT_H 
-
-  typedef struct {
-    uint32_t width;
-    uint32_t height;
-  } amberModel;
-
-  /** Allocation of a new data structure where the background model
-     will be stored */
-  amberModel* libamberModelNew();
-
-  int32_t libamberModelAllocInit_8u_C3R(amberModel* model,
-    const uint8_t *image_data,
-    const uint32_t width,
-    const uint32_t height);
-
-  int32_t libamberGetSegmentation_8u_C3R(amberModel* model,
-    const uint8_t *image_data,
-    uint8_t *segmentation_map);
-
-
-  int32_t libamberModelFree(amberModel* model);
-
-  /* For compilation with g++ */
-#ifdef __cplusplus
-}
-#endif 
diff --git a/package_bgs/dp/AdaptiveMedianBGS.h b/package_bgs/dp/AdaptiveMedianBGS.h
deleted file mode 100644
index 79a04b39ab60dae865fb0b38af2f1108c4e18df7..0000000000000000000000000000000000000000
--- a/package_bgs/dp/AdaptiveMedianBGS.h
+++ /dev/null
@@ -1,90 +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/>.
-*/
-/****************************************************************************
-*
-* AdaptiveMedianBGS.hpp
-*
-* Purpose: Implementation of the simple adaptive median background
-*		  		 subtraction algorithm described in:
-*	  			 "Segmentation and tracking of piglets in images"
-* 						by McFarlane and Schofield
-*
-* Author: Donovan Parks, September 2007
-
-Example:
-    Algorithms::BackgroundSubtraction::AdaptiveMedianParams params;
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = 40;
-    params.HighThreshold() = 2*params.LowThreshold();
-    params.SamplingRate() = 7;
-    params.LearningFrames() = 30;
-
-    Algorithms::BackgroundSubtraction::AdaptiveMedianBGS bgs;
-    bgs.Initalize(params);
-******************************************************************************/
-#pragma once
-
-#include "Bgs.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    // --- Parameters used by the Adaptive Median BGS algorithm ---
-    class AdaptiveMedianParams : public BgsParams
-    {
-    public:
-      unsigned char &LowThreshold() { return m_low_threshold; }
-      unsigned char &HighThreshold() { return m_high_threshold; }
-
-      int &SamplingRate() { return m_samplingRate; }
-      int &LearningFrames() { return m_learning_frames; }
-
-    private:
-      unsigned char m_low_threshold;
-      unsigned char m_high_threshold;
-
-      int m_samplingRate;
-      int m_learning_frames;
-    };
-
-
-    // --- Adaptive Median BGS algorithm ---
-    class AdaptiveMedianBGS : public Bgs
-    {
-    public:
-      virtual ~AdaptiveMedianBGS() {}
-
-      void Initalize(const BgsParams& param);
-
-      void InitModel(const RgbImage& data);
-      void Subtract(int frame_num, const RgbImage& data,
-        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
-      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
-
-      RgbImage* Background();
-
-    private:
-      void SubtractPixel(int r, int c, const RgbPixel& pixel,
-        unsigned char& low_threshold, unsigned char& high_threshold);
-
-      AdaptiveMedianParams m_params;
-
-      RgbImage m_median;
-    };
-  }
-}
diff --git a/package_bgs/dp/Bgs.h b/package_bgs/dp/Bgs.h
deleted file mode 100644
index 26fff70ea503cfb5737f53ae1991efbb529ff598..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Bgs.h
+++ /dev/null
@@ -1,63 +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/>.
-*/
-/****************************************************************************
-*
-* Bgs.hpp
-*
-* Purpose: Base class for BGS algorithms.
-*
-* Author: Donovan Parks, October 2007
-*
-******************************************************************************/
-#pragma once
-
-#include "Image.h"
-#include "BgsParams.h"
-
-namespace Algorithms
-{
-namespace BackgroundSubtraction
-{
-class Bgs
-{
-public:
-  static const int BACKGROUND = 0;
-  static const int FOREGROUND = 255;
-
-  virtual ~Bgs() {}
-
-  // Initialize any data required by the BGS algorithm. Should be called once before calling
-  // any of the following functions.
-  virtual void Initalize(const BgsParams& param) = 0;
-
-  // Initialize the background model. Typically, the background model is initialized using the first
-  // frame of the incoming video stream, but alternatives are possible.
-  virtual void InitModel(const RgbImage& data) = 0;
-
-  // Subtract the current frame from the background model and produce a binary foreground mask using
-  // both a low and high threshold value.
-  virtual void Subtract(int frame_num, const RgbImage& data,
-                        BwImage& low_threshold_mask, BwImage& high_threshold_mask) = 0;
-
-  // Update the background model. Only pixels set to background in update_mask are updated.
-  virtual void Update(int frame_num, const RgbImage& data,  const BwImage& update_mask) = 0;
-
-  // Return the current background model.
-  virtual RgbImage *Background() = 0;
-};
-}
-}
diff --git a/package_bgs/dp/BgsParams.h b/package_bgs/dp/BgsParams.h
deleted file mode 100644
index d2e7d29e084cffc798f968c0290b304e62071a50..0000000000000000000000000000000000000000
--- a/package_bgs/dp/BgsParams.h
+++ /dev/null
@@ -1,55 +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/>.
-*/
-/****************************************************************************
-*
-* BgsParams.hpp
-*
-* Purpose: Base class for BGS parameters. Any parameters common to all BGS
-*					 algorithms should be specified directly in this class.
-*
-* Author: Donovan Parks, May 2008
-*
-******************************************************************************/
-#pragma once
-
-namespace Algorithms
-{
-namespace BackgroundSubtraction
-{
-class BgsParams
-{
-public:
-  virtual ~BgsParams() {}
-
-  virtual void SetFrameSize(unsigned int width, unsigned int height)
-  {
-    m_width = width;
-    m_height = height;
-    m_size = width*height;
-  }
-
-  unsigned int &Width() { return m_width; }
-  unsigned int &Height() { return m_height; }
-  unsigned int &Size() { return m_size; }
-
-protected:
-  unsigned int m_width;
-  unsigned int m_height;
-  unsigned int m_size;
-};
-}
-}
diff --git a/package_bgs/dp/Eigenbackground.h b/package_bgs/dp/Eigenbackground.h
deleted file mode 100644
index 10ed189696c08296181fc0c1eb54a61a81f2dd7a..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Eigenbackground.h
+++ /dev/null
@@ -1,97 +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/>.
-*/
-/****************************************************************************
-*
-* Eigenbackground.hpp
-*
-* Purpose: Implementation of the Eigenbackground background subtraction
-*					 algorithm developed by Oliver et al.
-*
-* Author: Donovan Parks, September 2007
-*
-* "A Bayesian Computer Vision System for Modeling Human Interactions"
-*   Nuria Oliver, Barbara Rosario, Alex P. Pentland 2000
-
-Example:
-Algorithms::BackgroundSubtraction::EigenbackgroundParams params;
-params.SetFrameSize(width, height);
-params.LowThreshold() = 15*15;
-params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-params.HistorySize() = 100;
-params.EmbeddedDim() = 20;
-
-Algorithms::BackgroundSubtraction::Eigenbackground bgs;
-bgs.Initalize(params);
-******************************************************************************/
-#pragma once
-
-#include "Bgs.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    // --- Parameters used by the Mean BGS algorithm ---
-    class EigenbackgroundParams : public BgsParams
-    {
-    public:
-      float &LowThreshold() { return m_low_threshold; }
-      float &HighThreshold() { return m_high_threshold; }
-
-      int &HistorySize() { return m_history_size; }
-      int &EmbeddedDim() { return m_dim; }
-
-    private:
-      // A pixel will be classified as foreground if the squared distance of any
-      // color channel is greater than the specified threshold
-      float m_low_threshold;
-      float m_high_threshold;
-
-      int m_history_size;			// number frames used to create eigenspace
-      int m_dim;							// eigenspace dimensionality
-    };
-
-    // --- Eigenbackground BGS algorithm ---
-    class Eigenbackground : public Bgs
-    {
-    public:
-      Eigenbackground();
-      ~Eigenbackground();
-
-      void Initalize(const BgsParams& param);
-
-      void InitModel(const RgbImage& data);
-      void Subtract(int frame_num, const RgbImage& data,
-        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
-      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
-
-      RgbImage* Background() { return &m_background; }
-
-    private:
-      void UpdateHistory(int frameNum, const RgbImage& newFrame);
-
-      EigenbackgroundParams m_params;
-
-      CvMat* m_pcaData;
-      CvMat* m_pcaAvg;
-      CvMat* m_eigenValues;
-      CvMat* m_eigenVectors;
-
-      RgbImage m_background;
-    };
-  }
-}
diff --git a/package_bgs/dp/Error.cpp b/package_bgs/dp/Error.cpp
deleted file mode 100644
index 1bd87db824e308d63181f5ea6cc32a6304d6129f..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Error.cpp
+++ /dev/null
@@ -1,57 +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/>.
-*/
-/****************************************************************************
-*
-* Error.cpp
-*
-* Purpose:  Error checking routines.
-*
-* Author: Donovan Parks, July 2007
-*
-******************************************************************************/
-
-#include <iostream> 
-#include <fstream>
-
-#include "Error.h"
-
-using namespace std;
-
-ofstream traceFile;
-
-bool Error(const char* msg, const char* code, int data)
-{
-  cerr << code << ": " << msg << endl;
-
-  return false;
-}
-
-bool TraceInit(const char* filename)
-{
-  traceFile.open(filename);
-  return traceFile.is_open();
-}
-
-void Trace(const char* msg)
-{
-  traceFile << msg << endl;
-}
-
-void TraceClose()
-{
-  traceFile.close();
-}
diff --git a/package_bgs/dp/Error.h b/package_bgs/dp/Error.h
deleted file mode 100644
index 81cbbebcf8181bc40bddc526bc3ebb88ec6a0ea8..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Error.h
+++ /dev/null
@@ -1,31 +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/>.
-*/
-/****************************************************************************
-*
-* Error.h
-*
-* Purpose:  Error checking routines.
-*
-* Author: Donovan Parks, July 2007
-*
-******************************************************************************/
-#pragma once
-
-bool Error(const char* msg, const char* code, int data);
-bool TraceInit(const char* filename);
-void Trace(const char* msg);
-void TraceClose();
diff --git a/package_bgs/dp/GrimsonGMM.cpp b/package_bgs/dp/GrimsonGMM.cpp
deleted file mode 100644
index 4cf6f35e8e9ae30c19481c8fbcc7ef4f250df15f..0000000000000000000000000000000000000000
--- a/package_bgs/dp/GrimsonGMM.cpp
+++ /dev/null
@@ -1,331 +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/>.
-*/
-/****************************************************************************
-*
-* GrimsonGMM.cpp
-*
-* Purpose: Implementation of the Gaussian mixture model (GMM) background
-*		  		 subtraction described in:
-*	  			 "Adaptive background mixture models for real-time tracking"
-* 						by Chris Stauffer and W.E.L Grimson
-*
-* Author: Donovan Parks, September 2007
-*
-* This code is based on code by Z. Zivkovic's written for his enhanced GMM
-* background subtraction algorithm:
-*
-*	"Improved adaptive Gausian mixture model for background subtraction"
-*		Z.Zivkovic
-*		International Conference Pattern Recognition, UK, August, 2004
-*
-*
-* "Efficient Adaptive Density Estimapion per Image Pixel for the
-*			Task of Background Subtraction"
-*		Z.Zivkovic, F. van der Heijden
-*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-******************************************************************************/
-
-#include "GrimsonGMM.h"
-
-using namespace Algorithms::BackgroundSubtraction;
-
-int compareGMM(const void* _gmm1, const void* _gmm2)
-{
-  GMM gmm1 = *(GMM*)_gmm1;
-  GMM gmm2 = *(GMM*)_gmm2;
-
-  if (gmm1.significants < gmm2.significants)
-    return 1;
-  else if (gmm1.significants == gmm2.significants)
-    return 0;
-  else
-    return -1;
-}
-
-GrimsonGMM::GrimsonGMM()
-{
-  m_modes = NULL;
-}
-
-GrimsonGMM::~GrimsonGMM()
-{
-  delete[] m_modes;
-}
-
-void GrimsonGMM::Initalize(const BgsParams& param)
-{
-  m_params = (GrimsonParams&)param;
-
-  // Tbf - the threshold
-  m_bg_threshold = 0.75f;	// 1-cf from the paper
-
-  // Tgenerate - the threshold
-  m_variance = 36.0f;		// sigma for the new mode
-
-  // GMM for each pixel
-  m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
-
-  // used modes per pixel
-  m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
-
-  m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
-}
-
-RgbImage* GrimsonGMM::Background()
-{
-  return &m_background;
-}
-
-void GrimsonGMM::InitModel(const RgbImage& data)
-{
-  m_modes_per_pixel.Clear();
-
-  for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
-  {
-    m_modes[i].weight = 0;
-    m_modes[i].variance = 0;
-    m_modes[i].muR = 0;
-    m_modes[i].muG = 0;
-    m_modes[i].muB = 0;
-    m_modes[i].significants = 0;
-  }
-}
-
-void GrimsonGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
-{
-  // it doesn't make sense to have conditional updates in the GMM framework
-}
-
-void GrimsonGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
-  unsigned char& low_threshold, unsigned char& high_threshold)
-{
-  // calculate distances to the modes (+ sort???)
-  // here we need to go in descending order!!!
-  long pos;
-  bool bFitsPDF = false;
-  bool bBackgroundLow = false;
-  bool bBackgroundHigh = false;
-
-  float fOneMinAlpha = 1 - m_params.Alpha();
-
-  float totalWeight = 0.0f;
-
-  // calculate number of Gaussians to include in the background model
-  int backgroundGaussians = 0;
-  double sum = 0.0;
-  for (int i = 0; i < numModes; ++i)
-  {
-    if (sum < m_bg_threshold)
-    {
-      backgroundGaussians++;
-      sum += m_modes[posPixel + i].weight;
-    }
-    else
-    {
-      break;
-    }
-  }
-
-  // update all distributions and check for match with current pixel
-  for (int iModes = 0; iModes < numModes; iModes++)
-  {
-    pos = posPixel + iModes;
-    float weight = m_modes[pos].weight;
-
-    // fit not found yet
-    if (!bFitsPDF)
-    {
-      //check if it belongs to some of the modes
-      //calculate distance
-      float var = m_modes[pos].variance;
-      float muR = m_modes[pos].muR;
-      float muG = m_modes[pos].muG;
-      float muB = m_modes[pos].muB;
-
-      float dR = muR - pixel(0);
-      float dG = muG - pixel(1);
-      float dB = muB - pixel(2);
-
-      // calculate the squared distance
-      float dist = (dR*dR + dG*dG + dB*dB);
-
-      if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
-        bBackgroundHigh = true;
-
-      // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
-      if (dist < m_params.LowThreshold()*var)
-      {
-        bFitsPDF = true;
-
-        // check if this Gaussian is part of the background model
-        if (iModes < backgroundGaussians)
-          bBackgroundLow = true;
-
-        //update distribution
-        float k = m_params.Alpha() / weight;
-        weight = fOneMinAlpha*weight + m_params.Alpha();
-        m_modes[pos].weight = weight;
-        m_modes[pos].muR = muR - k*(dR);
-        m_modes[pos].muG = muG - k*(dG);
-        m_modes[pos].muB = muB - k*(dB);
-
-        //limit the variance
-        float sigmanew = var + k*(dist - var);
-        m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-      else
-      {
-        weight = fOneMinAlpha*weight;
-        if (weight < 0.0)
-        {
-          weight = 0.0;
-          numModes--;
-        }
-
-        m_modes[pos].weight = weight;
-        m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-      }
-    }
-    else
-    {
-      weight = fOneMinAlpha*weight;
-      if (weight < 0.0)
-      {
-        weight = 0.0;
-        numModes--;
-      }
-      m_modes[pos].weight = weight;
-      m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
-    }
-
-    totalWeight += weight;
-  }
-
-  // renormalize weights so they add to one
-  double invTotalWeight = 1.0 / totalWeight;
-  for (int iLocal = 0; iLocal < numModes; iLocal++)
-  {
-    m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
-    m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
-      / sqrt(m_modes[posPixel + iLocal].variance);
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&m_modes[posPixel], numModes, sizeof(GMM), compareGMM);
-
-  // make new mode if needed and exit
-  if (!bFitsPDF)
-  {
-    if (numModes < m_params.MaxModes())
-    {
-      numModes++;
-    }
-    else
-    {
-      // the weakest mode will be replaced
-    }
-
-    pos = posPixel + numModes - 1;
-
-    m_modes[pos].muR = pixel.ch[0];
-    m_modes[pos].muG = pixel.ch[1];
-    m_modes[pos].muB = pixel.ch[2];
-    m_modes[pos].variance = m_variance;
-    m_modes[pos].significants = 0;			// will be set below
-
-    if (numModes == 1)
-      m_modes[pos].weight = 1;
-    else
-      m_modes[pos].weight = m_params.Alpha();
-
-    //renormalize weights
-    int iLocal;
-    float sum = 0.0;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-    {
-      sum += m_modes[posPixel + iLocal].weight;
-    }
-
-    double invSum = 1.0 / sum;
-    for (iLocal = 0; iLocal < numModes; iLocal++)
-    {
-      m_modes[posPixel + iLocal].weight *= (float)invSum;
-      m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
-        / sqrt(m_modes[posPixel + iLocal].variance);
-
-    }
-  }
-
-  // Sort significance values so they are in desending order.
-  qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareGMM);
-
-  if (bBackgroundLow)
-  {
-    low_threshold = BACKGROUND;
-  }
-  else
-  {
-    low_threshold = FOREGROUND;
-  }
-
-  if (bBackgroundHigh)
-  {
-    high_threshold = BACKGROUND;
-  }
-  else
-  {
-    high_threshold = FOREGROUND;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//Input:
-//  data - a pointer to the data of a RGB image of the same size
-//Output:
-//  output - a pointer to the data of a gray value image of the same size 
-//					(the memory should already be reserved) 
-//					values: 255-foreground, 125-shadow, 0-background
-///////////////////////////////////////////////////////////////////////////////
-void GrimsonGMM::Subtract(int frame_num, const RgbImage& data,
-  BwImage& low_threshold_mask, BwImage& high_threshold_mask)
-{
-  unsigned char low_threshold, high_threshold;
-  long posPixel;
-
-  // update each pixel of the image
-  for (unsigned int r = 0; r < m_params.Height(); ++r)
-  {
-    for (unsigned int c = 0; c < m_params.Width(); ++c)
-    {
-      // update model + background subtract
-      posPixel = (r*m_params.Width() + c)*m_params.MaxModes();
-
-      SubtractPixel(posPixel, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
-
-      low_threshold_mask(r, c) = low_threshold;
-      high_threshold_mask(r, c) = high_threshold;
-
-      m_background(r, c, 0) = (unsigned char)m_modes[posPixel].muR;
-      m_background(r, c, 1) = (unsigned char)m_modes[posPixel].muG;
-      m_background(r, c, 2) = (unsigned char)m_modes[posPixel].muB;
-    }
-  }
-}
-
diff --git a/package_bgs/dp/Image.cpp b/package_bgs/dp/Image.cpp
deleted file mode 100644
index 92119c246c8d366b3f7addaabefe0c013fa25b7e..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Image.cpp
+++ /dev/null
@@ -1,76 +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/>.
-*/
-/****************************************************************************
-*
-* Image.hpp
-*
-* Purpose:  C++ wrapper for OpenCV IplImage which supports simple and
-*						efficient access to the image data
-*
-* Author: Donovan Parks, September 2007
-*
-* Based on code from:
-*  http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.hpptml
-******************************************************************************/
-
-#include "Image.h"
-
-ImageBase::~ImageBase()
-{
-  if (imgp != NULL && m_bReleaseMemory)
-    cvReleaseImage(&imgp);
-  imgp = NULL;
-}
-
-void DensityFilter(BwImage& image, BwImage& filtered, int minDensity, unsigned char fgValue)
-{
-  for (int r = 1; r < image.Ptr()->height - 1; ++r)
-  {
-    for (int c = 1; c < image.Ptr()->width - 1; ++c)
-    {
-      int count = 0;
-      if (image(r, c) == fgValue)
-      {
-        if (image(r - 1, c - 1) == fgValue)
-          count++;
-        if (image(r - 1, c) == fgValue)
-          count++;
-        if (image(r - 1, c + 1) == fgValue)
-          count++;
-        if (image(r, c - 1) == fgValue)
-          count++;
-        if (image(r, c + 1) == fgValue)
-          count++;
-        if (image(r + 1, c - 1) == fgValue)
-          count++;
-        if (image(r + 1, c) == fgValue)
-          count++;
-        if (image(r + 1, c + 1) == fgValue)
-          count++;
-
-        if (count < minDensity)
-          filtered(r, c) = 0;
-        else
-          filtered(r, c) = fgValue;
-      }
-      else
-      {
-        filtered(r, c) = 0;
-      }
-    }
-  }
-}
diff --git a/package_bgs/dp/Image.h b/package_bgs/dp/Image.h
deleted file mode 100644
index 6c0b5b3257486489597f8c9dae47dc6cec304d8b..0000000000000000000000000000000000000000
--- a/package_bgs/dp/Image.h
+++ /dev/null
@@ -1,360 +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/>.
-*/
-/****************************************************************************
-*
-* Image.h
-*
-* Purpose:  C++ wrapper for OpenCV IplImage which supports simple and
-*						efficient access to the image data
-*
-* Author: Donovan Parks, September 2007
-*
-* Based on code from:
-*  http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html
-******************************************************************************/
-#pragma once
-
-#include <opencv2/opencv.hpp>
-//#include <cxcore.h>
-
-// --- Image Iterator ---------------------------------------------------------
-
-template <class T>
-class ImageIterator
-{
-public:
-  ImageIterator(IplImage* image, int x = 0, int y = 0, int dx = 0, int dy = 0) :
-    i(x), j(y), i0(0)
-  {
-    data = reinterpret_cast<T*>(image->imageData);
-    step = image->widthStep / sizeof(T);
-
-    nl = image->height;
-    if ((y + dy) > 0 && (y + dy) < nl)
-      nl = y + dy;
-
-    if (y < 0)
-      j = 0;
-
-    data += step*j;
-
-    nc = image->width;
-    if ((x + dx) > 0 && (x + dx) < nc)
-      nc = x + dx;
-
-    nc *= image->nChannels;
-    if (x > 0)
-      i0 = x*image->nChannels;
-    i = i0;
-
-    nch = image->nChannels;
-  }
-
-
-  /* has next ? */
-  bool operator!() const { return j < nl; }
-
-  /* next pixel */
-  ImageIterator& operator++()
-  {
-    i++;
-    if (i >= nc)
-    {
-      i = i0;
-      j++;
-      data += step;
-    }
-    return *this;
-  }
-
-  ImageIterator& operator+=(int s)
-  {
-    i += s;
-    if (i >= nc)
-    {
-      i = i0;
-      j++;
-      data += step;
-    }
-    return *this;
-  }
-
-  /* pixel access */
-  T& operator*() { return data[i]; }
-
-  const T operator*() const { return data[i]; }
-
-  const T neighbor(int dx, int dy) const
-  {
-    return *(data + dy*step + i + dx);
-  }
-
-  T* operator&() const { return data + i; }
-
-  /* current pixel coordinates */
-  int column() const { return i / nch; }
-  int line() const { return j; }
-
-private:
-  int i, i0, j;
-  T* data;
-  int step;
-  int nl, nc;
-  int nch;
-};
-
-// --- Constants --------------------------------------------------------------
-
-const unsigned char NUM_CHANNELS = 3;
-
-// --- Pixel Types ------------------------------------------------------------
-
-class RgbPixel
-{
-public:
-  RgbPixel() { ; }
-  RgbPixel(unsigned char _r, unsigned char _g, unsigned char _b)
-  {
-    ch[0] = _r; ch[1] = _g; ch[2] = _b;
-  }
-
-  RgbPixel& operator=(const RgbPixel& rhs)
-  {
-    ch[0] = rhs.ch[0]; ch[1] = rhs.ch[1]; ch[2] = rhs.ch[2];
-    return *this;
-  }
-
-  inline unsigned char& operator()(const int _ch)
-  {
-    return ch[_ch];
-  }
-
-  inline unsigned char operator()(const int _ch) const
-  {
-    return ch[_ch];
-  }
-
-  unsigned char ch[3];
-};
-
-class RgbPixelFloat
-{
-public:
-  RgbPixelFloat() { ; }
-  RgbPixelFloat(float _r, float _g, float _b)
-  {
-    ch[0] = _r; ch[1] = _g; ch[2] = _b;
-  }
-
-  RgbPixelFloat& operator=(const RgbPixelFloat& rhs)
-  {
-    ch[0] = rhs.ch[0]; ch[1] = rhs.ch[1]; ch[2] = rhs.ch[2];
-    return *this;
-  }
-
-  inline float& operator()(const int _ch)
-  {
-    return ch[_ch];
-  }
-
-  inline float operator()(const int _ch) const
-  {
-    return ch[_ch];
-  }
-
-  float ch[3];
-};
-
-// --- Image Types ------------------------------------------------------------
-
-class ImageBase
-{
-public:
-  ImageBase(IplImage* img = NULL) { imgp = img; m_bReleaseMemory = true; }
-  ~ImageBase();
-
-  void ReleaseMemory(bool b) { m_bReleaseMemory = b; }
-
-  IplImage* Ptr() { return imgp; }
-  const IplImage* Ptr() const { return imgp; }
-
-  void ReleaseImage()
-  {
-    cvReleaseImage(&imgp);
-  }
-
-  void operator=(IplImage* img)
-  {
-    imgp = img;
-  }
-
-  // copy-constructor
-  ImageBase(const ImageBase& rhs)
-  {
-    // it is very inefficent if this copy-constructor is called
-    assert(false);
-  }
-
-  // assignment operator
-  ImageBase& operator=(const ImageBase& rhs)
-  {
-    // it is very inefficent if operator= is called
-    assert(false);
-
-    return *this;
-  }
-
-  virtual void Clear() = 0;
-
-protected:
-  IplImage* imgp;
-  bool m_bReleaseMemory;
-};
-
-class RgbImage : public ImageBase
-{
-public:
-  RgbImage(IplImage* img = NULL) : ImageBase(img) { ; }
-
-  virtual void Clear()
-  {
-    cvZero(imgp);
-  }
-
-  void operator=(IplImage* img)
-  {
-    imgp = img;
-  }
-
-  // channel-level access using image(row, col, channel)
-  inline unsigned char& operator()(const int r, const int c, const int ch)
-  {
-    return (unsigned char &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels + ch];
-  }
-
-  inline const unsigned char& operator()(const int r, const int c, const int ch) const
-  {
-    return (unsigned char &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels + ch];
-  }
-
-  // RGB pixel-level access using image(row, col)
-  inline RgbPixel& operator()(const int r, const int c)
-  {
-    return (RgbPixel &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels];
-  }
-
-  inline const RgbPixel& operator()(const int r, const int c) const
-  {
-    return (RgbPixel &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels];
-  }
-};
-
-class RgbImageFloat : public ImageBase
-{
-public:
-  RgbImageFloat(IplImage* img = NULL) : ImageBase(img) { ; }
-
-  virtual void Clear()
-  {
-    cvZero(imgp);
-  }
-
-  void operator=(IplImage* img)
-  {
-    imgp = img;
-  }
-
-  // channel-level access using image(row, col, channel)
-  inline float& operator()(const int r, const int c, const int ch)
-  {
-    return (float &)imgp->imageData[r*imgp->widthStep + (c*imgp->nChannels + ch) * sizeof(float)];
-  }
-
-  inline float operator()(const int r, const int c, const int ch) const
-  {
-    return (float)imgp->imageData[r*imgp->widthStep + (c*imgp->nChannels + ch) * sizeof(float)];
-  }
-
-  // RGB pixel-level access using image(row, col)
-  inline RgbPixelFloat& operator()(const int r, const int c)
-  {
-    return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels * sizeof(float)];
-  }
-
-  inline const RgbPixelFloat& operator()(const int r, const int c) const
-  {
-    return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels * sizeof(float)];
-  }
-};
-
-class BwImage : public ImageBase
-{
-public:
-  BwImage(IplImage* img = NULL) : ImageBase(img) { ; }
-
-  virtual void Clear()
-  {
-    cvZero(imgp);
-  }
-
-  void operator=(IplImage* img)
-  {
-    imgp = img;
-  }
-
-  // pixel-level access using image(row, col)
-  inline unsigned char& operator()(const int r, const int c)
-  {
-    return (unsigned char &)imgp->imageData[r*imgp->widthStep + c];
-  }
-
-  inline unsigned char operator()(const int r, const int c) const
-  {
-    return (unsigned char)imgp->imageData[r*imgp->widthStep + c];
-  }
-};
-
-class BwImageFloat : public ImageBase
-{
-public:
-  BwImageFloat(IplImage* img = NULL) : ImageBase(img) { ; }
-
-  virtual void Clear()
-  {
-    cvZero(imgp);
-  }
-
-  void operator=(IplImage* img)
-  {
-    imgp = img;
-  }
-
-  // pixel-level access using image(row, col)
-  inline float& operator()(const int r, const int c)
-  {
-    return (float &)imgp->imageData[r*imgp->widthStep + c * sizeof(float)];
-  }
-
-  inline float operator()(const int r, const int c) const
-  {
-    return (float)imgp->imageData[r*imgp->widthStep + c * sizeof(float)];
-  }
-};
-
-// --- Image Functions --------------------------------------------------------
-
-void DensityFilter(BwImage& image, BwImage& filtered, int minDensity, unsigned char fgValue);
diff --git a/package_bgs/dp/TextureBGS.h b/package_bgs/dp/TextureBGS.h
deleted file mode 100644
index 2650f04cb1b55a8a71ce157e40b9806a73d7a8af..0000000000000000000000000000000000000000
--- a/package_bgs/dp/TextureBGS.h
+++ /dev/null
@@ -1,57 +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
-
-#include <math.h>
-#include "Image.h"
-
-const int REGION_R = 5;			// Note: the code currently assumes this value is <= 7
-const int TEXTURE_POINTS = 6;	// Note: the code currently assumes this value is 6
-const int TEXTURE_R = 2;		// Note: the code currently assumes this value is 2
-const int NUM_BINS = 64;		// 2^TEXTURE_POINTS
-const int HYSTERSIS = 3;
-const double ALPHA = 0.05f;
-const double THRESHOLD = 0.5*(REGION_R + REGION_R + 1)*(REGION_R + REGION_R + 1)*NUM_CHANNELS;
-const int NUM_MODES = 1;		// The paper describes how multiple modes can be maintained,
-// but this implementation does not fully support more than one
-
-struct TextureHistogram
-{
-  unsigned char r[NUM_BINS];	// histogram for red channel
-  unsigned char g[NUM_BINS];	// histogram for green channel
-  unsigned char b[NUM_BINS];	// histogram for blue channel
-};
-
-struct TextureArray
-{
-  TextureHistogram mode[NUM_MODES];
-};
-
-class TextureBGS
-{
-public:
-  TextureBGS();
-  ~TextureBGS();
-
-  void LBP(RgbImage& image, RgbImage& texture);
-  void Histogram(RgbImage& texture, TextureHistogram* curTextureHist);
-  int ProximityMeasure(TextureHistogram& bgTexture, TextureHistogram& curTextureHist);
-  void BgsCompare(TextureArray* bgModel, TextureHistogram* curTextureHist,
-    unsigned char* modeArray, float threshold, BwImage& fgMask);
-  void UpdateModel(BwImage& fgMask, TextureArray* bgModel,
-    TextureHistogram* curTextureHist, unsigned char* modeArray);
-};
diff --git a/package_bgs/dp/WrenGA.h b/package_bgs/dp/WrenGA.h
deleted file mode 100644
index 97e97ee7022c0ff3964332d083e93858fabe038c..0000000000000000000000000000000000000000
--- a/package_bgs/dp/WrenGA.h
+++ /dev/null
@@ -1,110 +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/>.
-*/
-/****************************************************************************
-*
-* WrenGA.hpp
-*
-* Purpose: Implementation of the running Gaussian average background
-*		  		 subtraction algorithm described in:
-*	  			 "Pfinder: real-time tracking of the human body"
-* 						by C. Wren et al (1997)
-*
-* Author: Donovan Parks, September 2007
-*
-* Please note that this is not an implementation of Pfinder. It implements
-* a simple background subtraction algorithm where each pixel is represented
-* by a single Gaussian and update using a simple weighting function.
-
-Example:
-Algorithms::BackgroundSubtraction::WrenParams params;
-params.SetFrameSize(width, height);
-params.LowThreshold() = 3.5f*3.5f;
-params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-params.Alpha() = 0.005f;
-params.LearningFrames() = 30;
-
-Algorithms::BackgroundSubtraction::WrenGA bgs;
-bgs.Initalize(params);
-******************************************************************************/
-#pragma once
-
-#include "Bgs.h"
-
-namespace Algorithms
-{
-  namespace BackgroundSubtraction
-  {
-    // --- Parameters used by the Mean BGS algorithm ---
-    class WrenParams : public BgsParams
-    {
-    public:
-      float &LowThreshold() { return m_low_threshold; }
-      float &HighThreshold() { return m_high_threshold; }
-
-      float &Alpha() { return m_alpha; }
-      int &LearningFrames() { return m_learning_frames; }
-
-    private:
-      // The threshold indicates the number of variances (not standard deviations) away
-      // from the mean before a pixel is considered to be from the foreground.
-      float m_low_threshold;
-      float m_high_threshold;
-
-      float m_alpha;
-      int m_learning_frames;
-    };
-
-
-    // --- Mean BGS algorithm ---
-    class WrenGA : public Bgs
-    {
-    private:
-      struct GAUSSIAN
-      {
-        float mu[NUM_CHANNELS];
-        float var[NUM_CHANNELS];
-      };
-
-    public:
-      WrenGA();
-      ~WrenGA();
-
-      void Initalize(const BgsParams& param);
-
-      void InitModel(const RgbImage& data);
-      void Subtract(int frame_num, const RgbImage& data,
-        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
-      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
-
-      RgbImage* Background() { return &m_background; }
-
-    private:
-      void SubtractPixel(int r, int c, const RgbPixel& pixel,
-        unsigned char& lowThreshold, unsigned char& highThreshold);
-
-      WrenParams m_params;
-
-      // Initial variance for the newly generated components.
-      float m_variance;
-
-      // dynamic array for the mixture of Gaussians
-      GAUSSIAN* m_gaussian;
-
-      RgbImage m_background;
-    };
-  }
-}
diff --git a/package_bgs/lb/BGModel.cpp b/package_bgs/lb/BGModel.cpp
deleted file mode 100644
index 3c73b53ce3f3ae7e8e4cb66304279ffd046fb85a..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModel.cpp
+++ /dev/null
@@ -1,87 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-  BGModel.cpp
-
-  Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  BGModel::BGModel(int width, int height) : m_width(width), m_height(height)
-  {
-    m_SrcImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
-    m_BGImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
-    m_FGImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
-
-    cvZero(m_SrcImage);
-    cvZero(m_BGImage);
-    cvZero(m_FGImage);
-  }
-
-  BGModel::~BGModel()
-  {
-    if (m_SrcImage != NULL) cvReleaseImage(&m_SrcImage);
-    if (m_BGImage != NULL) cvReleaseImage(&m_BGImage);
-    if (m_FGImage != NULL) cvReleaseImage(&m_FGImage);
-  }
-
-  IplImage* BGModel::GetSrc()
-  {
-    return m_SrcImage;
-  }
-
-  IplImage* BGModel::GetFG()
-  {
-    return m_FGImage;
-  }
-
-  IplImage* BGModel::GetBG()
-  {
-    return m_BGImage;
-  }
-
-  void BGModel::InitModel(IplImage* image)
-  {
-    cvCopy(image, m_SrcImage);
-    Init();
-    return;
-  }
-
-  void BGModel::UpdateModel(IplImage* image)
-  {
-    cvCopy(image, m_SrcImage);
-    Update();
-    return;
-  }
-}
diff --git a/package_bgs/lb/BGModel.h b/package_bgs/lb/BGModel.h
deleted file mode 100644
index d47ad6242bd40995a94337b7bb511d8979851837..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModel.h
+++ /dev/null
@@ -1,74 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-  BGModel.h
-
-  Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-    This program 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 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include <opencv2/opencv.hpp>
-#include <math.h>
-#include <float.h>
-
-#include "Types.h"
-
-namespace lb_library
-{
-  class BGModel
-  {
-  public:
-
-    BGModel(int width, int height);
-    virtual ~BGModel();
-
-    void InitModel(IplImage* image);
-    void UpdateModel(IplImage* image);
-
-    virtual void setBGModelParameter(int id, int value) {};
-
-    virtual IplImage* GetSrc();
-    virtual IplImage* GetFG();
-    virtual IplImage* GetBG();
-
-  protected:
-
-    IplImage* m_SrcImage;
-    IplImage* m_BGImage;
-    IplImage* m_FGImage;
-
-    const int m_width;
-    const int m_height;
-
-    virtual void Init() = 0;
-    virtual void Update() = 0;
-  };
-}
diff --git a/package_bgs/lb/BGModelFuzzyGauss.cpp b/package_bgs/lb/BGModelFuzzyGauss.cpp
deleted file mode 100644
index b249052bc4920a77bc49c1d7e0b9a0acb0fbcdfc..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelFuzzyGauss.cpp
+++ /dev/null
@@ -1,210 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelFuzzyGauss.cpp
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModelFuzzyGauss.h"
-
-namespace lb_library
-{
-  namespace FuzzyGaussian
-  {
-    BGModelFuzzyGauss::BGModelFuzzyGauss(int width, int height) : BGModel(width, height)
-    {
-      m_alphamax = ALPHAFUZZYGAUSS;
-      m_threshold = THRESHOLDFUZZYGAUSS * THRESHOLDFUZZYGAUSS;
-      m_threshBG = THRESHOLDBG;
-      m_noise = NOISEFUZZYGAUSS;
-
-      m_pMu = new DBLRGB[m_width * m_height];
-      m_pVar = new DBLRGB[m_width * m_height];
-
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      for (int k = 0; k < (m_width * m_height); k++)
-      {
-        pMu->Red = 0.0;
-        pMu->Green = 0.0;
-        pMu->Blue = 0.0;
-
-        pVar->Red = m_noise;
-        pVar->Green = m_noise;
-        pVar->Blue = m_noise;
-
-        pMu++;
-        pVar++;
-      }
-    }
-
-    BGModelFuzzyGauss::~BGModelFuzzyGauss()
-    {
-      delete[] m_pMu;
-      delete[] m_pVar;
-    }
-
-    void BGModelFuzzyGauss::setBGModelParameter(int id, int value)
-    {
-      double dvalue = (double)value / 255.0;
-
-      switch (id)
-      {
-      case 0:
-        m_threshold = 100.0*dvalue*dvalue;
-        break;
-
-      case 1:
-        m_threshBG = dvalue;
-        break;
-
-      case 2:
-        m_alphamax = dvalue*dvalue*dvalue;
-        break;
-
-      case 3:
-        m_noise = 100.0*dvalue;
-        break;
-      }
-
-      return;
-    }
-
-    void BGModelFuzzyGauss::Init()
-    {
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          pMu->Red = prgbSrc[i][j].Red;
-          pMu->Green = prgbSrc[i][j].Green;
-          pMu->Blue = prgbSrc[i][j].Blue;
-
-          pVar->Red = m_noise;
-          pVar->Green = m_noise;
-          pVar->Blue = m_noise;
-
-          pMu++;
-          pVar++;
-        }
-      }
-
-      return;
-    }
-
-    void BGModelFuzzyGauss::Update()
-    {
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-      Image<BYTERGB> prgbBG(m_BGImage);
-      Image<BYTERGB> prgbFG(m_FGImage);
-
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          double srcR = (double)prgbSrc[i][j].Red;
-          double srcG = (double)prgbSrc[i][j].Green;
-          double srcB = (double)prgbSrc[i][j].Blue;
-
-          // Fuzzy background subtraction (Mahalanobis distance)
-
-          double dr = srcR - pMu->Red;
-          double dg = srcG - pMu->Green;
-          double db = srcB - pMu->Blue;
-
-          double d2 = dr*dr / pVar->Red + dg*dg / pVar->Green + db*db / pVar->Blue;
-
-          double fuzzyBG = 1.0;
-
-          if (d2 < m_threshold)
-            fuzzyBG = d2 / m_threshold;
-
-          // Fuzzy running average
-
-          double alpha = m_alphamax*exp(FUZZYEXP*fuzzyBG);
-
-          if (dr*dr > DBL_MIN)
-            pMu->Red += alpha*dr;
-
-          if (dg*dg > DBL_MIN)
-            pMu->Green += alpha*dg;
-
-          if (db*db > DBL_MIN)
-            pMu->Blue += alpha*db;
-
-          double d;
-
-          d = (srcR - pMu->Red)*(srcR - pMu->Red) - pVar->Red;
-          if (d*d > DBL_MIN)
-            pVar->Red += alpha*d;
-
-          d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green;
-          if (d*d > DBL_MIN)
-            pVar->Green += alpha*d;
-
-          d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue;
-          if (d*d > DBL_MIN)
-            pVar->Blue += alpha*d;
-
-          pVar->Red = (std::max)(pVar->Red, m_noise);
-          pVar->Green = (std::max)(pVar->Green, m_noise);
-          pVar->Blue = (std::max)(pVar->Blue, m_noise);
-
-          // Set foreground and background
-
-          if (fuzzyBG >= m_threshBG)
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
-          else
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
-
-          prgbBG[i][j].Red = (unsigned char)pMu->Red;
-          prgbBG[i][j].Green = (unsigned char)pMu->Green;
-          prgbBG[i][j].Blue = (unsigned char)pMu->Blue;
-
-          pMu++;
-          pVar++;
-        }
-      }
-
-      return;
-    }
-  }
-}
diff --git a/package_bgs/lb/BGModelFuzzyGauss.h b/package_bgs/lb/BGModelFuzzyGauss.h
deleted file mode 100644
index a73b7165080675520c3d6995074acbd1954795be..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelFuzzyGauss.h
+++ /dev/null
@@ -1,71 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelFuzzyGauss.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  namespace FuzzyGaussian
-  {
-    const float ALPHAFUZZYGAUSS = 0.02f;
-    const float THRESHOLDFUZZYGAUSS = 3.5f;
-    const float THRESHOLDBG = 0.5f;
-    const float NOISEFUZZYGAUSS = 50.0f;
-    const float FUZZYEXP = -5.0f;
-
-    class BGModelFuzzyGauss : public BGModel
-    {
-    public:
-      BGModelFuzzyGauss(int width, int height);
-      ~BGModelFuzzyGauss();
-
-      void setBGModelParameter(int id, int value);
-
-    protected:
-      double m_alphamax;
-      double m_threshold;
-      double m_threshBG;
-      double m_noise;
-
-      DBLRGB* m_pMu;
-      DBLRGB* m_pVar;
-
-      void Init();
-      void Update();
-    };
-  }
-}
diff --git a/package_bgs/lb/BGModelFuzzySom.cpp b/package_bgs/lb/BGModelFuzzySom.cpp
deleted file mode 100644
index e7e59dda3b5c6c93209668edc50155c6d6d147bc..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelFuzzySom.cpp
+++ /dev/null
@@ -1,298 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelFuzzySom.cpp
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModelFuzzySom.h"
-
-namespace lb_library
-{
-  namespace FuzzyAdaptiveSOM
-  {
-    BGModelFuzzySom::BGModelFuzzySom(int width, int height) : BGModel(width, height)
-    {
-      m_offset = (KERNEL - 1) / 2;
-
-      if (SPAN_NEIGHBORS)
-        m_pad = 0;
-      else
-        m_pad = m_offset;
-
-      // SOM models
-
-      m_widthSOM = m_width*M + 2 * m_offset + (m_width - 1)*m_pad;
-      m_heightSOM = m_height*N + 2 * m_offset + (m_height - 1)*m_pad;
-
-      m_ppSOM = new DBLRGB*[m_heightSOM];
-      for (int n = 0; n < m_heightSOM; n++)
-        m_ppSOM[n] = new DBLRGB[m_widthSOM];
-
-      for (int j = 0; j < m_heightSOM; j++)
-      {
-        for (int i = 0; i < m_widthSOM; i++)
-        {
-          m_ppSOM[j][i].Red = 0.0;
-          m_ppSOM[j][i].Green = 0.0;
-          m_ppSOM[j][i].Blue = 0.0;
-        }
-      }
-
-      // Create weights
-
-      m_ppW = new double*[KERNEL];
-      for (int n = 0; n < KERNEL; n++)
-        m_ppW[n] = new double[KERNEL];
-
-      // Construct Gaussian kernel using Pascal's triangle
-
-      int cM;
-      int cN;
-      m_Wmax = DBL_MIN;
-
-      cN = 1;
-      for (int j = 0; j < KERNEL; j++)
-      {
-        cM = 1;
-
-        for (int i = 0; i < KERNEL; i++)
-        {
-          m_ppW[j][i] = cN*cM;
-
-          if (m_ppW[j][i] > m_Wmax)
-            m_Wmax = m_ppW[j][i];
-
-          cM = cM * (KERNEL - 1 - i) / (i + 1);
-        }
-
-        cN = cN * (KERNEL - 1 - j) / (j + 1);
-      }
-
-      // Parameters
-
-      m_epsilon1 = EPS1*EPS1;
-      m_epsilon2 = EPS2*EPS2;
-
-      m_alpha1 = C1 / m_Wmax;
-      m_alpha2 = C2 / m_Wmax;
-
-      m_K = 0;
-      m_TSteps = TRAINING_STEPS;
-    }
-
-    BGModelFuzzySom::~BGModelFuzzySom()
-    {
-      for (int n = 0; n < m_heightSOM; n++)
-        delete[] m_ppSOM[n];
-
-      delete[] m_ppSOM;
-
-      for (int n = 0; n < KERNEL; n++)
-        delete[] m_ppW[n];
-
-      delete[] m_ppW;
-    }
-
-    void BGModelFuzzySom::setBGModelParameter(int id, int value)
-    {
-      double dvalue = (double)value / 255.0;
-
-      switch (id)
-      {
-      case 0:
-        m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
-        break;
-
-      case 1:
-        m_epsilon1 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
-        break;
-
-      case 2:
-        m_alpha2 = dvalue*dvalue*dvalue / m_Wmax;
-        break;
-
-      case 3:
-        m_alpha1 = dvalue*dvalue*dvalue / m_Wmax;
-        break;
-
-      case 5:
-        m_TSteps = (int)(255.0*dvalue);
-        break;
-      }
-
-      return;
-    }
-
-    void BGModelFuzzySom::Init()
-    {
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-
-      for (int j = 0; j < m_height; j++)
-      {
-        int jj = m_offset + j*(N + m_pad);
-
-        for (int i = 0; i < m_width; i++)
-        {
-          int ii = m_offset + i*(M + m_pad);
-
-          for (int l = 0; l < N; l++)
-          {
-            for (int k = 0; k < M; k++)
-            {
-              m_ppSOM[jj + l][ii + k].Red = (double)prgbSrc[j][i].Red;
-              m_ppSOM[jj + l][ii + k].Green = (double)prgbSrc[j][i].Green;
-              m_ppSOM[jj + l][ii + k].Blue = (double)prgbSrc[j][i].Blue;
-            }
-          }
-        }
-      }
-
-      m_K = 0;
-
-      return;
-    }
-
-    void BGModelFuzzySom::Update()
-    {
-      double alpha, a;
-      double epsilon;
-
-      // calibration phase
-      if (m_K <= m_TSteps)
-      {
-        epsilon = m_epsilon1;
-        alpha = (m_alpha1 - m_K * (m_alpha1 - m_alpha2) / m_TSteps);
-        m_K++;
-      }
-      else // online phase
-      {
-        epsilon = m_epsilon2;
-        alpha = m_alpha2;
-      }
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-      Image<BYTERGB> prgbBG(m_BGImage);
-      Image<BYTERGB> prgbFG(m_FGImage);
-
-      for (int j = 0; j < m_height; j++)
-      {
-        int jj = m_offset + j*(N + m_pad);
-
-        for (int i = 0; i < m_width; i++)
-        {
-          int ii = m_offset + i*(M + m_pad);
-
-          double srcR = (double)prgbSrc[j][i].Red;
-          double srcG = (double)prgbSrc[j][i].Green;
-          double srcB = (double)prgbSrc[j][i].Blue;
-
-          // Find BMU
-
-          double d2min = DBL_MAX;
-          int iiHit = ii;
-          int jjHit = jj;
-
-          for (int l = 0; l < N; l++)
-          {
-            for (int k = 0; k < M; k++)
-            {
-              double dr = srcR - m_ppSOM[jj + l][ii + k].Red;
-              double dg = srcG - m_ppSOM[jj + l][ii + k].Green;
-              double db = srcB - m_ppSOM[jj + l][ii + k].Blue;
-
-              double d2 = dr*dr + dg*dg + db*db;
-
-              if (d2 < d2min)
-              {
-                d2min = d2;
-                iiHit = ii + k;
-                jjHit = jj + l;
-              }
-            }
-          }
-
-          double fuzzyBG = 1.0;
-
-          if (d2min < epsilon)
-            fuzzyBG = d2min / epsilon;
-
-          // Update SOM
-
-          double alphamax = alpha*exp(FUZZYEXP*fuzzyBG);
-
-          for (int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++)
-          {
-            for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++)
-            {
-              a = alphamax * m_ppW[l - jjHit + m_offset][k - iiHit + m_offset];
-
-              // speed hack.. avoid very small increment values. abs() is sloooow.
-
-              double d;
-
-              d = srcR - m_ppSOM[l][k].Red;
-              if (d*d > DBL_MIN)
-                m_ppSOM[l][k].Red += a*d;
-
-              d = srcG - m_ppSOM[l][k].Green;
-              if (d*d > DBL_MIN)
-                m_ppSOM[l][k].Green += a*d;
-
-              d = srcB - m_ppSOM[l][k].Blue;
-              if (d*d > DBL_MIN)
-                m_ppSOM[l][k].Blue += a*d;
-            }
-          }
-
-          if (fuzzyBG >= FUZZYTHRESH)
-          {
-            // Set foreground image
-            prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 255;
-          }
-          else
-          {
-            // Set background image
-            prgbBG[j][i].Red = m_ppSOM[jjHit][iiHit].Red;
-            prgbBG[j][i].Green = m_ppSOM[jjHit][iiHit].Green;
-            prgbBG[j][i].Blue = m_ppSOM[jjHit][iiHit].Blue;
-
-            // Set foreground image
-            prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 0;
-          }
-        }
-      }
-
-      return;
-    }
-  }
-}
diff --git a/package_bgs/lb/BGModelFuzzySom.h b/package_bgs/lb/BGModelFuzzySom.h
deleted file mode 100644
index ed0bf210e236a8acf02685c1e802be698ed4814d..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelFuzzySom.h
+++ /dev/null
@@ -1,91 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelFuzzySom.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  namespace FuzzyAdaptiveSOM
-  {
-    // SOM parameters
-
-    const int M = 3;				// width SOM (per pixel)
-    const int N = 3;				// height SOM (per pixel)
-    const int KERNEL = 3; 	// size Gaussian kernel
-
-    const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels			//
-    const int TRAINING_STEPS = 100;			// number of training steps
-
-    const double EPS1 = 100.0; // model match distance during training
-    const double EPS2 = 20.0;  // model match distance
-    const double C1 = 1.0;     // learning rate during training
-    const double C2 = 0.05;    // learning rate
-
-    const double FUZZYEXP = -5.0;
-    const double FUZZYTHRESH = 0.8;
-
-    class BGModelFuzzySom : public BGModel
-    {
-    public:
-      BGModelFuzzySom(int width, int height);
-      ~BGModelFuzzySom();
-
-      void setBGModelParameter(int id, int value);
-
-    protected:
-      int m_widthSOM;
-      int m_heightSOM;
-      int m_offset;
-      int m_pad;
-      int m_K;
-      int m_TSteps;
-
-      double m_Wmax;
-
-      double m_epsilon1;
-      double m_epsilon2;
-      double m_alpha1;
-      double m_alpha2;
-
-      DBLRGB** m_ppSOM;					// SOM grid
-      double** m_ppW;						// Weights
-
-      void Init();
-      void Update();
-    };
-  }
-}
diff --git a/package_bgs/lb/BGModelGauss.cpp b/package_bgs/lb/BGModelGauss.cpp
deleted file mode 100644
index 28a8b9379606f6a34600ec9d677e74343ad0a522..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelGauss.cpp
+++ /dev/null
@@ -1,200 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelGauss.cpp
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModelGauss.h"
-
-namespace lb_library
-{
-  namespace SimpleGaussian
-  {
-    BGModelGauss::BGModelGauss(int width, int height) : BGModel(width, height)
-    {
-      m_alpha = ALPHAGAUSS;
-      m_threshold = THRESHGAUSS*THRESHGAUSS;
-      m_noise = NOISEGAUSS;
-
-      m_pMu = new DBLRGB[m_width * m_height];
-      m_pVar = new DBLRGB[m_width * m_height];
-
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      for (int k = 0; k < (m_width * m_height); k++)
-      {
-        pMu->Red = 0.0;
-        pMu->Green = 0.0;
-        pMu->Blue = 0.0;
-
-        pVar->Red = m_noise;
-        pVar->Green = m_noise;
-        pVar->Blue = m_noise;
-
-        pMu++;
-        pVar++;
-      }
-    }
-
-    BGModelGauss::~BGModelGauss()
-    {
-      delete[] m_pMu;
-      delete[] m_pVar;
-    }
-
-    void BGModelGauss::setBGModelParameter(int id, int value)
-    {
-      double dvalue = (double)value / 255.0;
-
-      switch (id)
-      {
-      case 0:
-        m_threshold = 100.0*dvalue*dvalue;
-        break;
-
-      case 1:
-        m_noise = 100.0*dvalue;
-        break;
-
-      case 2:
-        m_alpha = dvalue*dvalue*dvalue;
-        break;
-      }
-
-      return;
-    }
-
-    void BGModelGauss::Init()
-    {
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          pMu->Red = prgbSrc[i][j].Red;
-          pMu->Green = prgbSrc[i][j].Green;
-          pMu->Blue = prgbSrc[i][j].Blue;
-
-          pVar->Red = m_noise;
-          pVar->Green = m_noise;
-          pVar->Blue = m_noise;
-
-          pMu++;
-          pVar++;
-        }
-      }
-
-      return;
-    }
-
-    void BGModelGauss::Update()
-    {
-      DBLRGB *pMu = m_pMu;
-      DBLRGB *pVar = m_pVar;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-      Image<BYTERGB> prgbBG(m_BGImage);
-      Image<BYTERGB> prgbFG(m_FGImage);
-
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          double srcR = (double)prgbSrc[i][j].Red;
-          double srcG = (double)prgbSrc[i][j].Green;
-          double srcB = (double)prgbSrc[i][j].Blue;
-
-          // Mahalanobis distance
-
-          double dr = srcR - pMu->Red;
-          double dg = srcG - pMu->Green;
-          double db = srcB - pMu->Blue;
-
-          double d2 = dr*dr / pVar->Red + dg*dg / pVar->Green + db*db / pVar->Blue;
-
-          // Classify
-
-          if (d2 < m_threshold)
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
-          else
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
-
-          // Update parameters
-
-          if (dr*dr > DBL_MIN)
-            pMu->Red += m_alpha*dr;
-
-          if (dg*dg > DBL_MIN)
-            pMu->Green += m_alpha*dg;
-
-          if (db*db > DBL_MIN)
-            pMu->Blue += m_alpha*db;
-
-          double d;
-
-          d = (srcR - pMu->Red)*(srcR - pMu->Red) - pVar->Red;
-          if (d*d > DBL_MIN)
-            pVar->Red += m_alpha*d;
-
-          d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green;
-          if (d*d > DBL_MIN)
-            pVar->Green += m_alpha*d;
-
-          d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue;
-          if (d*d > DBL_MIN)
-            pVar->Blue += m_alpha*d;
-
-          pVar->Red = (std::min)(pVar->Red, m_noise);
-          pVar->Green = (std::min)(pVar->Green, m_noise);
-          pVar->Blue = (std::min)(pVar->Blue, m_noise);
-
-          // Set background
-
-          prgbBG[i][j].Red = (unsigned char)pMu->Red;
-          prgbBG[i][j].Green = (unsigned char)pMu->Green;
-          prgbBG[i][j].Blue = (unsigned char)pMu->Blue;
-
-          pMu++;
-          pVar++;
-        }
-      }
-
-      return;
-    }
-  }
-}
diff --git a/package_bgs/lb/BGModelGauss.h b/package_bgs/lb/BGModelGauss.h
deleted file mode 100644
index 0af6efe7beb9207d185ff15fc1d18df8c3657f3f..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelGauss.h
+++ /dev/null
@@ -1,69 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelGauss.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  namespace SimpleGaussian
-  {
-    // Parameters
-    const double THRESHGAUSS = 2.5;   // Threshold
-    const double ALPHAGAUSS = 0.0001; // Learning rate
-    const double NOISEGAUSS = 50.0;   // Minimum variance (noise)
-
-    class BGModelGauss : public BGModel
-    {
-    public:
-      BGModelGauss(int width, int height);
-      ~BGModelGauss();
-
-      void setBGModelParameter(int id, int value);
-
-    protected:
-      double m_alpha;
-      double m_threshold;
-      double m_noise;
-
-      DBLRGB* m_pMu;
-      DBLRGB* m_pVar;
-
-      void Init();
-      void Update();
-    };
-  }
-}
diff --git a/package_bgs/lb/BGModelMog.cpp b/package_bgs/lb/BGModelMog.cpp
deleted file mode 100644
index 036feabf1aaa3a819d3f816f43b98d97772c0a1e..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelMog.cpp
+++ /dev/null
@@ -1,309 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelMog.cpp
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModelMog.h"
-
-namespace lb_library
-{
-  namespace MixtureOfGaussians
-  {
-    BGModelMog::BGModelMog(int width, int height) : BGModel(width, height)
-    {
-      m_alpha = LEARNINGRATEMOG;
-      m_threshold = THRESHOLDMOG*THRESHOLDMOG;
-      m_noise = INITIALVARMOG;
-
-      m_T = BGTHRESHOLDMOG;
-
-      m_pMOG = new MOGDATA[NUMBERGAUSSIANS*m_width*m_height];
-      m_pK = new int[m_width*m_height];
-
-      MOGDATA *pMOG = m_pMOG;
-      int *pK = m_pK;
-
-      for (int i = 0; i < (m_width * m_height); i++)
-      {
-        for (int k = 0; k < NUMBERGAUSSIANS; k++)
-        {
-          pMOG->mu.Red = 0.0;
-          pMOG->mu.Green = 0.0;
-          pMOG->mu.Blue = 0.0;
-
-          pMOG->var.Red = 0.0;
-          pMOG->var.Green = 0.0;
-          pMOG->var.Blue = 0.0;
-
-          pMOG->w = 0.0;
-          pMOG->sortKey = 0.0;
-
-          pMOG++;
-        }
-
-        pK[i] = 0;
-      }
-    }
-
-    BGModelMog::~BGModelMog()
-    {
-      delete[] m_pMOG;
-      delete[] m_pK;
-    }
-
-    void BGModelMog::setBGModelParameter(int id, int value)
-    {
-      double dvalue = (double)value / 255.0;
-
-      switch (id)
-      {
-      case 0:
-        m_threshold = 100.0*dvalue*dvalue;
-        break;
-
-      case 1:
-        m_T = dvalue;
-        break;
-
-      case 2:
-        m_alpha = dvalue*dvalue*dvalue;
-        break;
-
-      case 3:
-        m_noise = 100.0*dvalue;;
-        break;
-      }
-
-      return;
-    }
-
-    void BGModelMog::Init()
-    {
-      MOGDATA *pMOG = m_pMOG;
-      int *pK = m_pK;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-
-      int n = 0;
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          pMOG[0].mu.Red = prgbSrc[i][j].Red;
-          pMOG[0].mu.Green = prgbSrc[i][j].Green;
-          pMOG[0].mu.Blue = prgbSrc[i][j].Blue;
-
-          pMOG[0].var.Red = m_noise;
-          pMOG[0].var.Green = m_noise;
-          pMOG[0].var.Blue = m_noise;
-
-          pMOG[0].w = 1.0;
-          pMOG[0].sortKey = pMOG[0].w / sqrt(pMOG[0].var.Red + pMOG[0].var.Green + pMOG[0].var.Blue);
-
-          pK[n] = 1;
-          n++;
-
-          pMOG += NUMBERGAUSSIANS;
-        }
-      }
-
-      return;
-    }
-
-    void BGModelMog::Update()
-    {
-      int kBG;
-
-      MOGDATA *pMOG = m_pMOG;
-      int *pK = m_pK;
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-      Image<BYTERGB> prgbBG(m_BGImage);
-      Image<BYTERGB> prgbFG(m_FGImage);
-
-      int n = 0;
-      for (int i = 0; i < m_height; i++)
-      {
-        for (int j = 0; j < m_width; j++)
-        {
-          double srcR = (double)prgbSrc[i][j].Red;
-          double srcG = (double)prgbSrc[i][j].Green;
-          double srcB = (double)prgbSrc[i][j].Blue;
-
-          // Find matching distribution
-
-          int kHit = -1;
-
-          for (int k = 0; k < pK[n]; k++)
-          {
-            // Mahalanobis distance
-            double dr = srcR - pMOG[k].mu.Red;
-            double dg = srcG - pMOG[k].mu.Green;
-            double db = srcB - pMOG[k].mu.Blue;
-            double d2 = dr*dr / pMOG[k].var.Red + dg*dg / pMOG[k].var.Green + db*db / pMOG[k].var.Blue;
-
-            if (d2 < m_threshold)
-            {
-              kHit = k;
-              break;
-            }
-          }
-
-          // Adjust parameters
-
-          // matching distribution found
-          if (kHit != -1)
-          {
-            for (int k = 0; k < pK[n]; k++)
-            {
-              if (k == kHit)
-              {
-                pMOG[k].w = pMOG[k].w + m_alpha*(1.0f - pMOG[k].w);
-
-                double d;
-
-                d = srcR - pMOG[k].mu.Red;
-                if (d*d > DBL_MIN)
-                  pMOG[k].mu.Red += m_alpha*d;
-
-                d = srcG - pMOG[k].mu.Green;
-                if (d*d > DBL_MIN)
-                  pMOG[k].mu.Green += m_alpha*d;
-
-                d = srcB - pMOG[k].mu.Blue;
-                if (d*d > DBL_MIN)
-                  pMOG[k].mu.Blue += m_alpha*d;
-
-                d = (srcR - pMOG[k].mu.Red)*(srcR - pMOG[k].mu.Red) - pMOG[k].var.Red;
-                if (d*d > DBL_MIN)
-                  pMOG[k].var.Red += m_alpha*d;
-
-                d = (srcG - pMOG[k].mu.Green)*(srcG - pMOG[k].mu.Green) - pMOG[k].var.Green;
-                if (d*d > DBL_MIN)
-                  pMOG[k].var.Green += m_alpha*d;
-
-                d = (srcB - pMOG[k].mu.Blue)*(srcB - pMOG[k].mu.Blue) - pMOG[k].var.Blue;
-                if (d*d > DBL_MIN)
-                  pMOG[k].var.Blue += m_alpha*d;
-
-                pMOG[k].var.Red = (std::max)(pMOG[k].var.Red, m_noise);
-                pMOG[k].var.Green = (std::max)(pMOG[k].var.Green, m_noise);
-                pMOG[k].var.Blue = (std::max)(pMOG[k].var.Blue, m_noise);
-              }
-              else
-                pMOG[k].w = (1.0 - m_alpha)*pMOG[k].w;
-            }
-          }
-          // no match found... create new one
-          else
-          {
-            if (pK[n] < NUMBERGAUSSIANS)
-              pK[n]++;
-
-            kHit = pK[n] - 1;
-
-            if (pK[n] == 1)
-              pMOG[kHit].w = 1.0;
-            else
-              pMOG[kHit].w = LEARNINGRATEMOG;
-
-            pMOG[kHit].mu.Red = srcR;
-            pMOG[kHit].mu.Green = srcG;
-            pMOG[kHit].mu.Blue = srcB;
-
-            pMOG[kHit].var.Red = m_noise;
-            pMOG[kHit].var.Green = m_noise;
-            pMOG[kHit].var.Blue = m_noise;
-          }
-
-          // Normalize weights
-
-          double wsum = 0.0;
-
-          for (int k = 0; k < pK[n]; k++)
-            wsum += pMOG[k].w;
-
-          double wfactor = 1.0 / wsum;
-
-          for (int k = 0; k < pK[n]; k++)
-          {
-            pMOG[k].w *= wfactor;
-            pMOG[k].sortKey = pMOG[k].w / sqrt(pMOG[k].var.Red + pMOG[k].var.Green + pMOG[k].var.Blue);
-          }
-
-          // Sort distributions
-
-          for (int k = 0; k < kHit; k++)
-          {
-            if (pMOG[kHit].sortKey > pMOG[k].sortKey)
-            {
-              std::swap(pMOG[kHit], pMOG[k]);
-              break;
-            }
-          }
-
-          // Determine background distributions
-
-          wsum = 0.0;
-
-          for (int k = 0; k < pK[n]; k++)
-          {
-            wsum += pMOG[k].w;
-
-            if (wsum > m_T)
-            {
-              kBG = k;
-              break;
-            }
-          }
-
-          if (kHit > kBG)
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
-          else
-            prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
-
-          prgbBG[i][j].Red = (unsigned char)pMOG[0].mu.Red;
-          prgbBG[i][j].Green = (unsigned char)pMOG[0].mu.Green;
-          prgbBG[i][j].Blue = (unsigned char)pMOG[0].mu.Blue;
-
-          pMOG += NUMBERGAUSSIANS;
-
-          n++;
-        }
-      }
-
-      return;
-    }
-  }
-}
diff --git a/package_bgs/lb/BGModelMog.h b/package_bgs/lb/BGModelMog.h
deleted file mode 100644
index c75d1fdee92df5ebba23358f3321fcd06114c661..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelMog.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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelMog.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  namespace MixtureOfGaussians
-  {
-    const unsigned int NUMBERGAUSSIANS = 3;
-    const float LEARNINGRATEMOG = 0.001f;
-    const float THRESHOLDMOG = 2.5f;
-    const float BGTHRESHOLDMOG = 0.5f;
-    const float INITIALVARMOG = 50.0f;
-
-    typedef struct tagMOGDATA
-    {
-      DBLRGB mu;
-      DBLRGB var;
-      double w;
-      double sortKey;
-    } MOGDATA;
-
-    class BGModelMog : public BGModel
-    {
-    public:
-      BGModelMog(int width, int height);
-      ~BGModelMog();
-
-      void setBGModelParameter(int id, int value);
-
-    protected:
-      double m_alpha;
-      double m_threshold;
-      double m_noise;
-      double m_T;
-
-      MOGDATA* m_pMOG;
-      int* m_pK;				// number of distributions per pixel
-
-      void Init();
-      void Update();
-    };
-  }
-}
diff --git a/package_bgs/lb/BGModelSom.cpp b/package_bgs/lb/BGModelSom.cpp
deleted file mode 100644
index 085fd9d575ecedb762c1048e710b2d6adf467675..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelSom.cpp
+++ /dev/null
@@ -1,290 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelSom.cpp
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "BGModelSom.h"
-
-namespace lb_library
-{
-  namespace AdaptiveSOM
-  {
-    BGModelSom::BGModelSom(int width, int height) : BGModel(width, height)
-    {
-      m_offset = (KERNEL - 1) / 2;
-
-      if (SPAN_NEIGHBORS)
-        m_pad = 0;
-      else
-        m_pad = m_offset;
-
-      // SOM models
-
-      m_widthSOM = m_width*M + 2 * m_offset + (m_width - 1)*m_pad;
-      m_heightSOM = m_height*N + 2 * m_offset + (m_height - 1)*m_pad;
-
-      m_ppSOM = new DBLRGB*[m_heightSOM];
-      for (int n = 0; n < m_heightSOM; n++)
-        m_ppSOM[n] = new DBLRGB[m_widthSOM];
-
-      for (int j = 0; j < m_heightSOM; j++)
-      {
-        for (int i = 0; i < m_widthSOM; i++)
-        {
-          m_ppSOM[j][i].Red = 0.0;
-          m_ppSOM[j][i].Green = 0.0;
-          m_ppSOM[j][i].Blue = 0.0;
-        }
-      }
-
-      // Create weights
-      m_ppW = new double*[KERNEL];
-      for (int n = 0; n < KERNEL; n++)
-        m_ppW[n] = new double[KERNEL];
-
-      // Construct Gaussian kernel using Pascal's triangle
-
-      int cM;
-      int cN;
-      m_Wmax = DBL_MIN;
-
-      cN = 1;
-      for (int j = 0; j < KERNEL; j++)
-      {
-        cM = 1;
-
-        for (int i = 0; i < KERNEL; i++)
-        {
-          m_ppW[j][i] = cN*cM;
-
-          if (m_ppW[j][i] > m_Wmax)
-            m_Wmax = m_ppW[j][i];
-
-          cM = cM * (KERNEL - 1 - i) / (i + 1);
-        }
-
-        cN = cN * (KERNEL - 1 - j) / (j + 1);
-      }
-
-      // Parameters
-
-      m_epsilon1 = EPS1*EPS1;
-      m_epsilon2 = EPS2*EPS2;
-
-      m_alpha1 = C1 / m_Wmax;
-      m_alpha2 = C2 / m_Wmax;
-
-      m_K = 0;
-      m_TSteps = TRAINING_STEPS;
-    }
-
-    BGModelSom::~BGModelSom()
-    {
-      for (int n = 0; n < m_heightSOM; n++)
-        delete[] m_ppSOM[n];
-
-      delete[] m_ppSOM;
-
-      for (int n = 0; n < KERNEL; n++)
-        delete[] m_ppW[n];
-
-      delete[] m_ppW;
-    }
-
-    void BGModelSom::setBGModelParameter(int id, int value)
-    {
-      double dvalue = (double)value / 255.0;
-
-      switch (id)
-      {
-      case 0:
-        m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
-        break;
-
-      case 1:
-        m_epsilon1 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
-        break;
-
-      case 2:
-        m_alpha2 = dvalue*dvalue*dvalue / m_Wmax;
-        break;
-
-      case 3:
-        m_alpha1 = dvalue*dvalue*dvalue / m_Wmax;
-        break;
-
-      case 5:
-        m_TSteps = (int)(255.0*dvalue);
-        break;
-      }
-
-      return;
-    }
-
-    void BGModelSom::Init()
-    {
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-
-      for (int j = 0; j < m_height; j++)
-      {
-        int jj = m_offset + j*(N + m_pad);
-
-        for (int i = 0; i < m_width; i++)
-        {
-          int ii = m_offset + i*(M + m_pad);
-
-          for (int l = 0; l < N; l++)
-          {
-            for (int k = 0; k < M; k++)
-            {
-              m_ppSOM[jj + l][ii + k].Red = (double)prgbSrc[j][i].Red;
-              m_ppSOM[jj + l][ii + k].Green = (double)prgbSrc[j][i].Green;
-              m_ppSOM[jj + l][ii + k].Blue = (double)prgbSrc[j][i].Blue;
-            }
-          }
-        }
-      }
-
-      m_K = 0;
-
-      return;
-    }
-
-    void BGModelSom::Update()
-    {
-      double alpha, a;
-      double epsilon;
-
-      // calibration phase
-      if (m_K <= m_TSteps)
-      {
-        epsilon = m_epsilon1;
-        alpha = (m_alpha1 - m_K*(m_alpha1 - m_alpha2) / m_TSteps);
-        m_K++;
-      }
-      else // online phase
-      {
-        epsilon = m_epsilon2;
-        alpha = m_alpha2;
-      }
-
-      Image<BYTERGB> prgbSrc(m_SrcImage);
-      Image<BYTERGB> prgbBG(m_BGImage);
-      Image<BYTERGB> prgbFG(m_FGImage);
-
-      for (int j = 0; j < m_height; j++)
-      {
-        int jj = m_offset + j*(N + m_pad);
-
-        for (int i = 0; i < m_width; i++)
-        {
-          int ii = m_offset + i*(M + m_pad);
-
-          double srcR = (double)prgbSrc[j][i].Red;
-          double srcG = (double)prgbSrc[j][i].Green;
-          double srcB = (double)prgbSrc[j][i].Blue;
-
-          // Find BMU
-
-          double d2min = DBL_MAX;
-          int iiHit = ii;
-          int jjHit = jj;
-
-          for (int l = 0; l < N; l++)
-          {
-            for (int k = 0; k < M; k++)
-            {
-              double dr = srcR - m_ppSOM[jj + l][ii + k].Red;
-              double dg = srcG - m_ppSOM[jj + l][ii + k].Green;
-              double db = srcB - m_ppSOM[jj + l][ii + k].Blue;
-
-              double d2 = dr*dr + dg*dg + db*db;
-
-              if (d2 < d2min)
-              {
-                d2min = d2;
-                iiHit = ii + k;
-                jjHit = jj + l;
-              }
-            }
-          }
-
-          // Update SOM
-
-          if (d2min <= epsilon) // matching model found
-          {
-            for (int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++)
-            {
-              for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++)
-              {
-                a = alpha*m_ppW[l - jjHit + m_offset][k - iiHit + m_offset];
-
-                // speed hack.. avoid very small increment values. abs() is sloooow.
-
-                double d;
-
-                d = srcR - m_ppSOM[l][k].Red;
-                if (d*d > DBL_MIN)
-                  m_ppSOM[l][k].Red += a*d;
-
-                d = srcG - m_ppSOM[l][k].Green;
-                if (d*d > DBL_MIN)
-                  m_ppSOM[l][k].Green += a*d;
-
-                d = srcB - m_ppSOM[l][k].Blue;
-                if (d*d > DBL_MIN)
-                  m_ppSOM[l][k].Blue += a*d;
-              }
-            }
-
-            // Set background image
-            prgbBG[j][i].Red = m_ppSOM[jjHit][iiHit].Red;
-            prgbBG[j][i].Green = m_ppSOM[jjHit][iiHit].Green;
-            prgbBG[j][i].Blue = m_ppSOM[jjHit][iiHit].Blue;
-
-            // Set foreground image
-            prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 0;
-          }
-          else
-          {
-            // Set foreground image
-            prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 255;
-          }
-        }
-      }
-
-      return;
-    }
-  }
-}
diff --git a/package_bgs/lb/BGModelSom.h b/package_bgs/lb/BGModelSom.h
deleted file mode 100644
index 0975b0b3e38d89a3e2b2e734e9c1d3c5bb4686ab..0000000000000000000000000000000000000000
--- a/package_bgs/lb/BGModelSom.h
+++ /dev/null
@@ -1,88 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments
-BGModelSom.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include "BGModel.h"
-
-namespace lb_library
-{
-  namespace AdaptiveSOM
-  {
-    // SOM parameters
-
-    const int M = 3;				// width SOM (per pixel)
-    const int N = 3;				// height SOM (per pixel)
-    const int KERNEL = 3; 	// size Gaussian kernel
-
-    const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels			//
-    const int TRAINING_STEPS = 100;			// number of training steps
-
-    const float EPS1 = 100.0; // model match distance during training
-    const float EPS2 = 20.0;  // model match distance
-    const float C1 = 1.0;     // learning rate during training
-    const float C2 = 0.05f;    // learning rate
-
-    class BGModelSom : public BGModel
-    {
-    public:
-      BGModelSom(int width, int height);
-      ~BGModelSom();
-
-      void setBGModelParameter(int id, int value);
-
-    protected:
-      int m_widthSOM;
-      int m_heightSOM;
-      int m_offset;
-      int m_pad;
-      int m_K;
-      int m_TSteps;
-
-      double m_Wmax;
-
-      double m_epsilon1;
-      double m_epsilon2;
-      double m_alpha1;
-      double m_alpha2;
-
-      DBLRGB** m_ppSOM;					// SOM grid
-      double** m_ppW;						// Weights
-
-      void Init();
-      void Update();
-    };
-  }
-}
diff --git a/package_bgs/lb/Types.h b/package_bgs/lb/Types.h
deleted file mode 100644
index bd59c41eaba01dc5f8642a7bf40c365f5c61758f..0000000000000000000000000000000000000000
--- a/package_bgs/lb/Types.h
+++ /dev/null
@@ -1,93 +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/>.
-*/
-/*  Scene 1.0.1 -- Background subtraction and object tracking for complex environments  
-Types.h
-
-Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar>
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#pragma once
-
-#include <opencv2/opencv.hpp>
-
-namespace lb_library
-{
-template<class T> class Image
-{
-private:
-  IplImage* imgp;
-
-public:
-  Image(IplImage* img=0) {imgp=img;}
-  ~Image(){imgp=0;}
-  
-  void operator=(IplImage* img) {imgp=img;}
-  
-  inline T* operator[](const int rowIndx)
-  {
-    return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));
-  }
-};
-
-typedef struct{
-  unsigned char b,g,r;
-} RgbPixel;
-
-typedef struct{
-  unsigned char Blue,Green,Red;
-} BYTERGB;
-
-typedef struct{
-  unsigned int Blue,Green,Red;
-} INTRGB;
-
-typedef struct{
-  float b,g,r;
-}RgbPixelFloat;
-
-typedef struct{
-  double Blue,Green,Red;
-} DBLRGB;
-
-typedef Image<RgbPixel>       RgbImage;
-typedef Image<RgbPixelFloat>  RgbImageFloat;
-typedef Image<unsigned char>  BwImage;
-typedef Image<float>          BwImageFloat;
-
-/*
-  IplImage* img = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 3);
-  RgbImageFloat imgA(img);
-  for(int i = 0; i < m_height; i++)
-    for(int j = 0; j < m_width; j++)
-      imgA[i][j].b = 111;
-      imgA[i][j].g = 111;
-      imgA[i][j].r = 111;
-  */
-}
diff --git a/package_bgs/ttoolbox.cpp b/package_bgs/ttoolbox.cpp
deleted file mode 100644
index d1734221196f4b002065fff5d46f0b3a76d4fb30..0000000000000000000000000000000000000000
--- a/package_bgs/ttoolbox.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "ttoolbox.h"
-
-std::string TToolBox::mNzero(int i)
-{
-    std::ostringstream convert;
-    convert << i ;
-    std::string numberString = convert.str();
-    std::string newNumberString = std::string(10 - numberString.length(), '0') + numberString;
-    return newNumberString;
-}
-std::string TToolBox::getFileName(int i)
-{
-    std::string fileName =std::string ( std::string ("/data/")+  mNzero(i) + std::string (".jpg"));
-    return fileName;
-}
-
-std::vector<std::vector<cv::Point>> TToolBox::applyCannyEdgeAndCalcCountours(cv::Mat imgSource, double threshholdMin, double threshholdMax, int apertureSize)
-{
-    cv::Mat imgCannyEdge;
-    std::vector<std::vector<cv::Point> > contours;
-    std::vector<cv::Vec4i> hierarchy;
-
-    //! 2 make a copy
-    cv::Mat imgBinary = imgSource.clone();
-    //imgMarkBinary = Scalar(255,255,255); //fill white
-
-    //! 3 apply binary filter not reduce noise
-    //method to threshold important changes
-    int binaryThreshold = 80; //TODO as parameter
-    imgBinary = imgSource > binaryThreshold;
-
-
-    //! 4 smooth with gaussian filter to suppress no connected lines
-    //add a gaussian filter //see http://docs.opencv.org/2.4/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.html
-    cv::Mat imgSmoothed = imgBinary.clone();
-    int exclusPara3 = 3; //TODO as parameter
-    cv::GaussianBlur(imgBinary,imgSmoothed,cv::Size(exclusPara3,exclusPara3),0);  //0 = BORDER_CONSTANT
-
-    //! 5 we make the canny edge detect
-    // Detect edges using canny
-    cv::Canny( imgSmoothed, imgCannyEdge, threshholdMin, threshholdMax, apertureSize );
-
-    // Find contours, use RETR_EXTERNAL ignore inner child structures, TREE more usefull ?
-    cv::findContours( imgCannyEdge, contours, hierarchy, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
-
-#define MC_SHOW_STEP_ANALYSE
-#ifdef  MC_SHOW_STEP_ANALYSE
-    // Draw contours on extra mat
-    cv::Mat imgContour = cv::Mat::zeros( imgCannyEdge.size(), CV_8UC3 );
-    imgContour =  cv::Scalar(255,255,255); //fille the picture
-    cv::RNG rng(232323);
-    for( size_t i = 0; i< contours.size(); i++ )
-    {
-        //random color
-        cv::Scalar color = cv::Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
-        //contour
-        cv::drawContours( imgContour, contours, i, color, 1, cv::LINE_AA, hierarchy, 0, cv::Point() );
-    }
-
-    cv::String outpath=  "/homes/tb55xemi/work/dev/bgslibrary-bgslib_qtgui_2.0.0/build/test0815/results";
-    std::ostringstream convert;
-    convert << outpath << "test_countour_canny_edge.jpg";
-    cv::imwrite(convert.str().c_str(), imgContour);
-
-#endif
-
-    //    return minRect;
-    return contours;
-}
-
-
-cv::Mat TToolBox::cropImageCircle(cv::Mat image, int x, int y, int r)
-{
-
-    // Your Hough circle
-    cv::Vec3f circ(x,y,r);
-
-    // Draw the mask: white circle on black background
-    cv::Mat1b mask(image.size(), uchar(0));
-    cv::circle(mask, cv::Point(circ[0], circ[1]), circ[2], cv::Scalar(255), CV_FILLED);
-
-    //NO CROP NEEDED
-
-    // Compute the bounding box
-    //Rect bbox(circ[0] - circ[2], circ[1] - circ[2], 2 * circ[2], 2 * circ[2]);
-
-    // Create a black image
-    cv::Mat res = cv::Mat::zeros( image.size(), CV_8UC3 );
-    res = cv::Scalar(0,0,0); //fill with black color
-
-
-    // Copy only the image under the white circle to black image
-    image.copyTo(res, mask);
-
-    // Crop according to the roi
-    //res = res(bbox);
-
-    return res;
-}
-
-int TToolBox::checkFileCorrupted(std::string filename)
-{
-    int retVal = 1;//is as long Corrupted as we dont find it in another way
-    char command[] =  "identify ";
-    const char *fileNameArr = filename.c_str();
-    char command2[] = " > /dev/null 2>&1 ; echo $?";
-    char *cmd = new char[std::strlen(command)+std::strlen(fileNameArr) + std::strlen(command2) +1];
-    //we put all peaces together
-    std::strcpy(cmd,command);
-    std::strcat(cmd,fileNameArr);
-    std::strcat(cmd,command2);
-
-    //std:: cout <<"cmd is: "<< cmd<< std::endl;
-    //execute the command
-    std::string result = TToolBox::execCMD((const char* ) cmd);
-
-    //std:: cout <<"results is: "<< result<< std::endl;
-
-    if(!result.empty())
-    {
-        try {
-            retVal = std::stoi(result);
-        }
-        catch(std::invalid_argument& e)
-        {
-            std::cerr <<"wrong argument for stoi"<<std::endl;
-            // if no conversion could be performed
-        }
-        catch (const std::exception& e)
-        {
-            std::cerr <<"error during use stoi"<<std::endl;
-        }
-
-    }//end if
-    return retVal;
-}
-
-
-std::string TToolBox::execCMD(const char* cmd) {
-    std::array<char, 128> buffer;
-    std::string result;
-    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
-    if (!pipe) throw std::runtime_error("popen() failed!");
-    while (!feof(pipe.get())) {
-        if (fgets(buffer.data(), 128, pipe.get()) != nullptr)
-            result += buffer.data();
-        //std::cout<<result<<std::endl;
-
-    }
-    //std::cout<<"call:       " <<result<<std::endl;
-    return result;
-}
diff --git a/package_bgs/ttoolbox.h b/package_bgs/ttoolbox.h
deleted file mode 100644
index ee2ca9b194ff94b72a7c73bf7382b640c556bb8d..0000000000000000000000000000000000000000
--- a/package_bgs/ttoolbox.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef TTOOLBOX_H
-#define TTOOLBOX_H
-
-//cpp,c
-#include <iostream>
-#include <algorithm>
-#include <cstdlib>
-#include <stdio.h>      /* printf, scanf, puts, NULL */
-#include <stdlib.h>     /* srand, rand */
-#include <time.h>       /* time */
-#include <ctime>
-#include <sstream>
-#include <cstdio>
-#include <memory>
-#include <stdexcept>
-#include <string>
-#include <array>
-
-//open cv
-#include "opencv2/core/core.hpp"
-#include "opencv2/opencv.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
-#include "opencv2/highgui/highgui.hpp"
-
-class TToolBox
-{
-public:
-
-    //! return the number as string with 10 digits and '0' leading ones
-    static std::string mNzero(int i);
-
-    //! return string plus data path and jpg suffix
-    static std::string getFileName(int i);
-
-    //! returns a image, which is resulting circle
-    //! return roi of image which is cloned
-    //! without resize the image
-    //! will fill rest outer bound black
-    static cv::Mat cropImageCircle(cv::Mat image, int x, int y, int r);
-
-    //! canny edge detect
-    static std::vector<std::vector<cv::Point>> applyCannyEdgeAndCalcCountours(cv::Mat imgSource, double threshholdMin, double threshholdMax, int apertureSize);
-
-    //! will test if file is not corrupted
-    //! @return 1 if corrupted
-    //! @return 0 if not
-    static int checkFileCorrupted(std::string filename);
-
-    //! will try to execute the cmd on the bash
-    static  std::string execCMD(const char* cmd);
-
-};
-
-#endif // TTOOLBOX_H
diff --git a/run_camera.sh b/run_camera.sh
old mode 100644
new mode 100755
diff --git a/run_demo.bat b/run_demo.bat
deleted file mode 100644
index 216799f8900d773d549911bf38cd3912852c8696..0000000000000000000000000000000000000000
--- a/run_demo.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-cls
-build\bgs_demo.exe dataset/video.avi
\ No newline at end of file
diff --git a/run_demo.sh b/run_demo.sh
deleted file mode 100644
index 2a7777d5e5b066801a5796ef97c1f897fe72cc86..0000000000000000000000000000000000000000
--- a/run_demo.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-./build/bgs_demo dataset/video.avi
diff --git a/run_demo2.bat b/run_demo2.bat
deleted file mode 100644
index c7aba15dc94e81110847b01d69cc0e774d4a4207..0000000000000000000000000000000000000000
--- a/run_demo2.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-cls
-build\bgs_demo2.exe
\ No newline at end of file
diff --git a/run_demo2.sh b/run_demo2.sh
deleted file mode 100644
index 910099c2d147bed6ea5622d00b54dbfa7a13ed29..0000000000000000000000000000000000000000
--- a/run_demo2.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-./build/bgs_demo2
diff --git a/run_video.sh b/run_video.sh
old mode 100644
new mode 100755
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0dc4dcd09b891ff5a6a571878647efdf7dcc88c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,216 @@
+"""
+To build the bgslibrary:
+    python setup.py build
+To build and install:
+    python setup.py install
+To install using pip:
+    pip install .
+To install using PyPI:
+    pip install pybgs
+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/pybgs-*.tar.gz
+"""
+import os, re, sys, shutil, platform, subprocess
+
+from setuptools import setup, find_packages, Extension
+from setuptools.command.build_ext import build_ext
+from setuptools.command.install_lib import install_lib
+from setuptools.command.install_scripts import install_scripts
+from distutils.command.install_data import install_data
+from distutils.version import LooseVersion
+
+PACKAGE_NAME = "pybgs"
+
+class CMakeExtension(Extension):
+    def __init__(self, name, sourcedir=''):
+        Extension.__init__(self, name, sources=[])
+        self.sourcedir = os.path.abspath(sourcedir)
+
+class InstallCMakeLibsData(install_data):
+    """
+    Just a wrapper to get the install data into the egg-info
+
+    Listing the installed files in the egg-info guarantees that
+    all of the package files will be uninstalled when the user
+    uninstalls your package through pip
+    """
+    def run(self):
+        """
+        Outfiles are the libraries that were built using cmake
+        """
+        # There seems to be no other way to do this; I tried listing the
+        # libraries during the execution of the InstallCMakeLibs.run() but
+        # setuptools never tracked them, seems like setuptools wants to
+        # track the libraries through package data more than anything...
+        # help would be appriciated
+        self.outfiles = self.distribution.data_files
+
+__metaclass__ = type
+class InstallCMakeLibs(install_lib, object):
+    """
+    Get the libraries from the parent distribution, use those as the outfiles
+
+    Skip building anything; everything is already built, forward libraries to
+    the installation step
+    """
+    def run(self):
+        """
+        Copy libraries from the bin directory and place them as appropriate
+        """
+        self.announce("Moving library files", level=3)
+        # We have already built the libraries in the previous build_ext step
+        self.skip_build = True
+        if hasattr(self.distribution, 'bin_dir'):
+            bin_dir = self.distribution.bin_dir
+        else:
+            bin_dir = os.path.join(self.build_dir)
+        # Depending on the files that are generated from your cmake
+        # build chain, you may need to change the below code, such that
+        # your files are moved to the appropriate location when the installation
+        # is run
+        libs = [os.path.join(bin_dir, _lib) for _lib in 
+                os.listdir(bin_dir) if 
+                os.path.isfile(os.path.join(bin_dir, _lib)) and 
+                os.path.splitext(_lib)[1] in [".dll", ".so"]
+                and not (_lib.startswith("python") or _lib.startswith(PACKAGE_NAME))]
+        for lib in libs:
+            shutil.move(lib, os.path.join(self.build_dir,
+                                          os.path.basename(lib)))
+        # Mark the libs for installation, adding them to 
+        # distribution.data_files seems to ensure that setuptools' record 
+        # writer appends them to installed-files.txt in the package's egg-info
+        #
+        # Also tried adding the libraries to the distribution.libraries list, 
+        # but that never seemed to add them to the installed-files.txt in the 
+        # egg-info, and the online recommendation seems to be adding libraries 
+        # into eager_resources in the call to setup(), which I think puts them 
+        # in data_files anyways. 
+        # 
+        # What is the best way?
+        # These are the additional installation files that should be
+        # included in the package, but are resultant of the cmake build
+        # step; depending on the files that are generated from your cmake
+        # build chain, you may need to modify the below code
+        self.distribution.data_files = [os.path.join(self.install_dir, 
+                                                     os.path.basename(lib))
+                                        for lib in libs]
+        # Must be forced to run after adding the libs to data_files
+        self.distribution.run_command("install_data")
+        super(InstallCMakeLibs, self).run()
+
+__metaclass__ = type
+class InstallCMakeScripts(install_scripts, object):
+    """
+    Install the scripts in the build dir
+    """
+    def run(self):
+        """
+        Copy the required directory to the build directory and super().run()
+        """
+        self.announce("Moving scripts files", level=3)
+        # Scripts were already built in a previous step
+        self.skip_build = True
+        bin_dir = self.distribution.bin_dir
+        scripts_dirs = [os.path.join(bin_dir, _dir) for _dir in
+                        os.listdir(bin_dir) if
+                        os.path.isdir(os.path.join(bin_dir, _dir))]
+        for scripts_dir in scripts_dirs:
+            shutil.move(scripts_dir,
+                        os.path.join(self.build_dir,
+                                     os.path.basename(scripts_dir)))
+        # Mark the scripts for installation, adding them to 
+        # distribution.scripts seems to ensure that the setuptools' record 
+        # writer appends them to installed-files.txt in the package's egg-info
+        self.distribution.scripts = scripts_dirs
+        super(InstallCMakeScripts, self).run()
+
+__metaclass__ = type
+class BuildCMakeExt(build_ext, object):
+    """
+    Builds using cmake instead of the python setuptools implicit build
+    """
+    def run(self):
+        """
+        Perform build_cmake before doing the 'normal' stuff
+        """
+        for extension in self.extensions:
+            self.build_cmake(extension)
+        super(BuildCMakeExt, self).run()
+
+    def build_cmake(self, extension):
+        """
+        The steps required to build the extension
+        """
+        self.announce("Preparing the build environment", level=3)
+        build_dir = os.path.join(self.build_temp)
+        extension_path = os.path.abspath(os.path.dirname(self.get_ext_fullpath(extension.name)))
+        os.makedirs(build_dir)
+        os.makedirs(extension_path)
+        python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1])
+
+        # Now that the necessary directories are created, build
+        self.announce("Configuring cmake project", level=3)
+        cmake_args = ['-DPYTHON_EXECUTABLE=' + sys.executable,
+                      '-DBGS_CORE_STATIC=ON',
+                      '-DBGS_PYTHON_SUPPORT=ON',
+                      '-DBGS_PYTHON_ONLY=ON',
+                      '-DBGS_PYTHON_VERSION=' + python_version]
+        if not os.path.exists(self.build_temp):
+            os.makedirs(self.build_temp)
+        self.spawn(['cmake', '-H'+extension.sourcedir, '-B'+self.build_temp]+ cmake_args)
+
+        self.announce("Building binaries", level=3)
+        self.spawn(["cmake", "--build", self.build_temp, 
+                    "--config", "Release", '--', '-j8'])
+
+        # Build finished, now copy the files into the copy directory
+        # The copy directory is the parent directory of the extension (.pyd)
+        self.announce("Moving built python module", level=3)
+        bin_dir = build_dir
+        self.distribution.bin_dir = bin_dir
+        pyd_path = [os.path.join(bin_dir, _pyd) for _pyd in
+                    os.listdir(bin_dir) if
+                    os.path.isfile(os.path.join(bin_dir, _pyd)) and
+                    os.path.splitext(_pyd)[0].startswith(PACKAGE_NAME) and
+                    os.path.splitext(_pyd)[1] in [".pyd", ".so"]][0]
+        shutil.move(pyd_path, extension_path)
+
+        # After build_ext is run, the following commands will run:
+        # 
+        # install_lib
+        # install_scripts
+        # 
+        # These commands are subclassed above to avoid pitfalls that
+        # setuptools tries to impose when installing these, as it usually
+        # wants to build those libs and scripts as well or move them to a
+        # different place. See comments above for additional information
+
+with open("README.md", "r") as fh:
+    long_description = fh.read()
+
+setup(
+    name='pybgs',
+    version='3.0.0.post2',
+    author='Andrews Sobral',
+    author_email='andrewssobral@gmail.com',
+    url='https://github.com/andrewssobral/bgslibrary',
+    license='MIT',
+    description='Official Python wrapper for BGSLibrary',
+    long_description=long_description,
+    long_description_content_type="text/markdown",
+    ext_modules=[CMakeExtension(name='pybgs', sourcedir='.')],
+    cmdclass={
+        'build_ext': BuildCMakeExt,
+        'install_data': InstallCMakeLibsData,
+        'install_lib': InstallCMakeLibs,
+        #'install_scripts': InstallCMakeScripts
+        },
+    zip_safe=False,
+    packages=find_packages(),
+    keywords=['BGSLibrary', 'Background Subtraction', 'Computer Vision', 'Machine Learning'],
+)
diff --git a/src/FrameProcessor.cpp b/src/FrameProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38eb71f989b0852abc85281cfde80507e558a832
--- /dev/null
+++ b/src/FrameProcessor.cpp
@@ -0,0 +1,530 @@
+#include <iomanip>
+
+#include "FrameProcessor.h"
+
+namespace bgslibrary
+{
+  FrameProcessor::FrameProcessor() : 
+    firstTime(true), frameNumber(0), duration(0), 
+    tictoc(""), frameToStop(0)
+  {
+    debug_construction(FrameProcessor);
+    initLoadSaveConfig(quote(FrameProcessor));
+  }
+
+  FrameProcessor::~FrameProcessor() {
+    debug_destruction(FrameProcessor);
+  }
+
+  void FrameProcessor::init()
+  {
+    if (enablePreProcessor)
+      preProcessor = std::make_unique<PreProcessor>();
+
+    if (enableFrameDifference)
+      frameDifference = std::make_shared<FrameDifference>();
+
+    if (enableStaticFrameDifference)
+      staticFrameDifference = std::make_shared<StaticFrameDifference>();
+
+    if (enableWeightedMovingMean)
+      weightedMovingMean = std::make_shared<WeightedMovingMean>();
+
+    if (enableWeightedMovingVariance)
+      weightedMovingVariance = std::make_shared<WeightedMovingVariance>();
+
+    if (enableAdaptiveBackgroundLearning)
+      adaptiveBackgroundLearning = std::make_shared<AdaptiveBackgroundLearning>();
+
+    if (enableAdaptiveSelectiveBackgroundLearning)
+      adaptiveSelectiveBackgroundLearning = std::make_shared<AdaptiveSelectiveBackgroundLearning>();
+
+    if (enableMixtureOfGaussianV2)
+      mixtureOfGaussianV2 = std::make_shared<MixtureOfGaussianV2>();
+
+#if CV_MAJOR_VERSION == 2
+    if (enableMixtureOfGaussianV1)
+      mixtureOfGaussianV1 = std::make_shared<MixtureOfGaussianV1>();
+#endif
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    if (enableGMG)
+      gmg = std::make_shared<GMG>();
+#endif
+
+#if CV_MAJOR_VERSION >= 3
+    if (enableKNN)
+      knn = std::make_shared<KNN>();
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+    if (enableDPAdaptiveMedian)
+      dpAdaptiveMedian = std::make_shared<DPAdaptiveMedian>();
+
+    if (enableDPGrimsonGMM)
+      dpGrimsonGMM = std::make_shared<DPGrimsonGMM>();
+
+    if (enableDPZivkovicAGMM)
+      dpZivkovicAGMM = std::make_shared<DPZivkovicAGMM>();
+
+    if (enableDPMean)
+      dpTemporalMean = std::make_shared<DPMean>();
+
+    if (enableDPWrenGA)
+      dpWrenGA = std::make_shared<DPWrenGA>();
+
+    if (enableDPPratiMediod)
+      dpPratiMediod = std::make_shared<DPPratiMediod>();
+
+    if (enableDPEigenbackground)
+      dpEigenBackground = std::make_shared<DPEigenbackground>();
+
+    if (enableDPTexture)
+      dpTexture = std::make_shared<DPTexture>();
+
+    if (enableT2FGMM_UM)
+      type2FuzzyGMM_UM = std::make_shared<T2FGMM_UM>();
+
+    if (enableT2FGMM_UV)
+      type2FuzzyGMM_UV = std::make_shared<T2FGMM_UV>();
+
+    if (enableT2FMRF_UM)
+      type2FuzzyMRF_UM = std::make_shared<T2FMRF_UM>();
+
+    if (enableT2FMRF_UV)
+      type2FuzzyMRF_UV = std::make_shared<T2FMRF_UV>();
+
+    if (enableFuzzySugenoIntegral)
+      fuzzySugenoIntegral = std::make_shared<FuzzySugenoIntegral>();
+
+    if (enableFuzzyChoquetIntegral)
+      fuzzyChoquetIntegral = std::make_shared<FuzzyChoquetIntegral>();
+
+    if (enableLBSimpleGaussian)
+      lbSimpleGaussian = std::make_shared<LBSimpleGaussian>();
+
+    if (enableLBFuzzyGaussian)
+      lbFuzzyGaussian = std::make_shared<LBFuzzyGaussian>();
+
+    if (enableLBMixtureOfGaussians)
+      lbMixtureOfGaussians = std::make_shared<LBMixtureOfGaussians>();
+
+    if (enableLBAdaptiveSOM)
+      lbAdaptiveSOM = std::make_shared<LBAdaptiveSOM>();
+
+    if (enableLBFuzzyAdaptiveSOM)
+      lbFuzzyAdaptiveSOM = std::make_shared<LBFuzzyAdaptiveSOM>();
+
+    if (enableLbpMrf)
+      lbpMrf = std::make_shared<LBP_MRF>();
+
+    if (enableMultiLayer)
+      multiLayer = std::make_shared<MultiLayer>();
+
+    if (enablePBAS)
+      pixelBasedAdaptiveSegmenter = std::make_shared<PixelBasedAdaptiveSegmenter>();
+
+    if (enableVuMeter)
+      vuMeter = std::make_shared<VuMeter>();
+
+    if (enableKDE)
+      kde = std::make_shared<KDE>();
+
+    if (enableIMBS)
+      imbs = std::make_shared<IndependentMultimodal>();
+
+    if (enableMultiCue)
+      multiCue = std::make_shared<MultiCue>();
+#endif
+
+    if (enableSigmaDelta)
+      sigmaDelta = std::make_shared<SigmaDelta>();
+
+    if (enableSuBSENSE)
+      subSENSE = std::make_shared<SuBSENSE>();
+
+    if (enableLOBSTER)
+      lobster = std::make_shared<LOBSTER>();
+
+    if (enablePAWCS)
+      pawcs = std::make_shared<PAWCS>();
+
+    if (enableTwoPoints)
+      twoPoints = std::make_shared<TwoPoints>();
+
+    if (enableViBe)
+      vibe = std::make_shared<ViBe>();
+
+    if (enableCodeBook)
+      codeBook = std::make_shared<CodeBook>();
+
+    if (enableForegroundMaskAnalysis)
+      foregroundMaskAnalysis = std::make_shared<tools::ForegroundMaskAnalysis>();
+  }
+  
+  void FrameProcessor::process(const std::string name, const std::shared_ptr<IBGS> &bgs, const cv::Mat &img_input, cv::Mat &img_bgs)
+  {
+    if (tictoc == name)
+      tic(name);
+    
+    cv::Mat img_bkgmodel;
+    bgs->process(img_input, img_bgs, img_bkgmodel);
+    
+    if (tictoc == name)
+      toc();
+  }
+  
+  void FrameProcessor::process(const cv::Mat &img_input)
+  {
+    frameNumber++;
+
+    if (enablePreProcessor)
+      preProcessor->process(img_input, img_preProcessor);
+    else
+      img_input.copyTo(img_preProcessor);
+
+    if (enableFrameDifference)
+      process("FrameDifference", frameDifference, img_preProcessor, img_frameDifference);
+
+    if (enableStaticFrameDifference)
+      process("StaticFrameDifference", staticFrameDifference, img_preProcessor, img_staticFrameDifference);
+
+    if (enableWeightedMovingMean)
+      process("WeightedMovingMean", weightedMovingMean, img_preProcessor, img_weightedMovingMean);
+
+    if (enableWeightedMovingVariance)
+      process("WeightedMovingVariance", weightedMovingVariance, img_preProcessor, img_weightedMovingVariance);
+
+    if (enableAdaptiveBackgroundLearning)
+      process("AdaptiveBackgroundLearning", adaptiveBackgroundLearning, img_preProcessor, img_adaptiveBackgroundLearning);
+
+    if (enableAdaptiveSelectiveBackgroundLearning)
+      process("AdaptiveSelectiveBackgroundLearning", adaptiveSelectiveBackgroundLearning, img_preProcessor, img_adaptiveSelectiveBackgroundLearning);
+
+    if (enableMixtureOfGaussianV2)
+      process("MixtureOfGaussianV2", mixtureOfGaussianV2, img_preProcessor, img_mixtureOfGaussianV2);
+
+#if CV_MAJOR_VERSION == 2
+    if (enableMixtureOfGaussianV1)
+      process("MixtureOfGaussianV1", mixtureOfGaussianV1, img_preProcessor, img_mixtureOfGaussianV1);
+#endif
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    if (enableGMG)
+      process("GMG", gmg, img_preProcessor, img_gmg);
+#endif
+
+#if CV_MAJOR_VERSION >= 3
+    if (enableKNN)
+      process("KNN", knn, img_preProcessor, img_knn);
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+    if (enableDPAdaptiveMedian)
+      process("DPAdaptiveMedian", dpAdaptiveMedian, img_preProcessor, img_dpAdaptiveMedian);
+
+    if (enableDPGrimsonGMM)
+      process("DPGrimsonGMM", dpGrimsonGMM, img_preProcessor, img_dpGrimsonGMM);
+
+    if (enableDPZivkovicAGMM)
+      process("DPZivkovicAGMM", dpZivkovicAGMM, img_preProcessor, img_dpZivkovicAGMM);
+
+    if (enableDPMean)
+      process("DPMean", dpTemporalMean, img_preProcessor, img_dpTemporalMean);
+
+    if (enableDPWrenGA)
+      process("DPWrenGA", dpWrenGA, img_preProcessor, img_dpWrenGA);
+
+    if (enableDPPratiMediod)
+      process("DPPratiMediod", dpPratiMediod, img_preProcessor, img_dpPratiMediod);
+
+    if (enableDPEigenbackground)
+      process("DPEigenbackground", dpEigenBackground, img_preProcessor, img_dpEigenBackground);
+
+    if (enableDPTexture)
+      process("DPTexture", dpTexture, img_preProcessor, img_dpTexture);
+
+    if (enableT2FGMM_UM)
+      process("T2FGMM_UM", type2FuzzyGMM_UM, img_preProcessor, img_type2FuzzyGMM_UM);
+
+    if (enableT2FGMM_UV)
+      process("T2FGMM_UV", type2FuzzyGMM_UV, img_preProcessor, img_type2FuzzyGMM_UV);
+
+    if (enableT2FMRF_UM)
+      process("T2FMRF_UM", type2FuzzyMRF_UM, img_preProcessor, img_type2FuzzyMRF_UM);
+
+    if (enableT2FMRF_UV)
+      process("T2FMRF_UV", type2FuzzyMRF_UV, img_preProcessor, img_type2FuzzyMRF_UV);
+
+    if (enableFuzzySugenoIntegral)
+      process("FuzzySugenoIntegral", fuzzySugenoIntegral, img_preProcessor, img_fuzzySugenoIntegral);
+
+    if (enableFuzzyChoquetIntegral)
+      process("FuzzyChoquetIntegral", fuzzyChoquetIntegral, img_preProcessor, img_fuzzyChoquetIntegral);
+
+    if (enableLBSimpleGaussian)
+      process("LBSimpleGaussian", lbSimpleGaussian, img_preProcessor, img_lbSimpleGaussian);
+
+    if (enableLBFuzzyGaussian)
+      process("LBFuzzyGaussian", lbFuzzyGaussian, img_preProcessor, img_lbFuzzyGaussian);
+
+    if (enableLBMixtureOfGaussians)
+      process("LBMixtureOfGaussians", lbMixtureOfGaussians, img_preProcessor, img_lbMixtureOfGaussians);
+
+    if (enableLBAdaptiveSOM)
+      process("LBAdaptiveSOM", lbAdaptiveSOM, img_preProcessor, img_lbAdaptiveSOM);
+
+    if (enableLBFuzzyAdaptiveSOM)
+      process("LBFuzzyAdaptiveSOM", lbFuzzyAdaptiveSOM, img_preProcessor, img_lbFuzzyAdaptiveSOM);
+
+    if (enableLbpMrf)
+      process("LbpMrf", lbpMrf, img_preProcessor, img_lbpMrf);
+
+    if (enableMultiLayer)
+    {
+      multiLayer->setStatus(MultiLayer::MLBGS_LEARN);
+      //multiLayer->setStatus(MultiLayer::MLBGS_DETECT);
+      process("MultiLayer", multiLayer, img_preProcessor, img_multiLayer);
+    }
+
+    if (enablePBAS)
+      process("PBAS", pixelBasedAdaptiveSegmenter, img_preProcessor, img_pixelBasedAdaptiveSegmenter);
+
+    if (enableVuMeter)
+      process("VuMeter", vuMeter, img_preProcessor, img_vumeter);
+
+    if (enableKDE)
+      process("KDE", kde, img_preProcessor, img_kde);
+
+    if (enableIMBS)
+      process("IMBS", imbs, img_preProcessor, img_imbs);
+
+    if (enableMultiCue)
+      process("MultiCue", multiCue, img_preProcessor, img_multiCue);
+#endif
+    
+    if (enableSigmaDelta)
+      process("SigmaDelta", sigmaDelta, img_preProcessor, img_sigmaDelta);
+
+    if (enableSuBSENSE)
+      process("SuBSENSE", subSENSE, img_preProcessor, img_subSENSE);
+
+    if (enableLOBSTER)
+      process("LOBSTER", lobster, img_preProcessor, img_lobster);
+
+    if (enablePAWCS)
+      process("PAWCS", pawcs, img_preProcessor, img_pawcs);
+
+    if (enableTwoPoints)
+      process("TwoPoints", twoPoints, img_preProcessor, img_twoPoints);
+
+    if (enableViBe)
+      process("ViBe", vibe, img_preProcessor, img_vibe);
+
+    if (enableCodeBook)
+      process("CodeBook", codeBook, img_preProcessor, img_codeBook);
+
+    if (enableForegroundMaskAnalysis)
+    {
+      foregroundMaskAnalysis->stopAt = frameToStop;
+      foregroundMaskAnalysis->img_ref_path = imgref;
+
+      foregroundMaskAnalysis->process(frameNumber, "FrameDifference", img_frameDifference);
+      foregroundMaskAnalysis->process(frameNumber, "StaticFrameDifference", img_staticFrameDifference);
+      foregroundMaskAnalysis->process(frameNumber, "WeightedMovingMean", img_weightedMovingMean);
+      foregroundMaskAnalysis->process(frameNumber, "WeightedMovingVariance", img_weightedMovingVariance);
+      foregroundMaskAnalysis->process(frameNumber, "AdaptiveBackgroundLearning", img_adaptiveBackgroundLearning);
+      foregroundMaskAnalysis->process(frameNumber, "AdaptiveSelectiveBackgroundLearning", img_adaptiveSelectiveBackgroundLearning);
+      foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV2", img_mixtureOfGaussianV2);
+
+#if CV_MAJOR_VERSION == 2
+      foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV1", img_mixtureOfGaussianV1);
+#endif
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+      foregroundMaskAnalysis->process(frameNumber, "GMG", img_gmg);
+#endif
+      
+#if CV_MAJOR_VERSION >= 3
+      foregroundMaskAnalysis->process(frameNumber, "KNN", img_knn);
+#endif
+      
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+      foregroundMaskAnalysis->process(frameNumber, "DPAdaptiveMedian", img_dpAdaptiveMedian);
+      foregroundMaskAnalysis->process(frameNumber, "DPGrimsonGMM", img_dpGrimsonGMM);
+      foregroundMaskAnalysis->process(frameNumber, "DPZivkovicAGMM", img_dpZivkovicAGMM);
+      foregroundMaskAnalysis->process(frameNumber, "DPMean", img_dpTemporalMean);
+      foregroundMaskAnalysis->process(frameNumber, "DPWrenGA", img_dpWrenGA);
+      foregroundMaskAnalysis->process(frameNumber, "DPPratiMediod", img_dpPratiMediod);
+      foregroundMaskAnalysis->process(frameNumber, "DPEigenbackground", img_dpEigenBackground);
+      foregroundMaskAnalysis->process(frameNumber, "DPTexture", img_dpTexture);
+      foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UM", img_type2FuzzyGMM_UM);
+      foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UV", img_type2FuzzyGMM_UV);
+      foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UM", img_type2FuzzyMRF_UM);
+      foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UV", img_type2FuzzyMRF_UV);
+      foregroundMaskAnalysis->process(frameNumber, "FuzzySugenoIntegral", img_fuzzySugenoIntegral);
+      foregroundMaskAnalysis->process(frameNumber, "FuzzyChoquetIntegral", img_fuzzyChoquetIntegral);
+      foregroundMaskAnalysis->process(frameNumber, "LBSimpleGaussian", img_lbSimpleGaussian);
+      foregroundMaskAnalysis->process(frameNumber, "LBFuzzyGaussian", img_lbFuzzyGaussian);
+      foregroundMaskAnalysis->process(frameNumber, "LBMixtureOfGaussians", img_lbMixtureOfGaussians);
+      foregroundMaskAnalysis->process(frameNumber, "LBAdaptiveSOM", img_lbAdaptiveSOM);
+      foregroundMaskAnalysis->process(frameNumber, "LBFuzzyAdaptiveSOM", img_lbFuzzyAdaptiveSOM);
+      foregroundMaskAnalysis->process(frameNumber, "LbpMrf", img_lbpMrf);
+      foregroundMaskAnalysis->process(frameNumber, "MultiLayer", img_multiLayer);
+      foregroundMaskAnalysis->process(frameNumber, "PBAS", img_pixelBasedAdaptiveSegmenter);
+      foregroundMaskAnalysis->process(frameNumber, "VuMeter", img_vumeter);
+      foregroundMaskAnalysis->process(frameNumber, "KDE", img_kde);
+      foregroundMaskAnalysis->process(frameNumber, "IMBS", img_imbs);
+      foregroundMaskAnalysis->process(frameNumber, "MultiCue", img_multiCue);
+#endif
+
+      foregroundMaskAnalysis->process(frameNumber, "SigmaDelta", img_sigmaDelta);
+      foregroundMaskAnalysis->process(frameNumber, "SuBSENSE", img_subSENSE);
+      foregroundMaskAnalysis->process(frameNumber, "LOBSTER", img_lobster);
+      foregroundMaskAnalysis->process(frameNumber, "PAWCS", img_pawcs);
+      foregroundMaskAnalysis->process(frameNumber, "TwoPoints", img_twoPoints);
+      foregroundMaskAnalysis->process(frameNumber, "ViBe", img_vibe);
+      foregroundMaskAnalysis->process(frameNumber, "CodeBook", img_codeBook);
+    }
+
+    firstTime = false;
+  }
+
+  void FrameProcessor::finish(void){}
+
+  void FrameProcessor::tic(std::string value)
+  {
+    processname = value;
+    duration = static_cast<double>(cv::getTickCount());
+  }
+
+  void FrameProcessor::toc()
+  {
+    duration = (static_cast<double>(cv::getTickCount()) - duration) / cv::getTickFrequency();
+    std::cout << processname << "\ttime(sec):" << std::fixed << std::setprecision(6) << duration << std::endl;
+  }
+
+  void FrameProcessor::save_config(cv::FileStorage &fs) {
+    fs << "tictoc" << tictoc;
+    fs << "enablePreProcessor" << enablePreProcessor;
+    fs << "enableForegroundMaskAnalysis" << enableForegroundMaskAnalysis;
+    fs << "enableFrameDifference" << enableFrameDifference;
+    fs << "enableStaticFrameDifference" << enableStaticFrameDifference;
+    fs << "enableWeightedMovingMean" << enableWeightedMovingMean;
+    fs << "enableWeightedMovingVariance" << enableWeightedMovingVariance;
+    fs << "enableAdaptiveBackgroundLearning" << enableAdaptiveBackgroundLearning;
+    fs << "enableAdaptiveSelectiveBackgroundLearning" << enableAdaptiveSelectiveBackgroundLearning;
+    fs << "enableMixtureOfGaussianV2" << enableMixtureOfGaussianV2;
+
+#if CV_MAJOR_VERSION == 2
+    fs << "enableMixtureOfGaussianV1" << enableMixtureOfGaussianV1;
+#endif
+    
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    fs << "enableGMG" << enableGMG;
+#endif
+    
+#if CV_MAJOR_VERSION >= 3
+    fs << "enableKNN" << enableKNN;
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+    fs << "enableDPAdaptiveMedian" << enableDPAdaptiveMedian;
+    fs << "enableDPGrimsonGMM" << enableDPGrimsonGMM;
+    fs << "enableDPZivkovicAGMM" << enableDPZivkovicAGMM;
+    fs << "enableDPMean" << enableDPMean;
+    fs << "enableDPWrenGA" << enableDPWrenGA;
+    fs << "enableDPPratiMediod" << enableDPPratiMediod;
+    fs << "enableDPEigenbackground" << enableDPEigenbackground;
+    fs << "enableDPTexture" << enableDPTexture;
+    fs << "enableT2FGMM_UM" << enableT2FGMM_UM;
+    fs << "enableT2FGMM_UV" << enableT2FGMM_UV;
+    fs << "enableT2FMRF_UM" << enableT2FMRF_UM;
+    fs << "enableT2FMRF_UV" << enableT2FMRF_UV;
+    fs << "enableFuzzySugenoIntegral" << enableFuzzySugenoIntegral;
+    fs << "enableFuzzyChoquetIntegral" << enableFuzzyChoquetIntegral;
+    fs << "enableLBSimpleGaussian" << enableLBSimpleGaussian;
+    fs << "enableLBFuzzyGaussian" << enableLBFuzzyGaussian;
+    fs << "enableLBMixtureOfGaussians" << enableLBMixtureOfGaussians;
+    fs << "enableLBAdaptiveSOM" << enableLBAdaptiveSOM;
+    fs << "enableLBFuzzyAdaptiveSOM" << enableLBFuzzyAdaptiveSOM;
+    fs << "enableLbpMrf" << enableLbpMrf;
+    fs << "enableMultiLayer" << enableMultiLayer;
+    fs << "enablePBAS" << enablePBAS;
+    fs << "enableVuMeter" << enableVuMeter;
+    fs << "enableKDE" << enableKDE;
+    fs << "enableIMBS" << enableIMBS;
+    fs << "enableMultiCue" << enableMultiCue;
+#endif
+    
+    fs << "enableSigmaDelta" << enableSigmaDelta;
+    fs << "enableSuBSENSE" << enableSuBSENSE;
+    fs << "enableLOBSTER" << enableLOBSTER;
+    fs << "enablePAWCS" << enablePAWCS;
+    fs << "enableTwoPoints" << enableTwoPoints;
+    fs << "enableViBe" << enableViBe;
+    fs << "enableCodeBook" << enableCodeBook;
+  }
+
+  void FrameProcessor::load_config(cv::FileStorage &fs) {
+    fs["tictoc"] >> tictoc;
+    fs["enablePreProcessor"] >> enablePreProcessor;
+    fs["enableForegroundMaskAnalysis"] >> enableForegroundMaskAnalysis;
+    fs["enableFrameDifference"] >> enableFrameDifference;
+    fs["enableStaticFrameDifference"] >> enableStaticFrameDifference;
+    fs["enableWeightedMovingMean"] >> enableWeightedMovingMean;
+    fs["enableWeightedMovingVariance"] >> enableWeightedMovingVariance;
+    fs["enableAdaptiveBackgroundLearning"] >> enableAdaptiveBackgroundLearning;
+    fs["enableAdaptiveBackgroundLearning"] >> enableAdaptiveSelectiveBackgroundLearning;
+    fs["enableMixtureOfGaussianV2"] >> enableMixtureOfGaussianV2;
+
+#if CV_MAJOR_VERSION == 2
+    fs["enableMixtureOfGaussianV1"] >> enableMixtureOfGaussianV1;
+#endif
+    
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    fs["enableGMG"] >> enableGMG;
+#endif
+    
+#if CV_MAJOR_VERSION >= 3
+    fs["enableKNN"] >> enableKNN;
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+    fs["enableDPAdaptiveMedian"] >> enableDPAdaptiveMedian;
+    fs["enableDPGrimsonGMM"] >> enableDPGrimsonGMM;
+    fs["enableDPZivkovicAGMM"] >> enableDPZivkovicAGMM;
+    fs["enableDPMean"] >> enableDPMean;
+    fs["enableDPWrenGA"] >> enableDPWrenGA;
+    fs["enableDPPratiMediod"] >> enableDPPratiMediod;
+    fs["enableDPEigenbackground"] >> enableDPEigenbackground;
+    fs["enableDPTexture"] >> enableDPTexture;
+    fs["enableT2FGMM_UM"] >> enableT2FGMM_UM;
+    fs["enableT2FGMM_UV"] >> enableT2FGMM_UV;
+    fs["enableT2FMRF_UM"] >> enableT2FMRF_UM;
+    fs["enableT2FMRF_UV"] >> enableT2FMRF_UV;
+    fs["enableFuzzySugenoIntegral"] >> enableFuzzySugenoIntegral;
+    fs["enableFuzzyChoquetIntegral"] >> enableFuzzyChoquetIntegral;
+    fs["enableLBSimpleGaussian"] >> enableLBSimpleGaussian;
+    fs["enableLBFuzzyGaussian"] >> enableLBFuzzyGaussian;
+    fs["enableLBMixtureOfGaussians"] >> enableLBMixtureOfGaussians;
+    fs["enableLBAdaptiveSOM"] >> enableLBAdaptiveSOM;
+    fs["enableLBFuzzyAdaptiveSOM"] >> enableLBFuzzyAdaptiveSOM;
+    fs["enableLbpMrf"] >> enableLbpMrf;
+    fs["enableMultiLayer"] >> enableMultiLayer;
+    fs["enablePBAS"] >> enablePBAS;
+    fs["enableVuMeter"] >> enableVuMeter;
+    fs["enableKDE"] >> enableKDE;
+    fs["enableIMBS"] >> enableIMBS;
+    fs["enableMultiCue"] >> enableMultiCue;
+#endif
+    
+    fs["enableSigmaDelta"] >> enableSigmaDelta;
+    fs["enableSuBSENSE"] >> enableSuBSENSE;
+    fs["enableLOBSTER"] >> enableLOBSTER;
+    fs["enablePAWCS"] >> enablePAWCS;
+    fs["enableTwoPoints"] >> enableTwoPoints;
+    fs["enableViBe"] >> enableViBe;
+    fs["enableCodeBook"] >> enableCodeBook;
+  }
+}
diff --git a/src/FrameProcessor.h b/src/FrameProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1eec6d601918556f62e1926d8b5735a996778e58
--- /dev/null
+++ b/src/FrameProcessor.h
@@ -0,0 +1,227 @@
+#pragma once
+#pragma warning(disable : 4482)
+
+#include "IFrameProcessor.h"
+#include "PreProcessor.h"
+
+#include "algorithms/algorithms.h"
+#include "tools/ForegroundMaskAnalysis.h"
+
+namespace bgslibrary
+{
+  class FrameProcessor : public IFrameProcessor, public ILoadSaveConfig
+  {
+  private:
+    bool firstTime;
+    long frameNumber;
+    std::string processname;
+    double duration;
+    std::string tictoc;
+
+    cv::Mat img_preProcessor;
+    std::unique_ptr<PreProcessor> preProcessor;
+    bool enablePreProcessor = false;
+
+    cv::Mat img_frameDifference;
+    std::shared_ptr<FrameDifference> frameDifference;
+    bool enableFrameDifference = false;
+
+    cv::Mat img_staticFrameDifference;
+    std::shared_ptr<StaticFrameDifference> staticFrameDifference;
+    bool enableStaticFrameDifference = false;
+
+    cv::Mat img_weightedMovingMean;
+    std::shared_ptr<WeightedMovingMean> weightedMovingMean;
+    bool enableWeightedMovingMean = false;
+
+    cv::Mat img_weightedMovingVariance;
+    std::shared_ptr<WeightedMovingVariance> weightedMovingVariance;
+    bool enableWeightedMovingVariance = false;
+
+    cv::Mat img_adaptiveBackgroundLearning;
+    std::shared_ptr<AdaptiveBackgroundLearning> adaptiveBackgroundLearning;
+    bool enableAdaptiveBackgroundLearning = false;
+
+    cv::Mat img_adaptiveSelectiveBackgroundLearning;
+    std::shared_ptr<AdaptiveSelectiveBackgroundLearning> adaptiveSelectiveBackgroundLearning;
+    bool enableAdaptiveSelectiveBackgroundLearning = false;
+
+    cv::Mat img_mixtureOfGaussianV2;
+    std::shared_ptr<MixtureOfGaussianV2> mixtureOfGaussianV2;
+    bool enableMixtureOfGaussianV2 = false;
+
+#if CV_MAJOR_VERSION == 2
+    cv::Mat img_mixtureOfGaussianV1;
+    std::shared_ptr<MixtureOfGaussianV1> mixtureOfGaussianV1;
+    bool enableMixtureOfGaussianV1 = false;
+#endif
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    cv::Mat img_gmg;
+    std::shared_ptr<GMG> gmg;
+    bool enableGMG = false;
+#endif
+
+#if CV_MAJOR_VERSION >= 3
+    cv::Mat img_knn;
+    std::shared_ptr<KNN> knn;
+    bool enableKNN = false;
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+    cv::Mat img_dpAdaptiveMedian;
+    std::shared_ptr<DPAdaptiveMedian> dpAdaptiveMedian;
+    bool enableDPAdaptiveMedian = false;
+
+    cv::Mat img_dpGrimsonGMM;
+    std::shared_ptr<DPGrimsonGMM> dpGrimsonGMM;
+    bool enableDPGrimsonGMM = false;
+
+    cv::Mat img_dpZivkovicAGMM;
+    std::shared_ptr<DPZivkovicAGMM> dpZivkovicAGMM;
+    bool enableDPZivkovicAGMM = false;
+
+    cv::Mat img_dpTemporalMean;
+    std::shared_ptr<DPMean> dpTemporalMean;
+    bool enableDPMean = false;
+
+    cv::Mat img_dpWrenGA;
+    std::shared_ptr<DPWrenGA> dpWrenGA;
+    bool enableDPWrenGA = false;
+
+    cv::Mat img_dpPratiMediod;
+    std::shared_ptr<DPPratiMediod> dpPratiMediod;
+    bool enableDPPratiMediod = false;
+
+    cv::Mat img_dpEigenBackground;
+    std::shared_ptr<DPEigenbackground> dpEigenBackground;
+    bool enableDPEigenbackground = false;
+
+    cv::Mat img_dpTexture;
+    std::shared_ptr<DPTexture> dpTexture;
+    bool enableDPTexture = false;
+
+    cv::Mat img_type2FuzzyGMM_UM;
+    std::shared_ptr<T2FGMM_UM> type2FuzzyGMM_UM;
+    bool enableT2FGMM_UM = false;
+
+    cv::Mat img_type2FuzzyGMM_UV;
+    std::shared_ptr<T2FGMM_UV> type2FuzzyGMM_UV;
+    bool enableT2FGMM_UV = false;
+
+    cv::Mat img_type2FuzzyMRF_UM;
+    std::shared_ptr<T2FMRF_UM> type2FuzzyMRF_UM;
+    bool enableT2FMRF_UM = false;
+
+    cv::Mat img_type2FuzzyMRF_UV;
+    std::shared_ptr<T2FMRF_UV> type2FuzzyMRF_UV;
+    bool enableT2FMRF_UV = false;
+
+    cv::Mat img_fuzzySugenoIntegral;
+    std::shared_ptr<FuzzySugenoIntegral> fuzzySugenoIntegral;
+    bool enableFuzzySugenoIntegral = false;
+
+    cv::Mat img_fuzzyChoquetIntegral;
+    std::shared_ptr<FuzzyChoquetIntegral> fuzzyChoquetIntegral;
+    bool enableFuzzyChoquetIntegral = false;
+
+    cv::Mat img_lbSimpleGaussian;
+    std::shared_ptr<LBSimpleGaussian> lbSimpleGaussian;
+    bool enableLBSimpleGaussian = false;
+
+    cv::Mat img_lbFuzzyGaussian;
+    std::shared_ptr<LBFuzzyGaussian> lbFuzzyGaussian;
+    bool enableLBFuzzyGaussian = false;
+
+    cv::Mat img_lbMixtureOfGaussians;
+    std::shared_ptr<LBMixtureOfGaussians> lbMixtureOfGaussians;
+    bool enableLBMixtureOfGaussians = false;
+
+    cv::Mat img_lbAdaptiveSOM;
+    std::shared_ptr<LBAdaptiveSOM> lbAdaptiveSOM;
+    bool enableLBAdaptiveSOM = false;
+
+    cv::Mat img_lbFuzzyAdaptiveSOM;
+    std::shared_ptr<LBFuzzyAdaptiveSOM> lbFuzzyAdaptiveSOM;
+    bool enableLBFuzzyAdaptiveSOM = false;
+    
+    cv::Mat img_lbpMrf;
+    std::shared_ptr<LBP_MRF> lbpMrf;
+    bool enableLbpMrf = false;
+
+    cv::Mat img_multiLayer;
+    std::shared_ptr<MultiLayer> multiLayer;
+    bool enableMultiLayer = false;
+
+    cv::Mat img_pixelBasedAdaptiveSegmenter;
+    std::shared_ptr<PixelBasedAdaptiveSegmenter> pixelBasedAdaptiveSegmenter;
+    bool enablePBAS = false;
+
+    cv::Mat img_vumeter;
+    std::shared_ptr<VuMeter> vuMeter;
+    bool enableVuMeter = false;
+
+    cv::Mat img_kde;
+    std::shared_ptr<KDE> kde;
+    bool enableKDE = false;
+
+    cv::Mat img_imbs;
+    std::shared_ptr<IndependentMultimodal> imbs;
+    bool enableIMBS = false;
+
+    cv::Mat img_multiCue;
+    std::shared_ptr<MultiCue> multiCue;
+    bool enableMultiCue = false;
+#endif
+
+    cv::Mat img_sigmaDelta;
+    std::shared_ptr<SigmaDelta> sigmaDelta;
+    bool enableSigmaDelta = false;
+
+    cv::Mat img_subSENSE;
+    std::shared_ptr<SuBSENSE> subSENSE;
+    bool enableSuBSENSE = false;
+
+    cv::Mat img_lobster;
+    std::shared_ptr<LOBSTER> lobster;
+    bool enableLOBSTER = false;
+
+    cv::Mat img_pawcs;
+    std::shared_ptr<PAWCS> pawcs;
+    bool enablePAWCS = false;
+
+    cv::Mat img_twoPoints;
+    std::shared_ptr<TwoPoints> twoPoints;
+    bool enableTwoPoints = false;
+
+    cv::Mat img_vibe;
+    std::shared_ptr<ViBe> vibe;
+    bool enableViBe = false;
+
+    cv::Mat img_codeBook;
+    std::shared_ptr<CodeBook> codeBook;
+    bool enableCodeBook = false;
+    
+    std::shared_ptr<tools::ForegroundMaskAnalysis> foregroundMaskAnalysis;
+    bool enableForegroundMaskAnalysis = false;
+
+  public:
+    FrameProcessor();
+    ~FrameProcessor();
+
+    long frameToStop;
+    std::string imgref;
+
+    void init();
+    void process(const cv::Mat &img_input);
+    void finish(void);
+
+  private:
+    void process(const std::string name, const std::shared_ptr<IBGS> &bgs, const cv::Mat &img_input, cv::Mat &img_bgs);
+    void tic(std::string value);
+    void toc();
+    
+    void save_config(cv::FileStorage &fs);
+    void load_config(cv::FileStorage &fs);
+  };
+}
diff --git a/src/IFrameProcessor.h b/src/IFrameProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cf0cdd2f344be361f3b4bce2fd02a6ed199e9cb
--- /dev/null
+++ b/src/IFrameProcessor.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <opencv2/opencv.hpp>
+
+#include "utils/GenericMacros.h"
+
+namespace bgslibrary
+{
+  class IFrameProcessor
+  {
+  public:
+    IFrameProcessor(){
+      //debug_construction(IFrameProcessor);
+    }
+    virtual ~IFrameProcessor() {
+      //debug_destruction(IFrameProcessor);
+    }
+    virtual void process(const cv::Mat &input) = 0;
+  };
+}
diff --git a/src/Main.cpp b/src/Main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73993d39f44386dd7b44538483557ecd4e1efe3d
--- /dev/null
+++ b/src/Main.cpp
@@ -0,0 +1,68 @@
+#include <iostream>
+
+#include "utils/GenericKeys.h"
+#include "VideoAnalysis.h"
+
+namespace bgslibrary
+{
+  class Main
+  {
+  private:
+    Main();
+
+  public:
+    static void start(int argc, const char **argv)
+    {
+      std::cout << "---------------------------------------------" << std::endl;
+      std::cout << "Background Subtraction Library               " << std::endl;
+      std::cout << "https://github.com/andrewssobral/bgslibrary  " << std::endl;
+      std::cout << "This software is under the MIT License       " << std::endl;
+      std::cout << "---------------------------------------------" << std::endl;
+      std::cout << "Using OpenCV version " << CV_VERSION << std::endl;
+
+      try
+      {
+        auto key = KEY_ESC;
+
+        do
+        {
+          auto videoAnalysis = std::make_unique<VideoAnalysis>();
+
+          if (videoAnalysis->setup(argc, argv))
+          {
+            videoAnalysis->start();
+
+            std::cout << "Processing finished, enter:" << std::endl;
+            std::cout << "R - Repeat" << std::endl;
+            std::cout << "Q - Quit" << std::endl;
+
+            key = cv::waitKey();
+          }
+
+          cv::destroyAllWindows();
+
+        } while (key == KEY_REPEAT);
+      }
+      catch (const std::exception& ex)
+      {
+        std::cout << "std::exception:" << ex.what() << std::endl;
+        return;
+      }
+      catch (...)
+      {
+        std::cout << "Unknow error" << std::endl;
+        return;
+      }
+
+#ifdef WIN32
+      //system("pause");
+#endif
+    }
+  };
+}
+
+int main(int argc, const char **argv)
+{
+  bgslibrary::Main::start(argc, argv);
+  return 0;
+}
diff --git a/PreProcessor.cpp b/src/PreProcessor.cpp
similarity index 55%
rename from PreProcessor.cpp
rename to src/PreProcessor.cpp
index 4c13f7e4c3fcd39959b93cb8b6484f45e55e2733..809d04d883210e67e678fbbdeb19ffb6cea60708 100644
--- a/PreProcessor.cpp
+++ b/src/PreProcessor.cpp
@@ -1,45 +1,27 @@
-/*
-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 "PreProcessor.h"
 
 namespace bgslibrary
 {
-  PreProcessor::PreProcessor() : firstTime(true), equalizeHist(false), gaussianBlur(false)
+  PreProcessor::PreProcessor() : 
+    firstTime(true), equalizeHist(false), gaussianBlur(false)
   {
-    std::cout << "PreProcessor()" << std::endl;
+    debug_construction(PreProcessor);
+    initLoadSaveConfig(quote(PreProcessor));
   }
 
-  PreProcessor::~PreProcessor()
-  {
-    std::cout << "~PreProcessor()" << std::endl;
+  PreProcessor::~PreProcessor() {
+    debug_destruction(PreProcessor);
   }
 
-  void PreProcessor::setEqualizeHist(bool value)
-  {
+  void PreProcessor::setEqualizeHist(bool value) {
     equalizeHist = value;
   }
 
-  void PreProcessor::setGaussianBlur(bool value)
-  {
+  void PreProcessor::setGaussianBlur(bool value) {
     gaussianBlur = value;
   }
 
-  cv::Mat PreProcessor::getGrayScale()
-  {
+  cv::Mat PreProcessor::getGrayScale() {
     return img_gray.clone();
   }
 
@@ -48,11 +30,6 @@ namespace bgslibrary
     if (img_input.empty())
       return;
 
-    loadConfig();
-
-    if (firstTime)
-      saveConfig();
-
     img_input.copyTo(img_output);
 
     // Converts image from one color space to another
@@ -71,11 +48,11 @@ namespace bgslibrary
       cv::GaussianBlur(img_output, img_output, cv::Size(7, 7), 1.5);
 
     if (enableShow)
-      cv::imshow("Pre Processor", img_output);
+      cv::imshow("PreProcessor", img_output);
 
     firstTime = false;
   }
-
+  /*
   void PreProcessor::rotate(const cv::Mat &img_input, cv::Mat &img_output, float angle)
   {
     IplImage* image = new IplImage(img_input);
@@ -102,7 +79,7 @@ namespace bgslibrary
     cvReleaseImage(&rotatedImage);
     cvReleaseMat(&mapMatrix);
   }
-
+  */
   void PreProcessor::applyCanny(const cv::Mat &img_input, cv::Mat &img_output)
   {
     if (img_input.empty())
@@ -116,34 +93,24 @@ namespace bgslibrary
 
     cv::Mat img_canny;
     cv::Canny(
-      img_input, // image � Single-channel 8-bit input image
-      img_canny,  // edges � The output edge map. It will have the same size and the same type as image
-      100,       // threshold1 � The first threshold for the hysteresis procedure
-      200);      // threshold2 � The second threshold for the hysteresis procedure
+      img_input, // image � Single-channel 8-bit input image
+      img_canny,  // edges � The output edge map. It will have the same size and the same type as image
+      100,       // threshold1 � The first threshold for the hysteresis procedure
+      200);      // threshold2 � The second threshold for the hysteresis procedure
     cv::threshold(img_canny, img_canny, 128, 255, cv::THRESH_BINARY_INV);
 
     img_canny.copyTo(img_output);
   }
 
-  void PreProcessor::saveConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/PreProcessor.xml", 0, CV_STORAGE_WRITE);
-
-    cvWriteInt(fs, "equalizeHist", equalizeHist);
-    cvWriteInt(fs, "gaussianBlur", gaussianBlur);
-    cvWriteInt(fs, "enableShow", enableShow);
-
-    cvReleaseFileStorage(&fs);
+  void PreProcessor::save_config(cv::FileStorage &fs) {
+    fs << "equalizeHist" << equalizeHist;
+    fs << "gaussianBlur" << gaussianBlur;
+    fs << "enableShow" << enableShow;
   }
 
-  void PreProcessor::loadConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/PreProcessor.xml", 0, CV_STORAGE_READ);
-
-    equalizeHist = cvReadIntByName(fs, 0, "equalizeHist", false);
-    gaussianBlur = cvReadIntByName(fs, 0, "gaussianBlur", false);
-    enableShow = cvReadIntByName(fs, 0, "enableShow", true);
-
-    cvReleaseFileStorage(&fs);
+  void PreProcessor::load_config(cv::FileStorage &fs) {
+    fs["equalizeHist"] >> equalizeHist;
+    fs["gaussianBlur"] >> gaussianBlur;
+    fs["enableShow"] >> enableShow;
   }
 }
diff --git a/src/PreProcessor.h b/src/PreProcessor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a14de1837218dff0d85aa251085d6805a93aec3d
--- /dev/null
+++ b/src/PreProcessor.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <iostream>
+#include <opencv2/opencv.hpp>
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/features2d/features2d.hpp>
+// opencv legacy includes
+#include <opencv2/imgproc/types_c.h>
+//#include <opencv2/imgproc/imgproc_c.h>
+//#include <opencv2/highgui/highgui_c.h>
+
+#include "utils/ILoadSaveConfig.h"
+
+namespace bgslibrary
+{
+  class PreProcessor : public ILoadSaveConfig
+  {
+  private:
+    bool firstTime;
+    bool equalizeHist;
+    bool gaussianBlur;
+    cv::Mat img_gray;
+    bool enableShow;
+
+  public:
+    PreProcessor();
+    ~PreProcessor();
+
+    void setEqualizeHist(bool value);
+    void setGaussianBlur(bool value);
+    cv::Mat getGrayScale();
+
+    void process(const cv::Mat &img_input, cv::Mat &img_output);
+
+    //void rotate(const cv::Mat &img_input, cv::Mat &img_output, float angle);
+    void applyCanny(const cv::Mat &img_input, cv::Mat &img_output);
+
+  private:
+    void save_config(cv::FileStorage &fs);
+    void load_config(cv::FileStorage &fs);
+  };
+}
diff --git a/src/VideoAnalysis.cpp b/src/VideoAnalysis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d06918609e39b6cba3f3973ed294080387e8a680
--- /dev/null
+++ b/src/VideoAnalysis.cpp
@@ -0,0 +1,141 @@
+#include "VideoAnalysis.h"
+
+namespace bgslibrary
+{
+  VideoAnalysis::VideoAnalysis() :
+    use_file(false), use_camera(false), cameraIndex(0),
+    use_comp(false), frameToStop(0)
+  {
+    debug_construction(VideoAnalysis);
+  }
+
+  VideoAnalysis::~VideoAnalysis() {
+    debug_destruction(VideoAnalysis);
+  }
+
+  bool VideoAnalysis::setup(int argc, const char **argv)
+  {
+    bool flag = false;
+
+#if CV_MAJOR_VERSION == 2
+    const char* keys =
+      "{hp|help|false|Print this message}"
+      "{uf|use_file|false|Use video file}"
+      "{fn|filename||Specify video file}"
+      "{uc|use_cam|false|Use camera}"
+      "{ca|camera|0|Specify camera index}"
+      "{co|use_comp|false|Use mask comparator}"
+      "{st|stopAt|0|Frame number to stop}"
+      "{im|imgref||Specify image file}"
+      ;
+#elif CV_MAJOR_VERSION >= 3
+    const std::string keys =
+      "{h help ?     |     | Print this message   }"
+      "{uf use_file  |false| Use a video file     }"
+      "{fn filename  |     | Specify a video file }"
+      "{uc use_cam   |false| Use a webcamera      }"
+      "{ca camera    | 0   | Specify camera index }"
+      "{co use_comp  |false| Use mask comparator  }"
+      "{st stopAt    | 0   | Frame number to stop }"
+      "{im imgref    |     | Specify a image file }"
+      ;
+#endif
+
+    cv::CommandLineParser cmd(argc, argv, keys);
+
+#if CV_MAJOR_VERSION == 2
+    if (argc <= 1 || cmd.get<bool>("help") == true)
+    {
+      std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
+      std::cout << "Available options:" << std::endl;
+      cmd.printParams();
+      return false;
+    }
+#elif CV_MAJOR_VERSION >= 3
+    if (argc <= 1 || cmd.has("help"))
+    {
+      std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
+      std::cout << "Available options:" << std::endl;
+      cmd.printMessage();
+      return false;
+    }
+    if (!cmd.check())
+    {
+      cmd.printErrors();
+      return false;
+    }
+#endif
+
+    use_file = cmd.get<bool>("uf"); //use_file
+    filename = cmd.get<std::string>("fn"); //filename
+    use_camera = cmd.get<bool>("uc"); //use_cam
+    cameraIndex = cmd.get<int>("ca"); //camera
+    use_comp = cmd.get<bool>("co"); //use_comp
+    frameToStop = cmd.get<int>("st"); //stopAt
+    imgref = cmd.get<std::string>("im"); //imgref
+
+    std::cout << "use_file:    " << use_file << std::endl;
+    std::cout << "filename:    " << filename << std::endl;
+    std::cout << "use_camera:  " << use_camera << std::endl;
+    std::cout << "cameraIndex: " << cameraIndex << std::endl;
+    std::cout << "use_comp:    " << use_comp << std::endl;
+    std::cout << "frameToStop: " << frameToStop << std::endl;
+    std::cout << "imgref:      " << imgref << std::endl;
+    //return false;
+
+    if (use_file) {
+      if (filename.empty()) {
+        std::cout << "Specify filename" << std::endl;
+        return false;
+      }
+
+      flag = true;
+    }
+
+    if (use_camera)
+      flag = true;
+
+    if (flag && use_comp) {
+      if (imgref.empty()) {
+        std::cout << "Specify image reference" << std::endl;
+        return false;
+      }
+    }
+
+    return flag;
+  }
+
+  void VideoAnalysis::start()
+  {
+    //std::cout << "Press 'ESC' to stop..." << std::endl;
+
+    do {
+      videoCapture = std::make_unique<VideoCapture>();
+      frameProcessor = std::make_shared<FrameProcessor>();
+
+      frameProcessor->init();
+      frameProcessor->frameToStop = frameToStop;
+      frameProcessor->imgref = imgref;
+
+      videoCapture->setFrameProcessor(frameProcessor);
+
+      if (use_file)
+        videoCapture->setVideo(filename);
+
+      if (use_camera)
+        videoCapture->setCamera(cameraIndex);
+
+      videoCapture->start();
+
+      if (use_file || use_camera)
+        break;
+
+      frameProcessor->finish();
+
+      auto key = cv::waitKey(500);
+      if (key == KEY_ESC)
+        break;
+
+    } while (1);
+  }
+}
diff --git a/src/VideoAnalysis.h b/src/VideoAnalysis.h
new file mode 100644
index 0000000000000000000000000000000000000000..02024a281cd14c4cf89e70693aa392025250eaf1
--- /dev/null
+++ b/src/VideoAnalysis.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <iostream>
+#include <sstream>
+
+#include "VideoCapture.h"
+#include "FrameProcessor.h"
+
+namespace bgslibrary
+{
+  class VideoAnalysis
+  {
+  private:
+    std::unique_ptr<VideoCapture> videoCapture;
+    std::shared_ptr<FrameProcessor> frameProcessor;
+    bool use_file;
+    std::string filename;
+    bool use_camera;
+    int cameraIndex;
+    bool use_comp;
+    long frameToStop;
+    std::string imgref;
+
+  public:
+    VideoAnalysis();
+    ~VideoAnalysis();
+
+    bool setup(int argc, const char **argv);
+    void start();
+  };
+}
diff --git a/VideoCapture.cpp b/src/VideoCapture.cpp
similarity index 51%
rename from VideoCapture.cpp
rename to src/VideoCapture.cpp
index b302a3f5e2921bef2c1424819f244efd5b76ac18..2b86899bf6b5435373e71810d4e2d75ae261f5a6 100644
--- a/VideoCapture.cpp
+++ b/src/VideoCapture.cpp
@@ -1,34 +1,26 @@
-/*
-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 "VideoCapture.h"
-#include <opencv2/highgui/highgui_c.h>
+
+#if  CV_MAJOR_VERSION >= 4
+//#define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES
+//#define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT
+#define CV_CAP_PROP_FPS cv::CAP_PROP_FPS
+#define CV_EVENT_LBUTTONDOWN cv::EVENT_LBUTTONDOWN
+#define CV_EVENT_MOUSEMOVE cv::EVENT_MOUSEMOVE
+#define cvSetMouseCallback cv::setMouseCallback
+#endif
 
 namespace bgslibrary
 {
   namespace VC_ROI
   {
-    IplImage* img_input1 = 0;
-    IplImage* img_input2 = 0;
+    cv::Mat img_input1;
+    cv::Mat img_input2;
     int roi_x0 = 0;
     int roi_y0 = 0;
     int roi_x1 = 0;
     int roi_y1 = 0;
     int numOfRec = 0;
-    int startDraw = 0;
+    bool startDraw = false;
     bool roi_defined = false;
     bool use_roi = true;
     bool disable_event = false;
@@ -43,7 +35,7 @@ namespace bgslibrary
     {
       if (use_roi == false || disable_event == true)
         return;
-
+      
       if (evt == CV_EVENT_LBUTTONDOWN)
       {
         if (!startDraw)
@@ -65,10 +57,11 @@ namespace bgslibrary
       if (evt == CV_EVENT_MOUSEMOVE && startDraw)
       {
         //redraw ROI selection
-        img_input2 = cvCloneImage(img_input1);
-        cvRectangle(img_input2, cvPoint(roi_x0, roi_y0), cvPoint(x, y), CV_RGB(255, 0, 0), 1);
-        cvShowImage("Input", img_input2);
-        cvReleaseImage(&img_input2);
+        img_input1.copyTo(img_input2);
+        cv::Point pt1(roi_x0, roi_y0);
+        cv::Point pt2(roi_x1, roi_y1);
+        cv::rectangle(img_input2, pt1, pt2, cv::Scalar(255, 0, 0));
+        cv::imshow("Input", img_input2);
         //startDraw = false;
         //disable_event = true;
       }
@@ -78,27 +71,26 @@ namespace bgslibrary
   VideoCapture::VideoCapture() :
     key(0), start_time(0), delta_time(0), freq(0),
     fps(0), frameNumber(0), stopAt(0), useCamera(false),
-    useVideo(false), input_resize_percent(100), showOutput(true),
-    enableFlip(false), cameraIndex(0)
+    cameraIndex(0), useVideo(false), input_resize_percent(100),
+    showOutput(true), showFPS(true), enableFlip(false)
   {
-    std::cout << "VideoCapture()" << std::endl;
+    debug_construction(VideoCapture);
+    initLoadSaveConfig(quote(VideoCapture));
   }
 
-  VideoCapture::~VideoCapture()
-  {
-    std::cout << "~VideoCapture()" << std::endl;
+  VideoCapture::~VideoCapture() {
+    debug_destruction(VideoCapture);
   }
 
-  void VideoCapture::setFrameProcessor(IFrameProcessor* frameProcessorPtr)
+  void VideoCapture::setFrameProcessor(const std::shared_ptr<IFrameProcessor> &_frameProcessor)
   {
-    frameProcessor = frameProcessorPtr;
+    frameProcessor = _frameProcessor;
   }
 
-  void VideoCapture::setCamera(int index)
+  void VideoCapture::setCamera(int _index)
   {
     useCamera = true;
-    cameraIndex = index;
-
+    cameraIndex = _index;
     useVideo = false;
   }
 
@@ -111,11 +103,10 @@ namespace bgslibrary
       std::cerr << "Cannot initialize webcam!\n" << std::endl;
   }
 
-  void VideoCapture::setVideo(std::string filename)
+  void VideoCapture::setVideo(std::string _filename)
   {
     useVideo = true;
-    videoFileName = filename;
-
+    videoFileName = _filename;
     useCamera = false;
   }
 
@@ -132,43 +123,53 @@ namespace bgslibrary
 
   void VideoCapture::start()
   {
-    loadConfig();
-
     if (useCamera) setUpCamera();
     if (useVideo)  setUpVideo();
     //if (!capture)  std::cerr << "Capture error..." << std::endl;
 
+    //using namespace std::chrono_literals;
+    do
+    {
+      capture >> frame;
+      if (frame.empty())
+      {
+        std::cout << "Frame is not ready" << std::endl;
+        std::string dummy;
+        std::cout << "Enter to continue..." << std::endl;
+        std::getline(std::cin, dummy);
+        //cv::waitKey(1000);
+        //std::this_thread::sleep_for(1s);
+      }
+      else
+        break;
+    } while (1);
+
     int input_fps = capture.get(CV_CAP_PROP_FPS);
     std::cout << "input->fps:" << input_fps << std::endl;
+    std::cout << "input->width:" << frame.size().width << std::endl;
+    std::cout << "input->height:" << frame.size().height << std::endl;
 
-    /*
-    IplImage* frame1 = cvQueryFrame(capture);
-    frame = cvCreateImage(cvSize(
-      (int)((frame1->width*input_resize_percent) / 100),
-      (int)((frame1->height*input_resize_percent) / 100)), frame1->depth, frame1->nChannels);
-    //cvCreateImage(cvSize(frame1->width/input_resize_factor, frame1->height/input_resize_factor), frame1->depth, frame1->nChannels);
-    std::cout << "input->resize_percent:" << input_resize_percent << std::endl;
-    std::cout << "input->width:" << frame->width << std::endl;
-    std::cout << "input->height:" << frame->height << std::endl;
-    */
-
-    double loopDelay = 33.333;
     if (input_fps > 0)
       loopDelay = (1. / input_fps)*1000.;
     std::cout << "loopDelay:" << loopDelay << std::endl;
 
     std::cout << "Press 'ESC' to stop..." << std::endl;
-    bool firstTime = true;
     do
     {
       frameNumber++;
 
-      cv::Mat frame;
       capture >> frame;
       if (frame.empty()) break;
 
-      //cvResize(frame1, frame);
+      cv::resize(frame, frame, cv::Size(), input_resize_percent/100., input_resize_percent / 100.);
 
+      if (firstTime && input_resize_percent != 100)
+      {
+        std::cout << "Resized to:" << std::endl;
+        std::cout << "input->width:" << frame.size().width << std::endl;
+        std::cout << "input->height:" << frame.size().height << std::endl;
+      }
+      
       //if (enableFlip)
       //  cvFlip(frame, frame, 0);
 
@@ -178,7 +179,6 @@ namespace bgslibrary
 
         do
         {
-          //cv::Mat img_input = cv::cvarrToMat(frame);
           cv::Mat img_input;
           frame.copyTo(img_input);
 
@@ -187,10 +187,10 @@ namespace bgslibrary
             cv::imshow("Input", img_input);
 
             std::cout << "Set ROI (press ESC to skip)" << std::endl;
-            VC_ROI::img_input1 = new IplImage(img_input);
+            //VC_ROI::img_input1 = new IplImage(img_input);
             cvSetMouseCallback("Input", VC_ROI::VideoCapture_on_mouse, NULL);
-            key = cvWaitKey(0);
-            delete VC_ROI::img_input1;
+            key = cv::waitKey(0);
+            //delete VC_ROI::img_input1;
           }
           else
             key = KEY_ESC;
@@ -220,36 +220,41 @@ namespace bgslibrary
         frame = frame(roi);
       }
 
-      //cv::Mat img_input = cv::cvarrToMat(frame);
       cv::Mat img_input;
       frame.copyTo(img_input);
 
-      if (showOutput)
-        cv::imshow("Input", img_input);
-
-      if (firstTime)
-        saveConfig();
-
       start_time = cv::getTickCount();
       frameProcessor->process(img_input);
-      int64 delta_time = cv::getTickCount() - start_time;
+      delta_time = cv::getTickCount() - start_time;
       freq = cv::getTickFrequency();
       fps = freq / delta_time;
       //std::cout << "FPS: " << fps << std::endl;
+      
+      if (showFPS)
+        cv::putText(img_input,
+              "FPS: " + std::to_string(fps),
+              cv::Point(10,15), // Coordinates
+              cv::FONT_HERSHEY_COMPLEX_SMALL, // Font
+              1.0, // Scale. 2.0 = 2x bigger
+              cv::Scalar(0,0,255), // BGR Color
+              1); // Line Thickness (Optional)
+
+      if (showOutput)
+        cv::imshow("Input", img_input);
 
       //cvResetImageROI(frame);
 
-      key = cvWaitKey(loopDelay);
+      key = cv::waitKey(loopDelay);
       //std::cout << "key: " << key << std::endl;
 
       if (key == KEY_SPACE)
-        key = cvWaitKey(0);
+        key = cv::waitKey(0);
 
       if (key == KEY_ESC)
         break;
 
       if (stopAt > 0 && stopAt == frameNumber)
-        key = cvWaitKey(0);
+        key = cv::waitKey(0);
 
       firstTime = false;
     } while (1);
@@ -257,39 +262,31 @@ namespace bgslibrary
     capture.release();
   }
 
-  void VideoCapture::saveConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_WRITE);
-
-    cvWriteInt(fs, "stopAt", stopAt);
-    cvWriteInt(fs, "input_resize_percent", input_resize_percent);
-    cvWriteInt(fs, "enableFlip", enableFlip);
-    cvWriteInt(fs, "use_roi", VC_ROI::use_roi);
-    cvWriteInt(fs, "roi_defined", VC_ROI::roi_defined);
-    cvWriteInt(fs, "roi_x0", VC_ROI::roi_x0);
-    cvWriteInt(fs, "roi_y0", VC_ROI::roi_y0);
-    cvWriteInt(fs, "roi_x1", VC_ROI::roi_x1);
-    cvWriteInt(fs, "roi_y1", VC_ROI::roi_y1);
-    cvWriteInt(fs, "showOutput", showOutput);
-
-    cvReleaseFileStorage(&fs);
+  void VideoCapture::save_config(cv::FileStorage &fs) {
+    fs << "stopAt" << stopAt;
+    fs << "input_resize_percent" << input_resize_percent;
+    fs << "enableFlip" << enableFlip;
+    fs << "use_roi" << VC_ROI::use_roi;
+    fs << "roi_defined" << VC_ROI::roi_defined;
+    fs << "roi_x0" << VC_ROI::roi_x0;
+    fs << "roi_y0" << VC_ROI::roi_y0;
+    fs << "roi_x1" << VC_ROI::roi_x1;
+    fs << "roi_y1" << VC_ROI::roi_y1;
+    fs << "showFPS" << showFPS;
+    fs << "showOutput" << showOutput;
   }
 
-  void VideoCapture::loadConfig()
-  {
-    CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_READ);
-
-    stopAt = cvReadIntByName(fs, 0, "stopAt", 0);
-    input_resize_percent = cvReadIntByName(fs, 0, "input_resize_percent", 100);
-    enableFlip = cvReadIntByName(fs, 0, "enableFlip", false);
-    VC_ROI::use_roi = cvReadIntByName(fs, 0, "use_roi", true);
-    VC_ROI::roi_defined = cvReadIntByName(fs, 0, "roi_defined", false);
-    VC_ROI::roi_x0 = cvReadIntByName(fs, 0, "roi_x0", 0);
-    VC_ROI::roi_y0 = cvReadIntByName(fs, 0, "roi_y0", 0);
-    VC_ROI::roi_x1 = cvReadIntByName(fs, 0, "roi_x1", 0);
-    VC_ROI::roi_y1 = cvReadIntByName(fs, 0, "roi_y1", 0);
-    showOutput = cvReadIntByName(fs, 0, "showOutput", true);
-
-    cvReleaseFileStorage(&fs);
+  void VideoCapture::load_config(cv::FileStorage &fs) {
+    fs["stopAt"] >> stopAt;
+    fs["input_resize_percent"] >> input_resize_percent;
+    fs["enableFlip"] >> enableFlip;
+    fs["use_roi"] >> VC_ROI::use_roi;
+    fs["roi_defined"] >> VC_ROI::roi_defined;
+    fs["roi_x0"] >> VC_ROI::roi_x0;
+    fs["roi_y0"] >> VC_ROI::roi_y0;
+    fs["roi_x1"] >> VC_ROI::roi_x1;
+    fs["roi_y1"] >> VC_ROI::roi_y1;
+    fs["showFPS"] >> showFPS;
+    fs["showOutput"] >> showOutput;
   }
 }
diff --git a/src/VideoCapture.h b/src/VideoCapture.h
new file mode 100644
index 0000000000000000000000000000000000000000..9eaec286c178bddd3bfb0430710e8dcf5bb31572
--- /dev/null
+++ b/src/VideoCapture.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+//#include <chrono>
+//#include <thread>
+#include <opencv2/opencv.hpp>
+// opencv legacy includes
+//#include <opencv2/highgui/highgui_c.h>
+//#include <opencv2/imgproc/imgproc_c.h>
+//#include <opencv2/imgproc/types_c.h>
+
+#include "utils/GenericKeys.h"
+#include "utils/ILoadSaveConfig.h"
+#include "IFrameProcessor.h"
+
+namespace bgslibrary
+{
+  class VideoCapture : public ILoadSaveConfig
+  {
+  private:
+    std::shared_ptr<IFrameProcessor> frameProcessor;
+    cv::VideoCapture capture;
+    cv::Mat frame;
+    int key;
+    int64 start_time;
+    int64 delta_time;
+    double freq;
+    double fps;
+    int frameNumber;
+    int stopAt;
+    bool useCamera;
+    int cameraIndex;
+    bool useVideo;
+    std::string videoFileName;
+    int input_resize_percent;
+    bool showOutput;
+    bool showFPS;
+    bool enableFlip;
+    double loopDelay = 33.333;
+    bool firstTime = true;
+
+  public:
+    VideoCapture();
+    ~VideoCapture();
+
+    void setFrameProcessor(const std::shared_ptr<IFrameProcessor> &_frameProcessor);
+    void setCamera(int _index);
+    void setVideo(std::string _filename);
+    void start();
+
+  private:
+    void setUpCamera();
+    void setUpVideo();
+    
+    void save_config(cv::FileStorage &fs);
+    void load_config(cv::FileStorage &fs);
+  };
+}
diff --git a/src/algorithms/AdaptiveBackgroundLearning.cpp b/src/algorithms/AdaptiveBackgroundLearning.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d239dd0a0de50b52d0cba9ec3ee18e24989bfbb9
--- /dev/null
+++ b/src/algorithms/AdaptiveBackgroundLearning.cpp
@@ -0,0 +1,82 @@
+#include "AdaptiveBackgroundLearning.h"
+
+using namespace bgslibrary::algorithms;
+
+AdaptiveBackgroundLearning::AdaptiveBackgroundLearning() :
+  IBGS(quote(AdaptiveBackgroundLearning)),
+  alpha(0.05), limit(-1), counter(0), minVal(0.0),
+  maxVal(1.0), enableThreshold(true), threshold(15)
+{
+  debug_construction(AdaptiveBackgroundLearning);
+  initLoadSaveConfig(algorithmName);
+}
+
+AdaptiveBackgroundLearning::~AdaptiveBackgroundLearning() {
+  debug_destruction(AdaptiveBackgroundLearning);
+}
+
+void AdaptiveBackgroundLearning::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (img_background.empty())
+    img_input.copyTo(img_background);
+
+  cv::Mat img_input_f(img_input.size(), CV_32F);
+  img_input.convertTo(img_input_f, CV_32F, 1. / 255.);
+
+  cv::Mat img_background_f(img_background.size(), CV_32F);
+  img_background.convertTo(img_background_f, CV_32F, 1. / 255.);
+
+  cv::Mat img_diff_f(img_input.size(), CV_32F);
+  cv::absdiff(img_input_f, img_background_f, img_diff_f);
+
+  if ((limit > 0 && limit < counter) || limit == -1)
+  {
+    img_background_f = alpha*img_input_f + (1 - alpha)*img_background_f;
+
+    cv::Mat img_new_background(img_input.size(), CV_8U);
+    img_background_f.convertTo(img_new_background, CV_8U, 255.0 / (maxVal - minVal), -minVal);
+    img_new_background.copyTo(img_background);
+
+    if (limit > 0 && limit < counter)
+      counter++;
+  }
+
+  //cv::Mat img_foreground(img_input.size(), CV_8U);
+  img_diff_f.convertTo(img_foreground, CV_8UC1, 255.0 / (maxVal - minVal), -minVal);
+
+  if (img_foreground.channels() == 3)
+    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
+
+  if (enableThreshold)
+    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void AdaptiveBackgroundLearning::save_config(cv::FileStorage &fs) {
+  fs << "alpha" << alpha;
+  fs << "limit" << limit;
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void AdaptiveBackgroundLearning::load_config(cv::FileStorage &fs) {
+  fs["alpha"] >> alpha;
+  fs["limit"] >> limit;
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/AdaptiveBackgroundLearning.h b/src/algorithms/AdaptiveBackgroundLearning.h
new file mode 100644
index 0000000000000000000000000000000000000000..5884ed4a133ad4ba4de58d5d04e8ba32aa63c2ff
--- /dev/null
+++ b/src/algorithms/AdaptiveBackgroundLearning.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class AdaptiveBackgroundLearning : public IBGS
+    {
+    private:
+      double alpha;
+      int limit;
+      long counter;
+      double minVal;
+      double maxVal;
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      AdaptiveBackgroundLearning();
+      ~AdaptiveBackgroundLearning();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(AdaptiveBackgroundLearning);
+  }
+}
diff --git a/src/algorithms/AdaptiveSelectiveBackgroundLearning.cpp b/src/algorithms/AdaptiveSelectiveBackgroundLearning.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..84893b0a414df68c011cf99aed176e46dbcefc3a
--- /dev/null
+++ b/src/algorithms/AdaptiveSelectiveBackgroundLearning.cpp
@@ -0,0 +1,97 @@
+#include "AdaptiveSelectiveBackgroundLearning.h"
+
+using namespace bgslibrary::algorithms;
+
+AdaptiveSelectiveBackgroundLearning::AdaptiveSelectiveBackgroundLearning() :
+  IBGS(quote(AdaptiveSelectiveBackgroundLearning)),
+  alphaLearn(0.05), alphaDetection(0.05), learningFrames(-1), 
+  counter(0), minVal(0.0), maxVal(1.0), threshold(15)
+{
+  debug_construction(AdaptiveSelectiveBackgroundLearning);
+  initLoadSaveConfig(algorithmName);
+}
+
+AdaptiveSelectiveBackgroundLearning::~AdaptiveSelectiveBackgroundLearning() {
+  debug_destruction(AdaptiveSelectiveBackgroundLearning);
+}
+
+void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input_, img_output, img_bgmodel);
+
+  cv::Mat img_input;
+  if (img_input_.channels() == 3)
+    cv::cvtColor(img_input_, img_input, CV_BGR2GRAY);
+  else
+    img_input_.copyTo(img_input);
+
+  if (img_background.empty())
+    img_input.copyTo(img_background);
+
+  cv::Mat img_input_f(img_input.size(), CV_32F);
+  img_input.convertTo(img_input_f, CV_32F, 1. / 255.);
+
+  cv::Mat img_background_f(img_background.size(), CV_32F);
+  img_background.convertTo(img_background_f, CV_32F, 1. / 255.);
+
+  cv::Mat img_diff_f(img_input.size(), CV_32F);
+  cv::absdiff(img_input_f, img_background_f, img_diff_f);
+
+  //cv::Mat img_foreground(img_input.size(), CV_8U);
+  img_diff_f.convertTo(img_foreground, CV_8U, 255.0 / (maxVal - minVal), -minVal);
+
+  cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
+  cv::medianBlur(img_foreground, img_foreground, 3);
+
+  if (learningFrames > 0 && counter <= learningFrames) {
+    //std::cout << "Adaptive update..." << std::endl;
+    // Only Adaptive update of the background model
+    img_background_f = alphaLearn * img_input_f + (1 - alphaLearn) * img_background_f;
+    counter++;
+  }
+  else {
+    //std::cout << "Adaptive and Selective update..." << std::endl;
+    int rows = img_input.rows;
+    int cols = img_input.cols;
+    for (int i = 0; i < rows; i++) {
+      for (int j = 0; j < cols; j++) {
+        // Adaptive and Selective update of the background model
+        if (img_foreground.at<uchar>(i, j) == 0) {
+          img_background_f.at<float>(i, j) = alphaDetection * img_input_f.at<float>(i, j) + (1 - alphaDetection) * img_background_f.at<float>(i, j);
+        }
+      }
+    }
+  }
+
+  //cv::Mat img_new_background(img_input.size(), CV_8U);
+  img_background_f.convertTo(img_background, CV_8UC1, 255.0 / (maxVal - minVal), -minVal);
+  //img_new_background.copyTo(img_background);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void AdaptiveSelectiveBackgroundLearning::save_config(cv::FileStorage &fs) {
+  fs << "learningFrames" << learningFrames;
+  fs << "alphaLearn" << alphaLearn;
+  fs << "alphaDetection" << alphaDetection;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void AdaptiveSelectiveBackgroundLearning::load_config(cv::FileStorage &fs) {
+  fs["learningFrames"] >> learningFrames;
+  fs["alphaLearn"] >> alphaLearn;
+  fs["alphaDetection"] >> alphaDetection;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/AdaptiveSelectiveBackgroundLearning.h b/src/algorithms/AdaptiveSelectiveBackgroundLearning.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5ad7c91b773450411bbaa7c7465554e62bdcdfd
--- /dev/null
+++ b/src/algorithms/AdaptiveSelectiveBackgroundLearning.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class AdaptiveSelectiveBackgroundLearning : public IBGS
+    {
+    private:
+      double alphaLearn;
+      double alphaDetection;
+      int learningFrames;
+      long counter;
+      double minVal;
+      double maxVal;
+      int threshold;
+
+    public:
+      AdaptiveSelectiveBackgroundLearning();
+      ~AdaptiveSelectiveBackgroundLearning();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(AdaptiveSelectiveBackgroundLearning);
+  }
+}
diff --git a/src/algorithms/CodeBook.cpp b/src/algorithms/CodeBook.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7aa828ea968dbff02f8a2291580392dc20df0db
--- /dev/null
+++ b/src/algorithms/CodeBook.cpp
@@ -0,0 +1,191 @@
+#include "CodeBook.h"
+
+using namespace bgslibrary::algorithms;
+
+CodeBook::CodeBook() :
+  IBGS(quote(CodeBook)),
+  t(0), learningFrames(DEFAULT_LEARNFRAMES), 
+  alpha(DEFAULT_ALPHA), beta(DEFAULT_BETA)
+{
+  debug_construction(CodeBook);
+  initLoadSaveConfig(algorithmName);
+}
+
+CodeBook::~CodeBook() {
+  debug_destruction(CodeBook);
+}
+
+void CodeBook::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+  
+  if(firstTime) {
+    img_foreground = cv::Mat::zeros(img_input.size(), CV_8UC1);
+    //img_background = cv::Mat::zeros(img_input.size(), CV_8UC3);
+    initializeCodebook(img_input.rows, img_input.cols);
+  } 
+
+  cv::Mat img_input_gray;
+
+  if (img_input.channels() == 1)
+    img_input_gray = img_input; 
+  else
+    cv::cvtColor(img_input, img_input_gray, CV_BGR2GRAY);
+
+  fg_cb(img_input_gray, img_foreground);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    //cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  //img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void CodeBook::initializeCodebook(int w, int h)
+{
+  cbMain = new std::vector<codeword>*[w];
+  for (int i = 0; i < w; ++i)
+    cbMain[i] = new std::vector<codeword>[h];
+
+  cbCache = new std::vector<codeword>*[w];
+  for (int i = 0; i < w; ++i)
+    cbCache[i] = new std::vector<codeword>[h];
+}
+
+void CodeBook::update_cb(const cv::Mat& frame)
+{
+  if (t > learningFrames)
+    return;
+
+  for (int i = 0; i < frame.rows; i++)
+  {
+    for (int j = 0; j < frame.cols; j++)
+    {
+      int pix = frame.at<uchar>(i, j);
+      std::vector<codeword>& cm = cbMain[i][j];
+      bool found = false;
+      for (int k = 0; k < (int)cm.size(); k++)
+      {
+        if (cm[k].min <= pix && pix <= cm[k].max && !found)
+        {
+          found = true;
+          cm[k].min = ((pix - alpha) + (cm[k].f*cm[k].min)) / (cm[k].f + 1);
+          cm[k].max = ((pix + alpha) + (cm[k].f*cm[k].max)) / (cm[k].f + 1);
+          cm[k].l = 0;
+          cm[k].last = t;
+          cm[k].f++;
+        }
+        else
+        {
+          cm[k].l++;
+        }
+      }
+      if (!found)
+      {
+        codeword n = {};
+        n.min = std::max(0, pix - alpha);
+        n.max = std::min(255, pix + alpha);
+        n.f = 1;
+        n.l = 0;
+        n.first = t;
+        n.last = t;
+        cm.push_back(n);
+      }
+    }
+  }
+  t++;
+}
+
+void CodeBook::fg_cb(const cv::Mat& frame, cv::Mat& fg)
+{
+  //fg = cv::Mat::zeros(frame.size(), CV_8UC1);
+  //if (cbMain == 0) initializeCodebook(frame.rows, frame.cols);
+  
+  if (t <= learningFrames) {
+    update_cb(frame);
+    return;
+  }
+
+  for (int i = 0; i<frame.rows; i++)
+  {
+    for (int j = 0; j<frame.cols; j++)
+    {
+      int pix = frame.at<uchar>(i, j);
+      std::vector<codeword>& cm = cbMain[i][j];
+      bool found = false;
+      for (int k = 0; k < (int)cm.size(); k++)
+      {
+        if (cm[k].min <= pix && pix <= cm[k].max && !found)
+        {
+          cm[k].min = ((1 - beta)*(pix - alpha)) + (beta*cm[k].min);
+          cm[k].max = ((1 - beta)*(pix + alpha)) + (beta*cm[k].max);
+          cm[k].l = 0;
+          cm[k].first = t;
+          cm[k].f++;
+          found = true;
+        }
+        else
+          cm[k].l++;
+      }
+      cm.erase(remove_if(cm.begin(), cm.end(), [](codeword& c) { return c.l >= Tdel; }), cm.end());
+      fg.at<uchar>(i, j) = found ? 0 : 255;
+      if (found) continue;
+      found = false;
+      std::vector<codeword>& cc = cbCache[i][j];
+      for (int k = 0; k < (int)cc.size(); k++)
+      {
+        if (cc[k].min <= pix && pix <= cc[k].max && !found)
+        {
+          cc[k].min = ((1 - beta)*(pix - alpha)) + (beta*cc[k].min);
+          cc[k].max = ((1 - beta)*(pix + alpha)) + (beta*cc[k].max);
+          cc[k].l = 0;
+          cc[k].first = t;
+          cc[k].f++;
+          found = true;
+        }
+        else
+          cc[k].l++;
+      }
+
+      if (!found)
+      {
+        codeword n = {};
+        n.min = std::max(0, pix - alpha);
+        n.max = std::min(255, pix + alpha);
+        n.f = 1;
+        n.l = 0;
+        n.first = t;
+        n.last = t;
+        cc.push_back(n);
+      }
+
+      cc.erase(remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.l >= Th; }), cc.end());
+
+      for (std::vector<codeword>::iterator it = cc.begin(); it != cc.end(); it++)
+        if (it->f > Tadd)
+          cm.push_back(*it);
+
+      cc.erase(remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.f > Tadd; }), cc.end());
+    }
+  }
+}
+
+void CodeBook::save_config(cv::FileStorage &fs) {
+  fs << "alpha" << alpha;
+  fs << "beta" << beta;
+  fs << "learningFrames" << learningFrames;
+  fs << "showOutput" << showOutput;
+}
+
+void CodeBook::load_config(cv::FileStorage &fs) {
+  fs["alpha"] >> alpha;
+  fs["beta"] >> beta;
+  fs["learningFrames"] >> learningFrames;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/CodeBook.h b/src/algorithms/CodeBook.h
new file mode 100644
index 0000000000000000000000000000000000000000..512d59bdbebfae780509f6ecfe27229aa835299b
--- /dev/null
+++ b/src/algorithms/CodeBook.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include <opencv2/opencv.hpp>
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace codebook {
+      struct codeword {
+        float min;
+        float max;
+        float f;
+        float l;
+        int first;
+        int last;
+        bool isStale;
+      };
+    }
+
+    class CodeBook : public IBGS
+    {
+    public:
+      typedef codebook::codeword codeword;
+
+      CodeBook();
+      ~CodeBook();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      static const int Tdel = 200;
+      static const int Tadd = 150;
+      static const int Th = 200;
+      const int DEFAULT_ALPHA = 10;
+      const float DEFAULT_BETA = 1.;
+      const int DEFAULT_LEARNFRAMES = 10;
+      int t = 0;
+      int learningFrames = 10;
+      int alpha = 10;
+      float beta = 1;
+      std::vector<codeword> **cbMain;
+      std::vector<codeword> **cbCache;
+
+      void initializeCodebook(int w, int h);
+      void update_cb(const cv::Mat& frame);
+      void fg_cb(const cv::Mat& frame, cv::Mat& fg);
+      
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(CodeBook);
+  }
+}
diff --git a/src/algorithms/DPAdaptiveMedian.cpp b/src/algorithms/DPAdaptiveMedian.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d8c0bc84d993fbeda1e2cdd7f18be6beb7926941
--- /dev/null
+++ b/src/algorithms/DPAdaptiveMedian.cpp
@@ -0,0 +1,92 @@
+#include "DPAdaptiveMedian.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPAdaptiveMedian::DPAdaptiveMedian() :
+  IBGS(quote(DPAdaptiveMedian)),
+  frameNumber(0), threshold(40), 
+  samplingRate(7), learningFrames(30)
+{
+  debug_construction(DPAdaptiveMedian);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPAdaptiveMedian::~DPAdaptiveMedian() {
+  debug_destruction(DPAdaptiveMedian);
+}
+
+void DPAdaptiveMedian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    params.SamplingRate() = samplingRate;
+    params.LearningFrames() = learningFrames;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  //bitwise_not(img_foreground, img_foreground);
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPAdaptiveMedian::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "samplingRate" << samplingRate;
+  fs << "learningFrames" << learningFrames;
+  fs << "showOutput" << showOutput;
+}
+
+void DPAdaptiveMedian::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["samplingRate"] >> samplingRate;
+  fs["learningFrames"] >> learningFrames;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPAdaptiveMedian.h b/src/algorithms/DPAdaptiveMedian.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbad2da636f3553c842ee5ff5ebe9d0beca80f56
--- /dev/null
+++ b/src/algorithms/DPAdaptiveMedian.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "dp/AdaptiveMedianBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPAdaptiveMedian : public IBGS
+    {
+    private:
+      long frameNumber;
+      int threshold;
+      int samplingRate;
+      int learningFrames;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::AdaptiveMedianParams params;
+      dp::AdaptiveMedianBGS bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPAdaptiveMedian();
+      ~DPAdaptiveMedian();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPAdaptiveMedian);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPEigenbackground.cpp b/src/algorithms/DPEigenbackground.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..770cc6102e2da8324b7ccf92e7e2ad411e3cba87
--- /dev/null
+++ b/src/algorithms/DPEigenbackground.cpp
@@ -0,0 +1,92 @@
+#include "DPEigenbackground.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPEigenbackground::DPEigenbackground() :
+  IBGS(quote(DPEigenbackground)),
+  frameNumber(0), threshold(225), 
+  historySize(20), embeddedDim(10)
+{
+  debug_construction(DPEigenbackground);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPEigenbackground::~DPEigenbackground() {
+  debug_destruction(DPEigenbackground);
+}
+
+void DPEigenbackground::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold; //15*15;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    //params.HistorySize() = 100;
+    params.HistorySize() = historySize;
+    //params.EmbeddedDim() = 20;
+    params.EmbeddedDim() = embeddedDim;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPEigenbackground::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "historySize" << historySize;
+  fs << "embeddedDim" << embeddedDim;
+  fs << "showOutput" << showOutput;
+}
+
+void DPEigenbackground::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["historySize"] >> historySize;
+  fs["embeddedDim"] >> embeddedDim;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPEigenbackground.h b/src/algorithms/DPEigenbackground.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d9b18dff20b25c6448e64429cfa5cb9a50fce71
--- /dev/null
+++ b/src/algorithms/DPEigenbackground.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/Eigenbackground.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPEigenbackground : public IBGS
+    {
+    private:
+      long frameNumber;
+      int threshold;
+      int historySize;
+      int embeddedDim;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::EigenbackgroundParams params;
+      dp::Eigenbackground bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPEigenbackground();
+      ~DPEigenbackground();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPEigenbackground);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPGrimsonGMM.cpp b/src/algorithms/DPGrimsonGMM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77e26931c1acae0e7ad93e6bbacc64b05d6bf9af
--- /dev/null
+++ b/src/algorithms/DPGrimsonGMM.cpp
@@ -0,0 +1,91 @@
+#include "DPGrimsonGMM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPGrimsonGMM::DPGrimsonGMM() :
+  IBGS(quote(DPGrimsonGMM)),
+  frameNumber(0), threshold(9.0), 
+  alpha(0.01), gaussians(3)
+{
+  debug_construction(DPGrimsonGMM);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPGrimsonGMM::~DPGrimsonGMM() {
+  debug_destruction(DPGrimsonGMM);
+}
+
+void DPGrimsonGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold; //3.0f*3.0f;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    //params.Alpha() = 0.001f;
+    params.Alpha() = alpha; //0.01f;
+    params.MaxModes() = gaussians; //3;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPGrimsonGMM::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
+}
+
+void DPGrimsonGMM::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPGrimsonGMM.h b/src/algorithms/DPGrimsonGMM.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d3d3e3edc5133ebc654cd14898e0a8fb6824ef1
--- /dev/null
+++ b/src/algorithms/DPGrimsonGMM.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/GrimsonGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPGrimsonGMM : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      int gaussians;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::GrimsonParams params;
+      dp::GrimsonGMM bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPGrimsonGMM();
+      ~DPGrimsonGMM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPGrimsonGMM);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPMean.cpp b/src/algorithms/DPMean.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..766e37914004029fcf607acf2a51c136850e72eb
--- /dev/null
+++ b/src/algorithms/DPMean.cpp
@@ -0,0 +1,91 @@
+#include "DPMean.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPMean::DPMean() :
+  IBGS(quote(DPMean)),
+  frameNumber(0), threshold(2700),
+  alpha(1e-6f), learningFrames(30)
+{
+  debug_construction(DPMean);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPMean::~DPMean() {
+  debug_destruction(DPMean);
+}
+
+void DPMean::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold; //3*30*30; // 2700
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    //params.Alpha() = 1e-6f;
+    params.Alpha() = alpha;
+    params.LearningFrames() = learningFrames;//30;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPMean::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "learningFrames" << learningFrames;
+  fs << "showOutput" << showOutput;
+}
+
+void DPMean::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["learningFrames"] >> learningFrames;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPMean.h b/src/algorithms/DPMean.h
new file mode 100644
index 0000000000000000000000000000000000000000..311906f13329ca0f4a987f5ff59def959104427e
--- /dev/null
+++ b/src/algorithms/DPMean.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/MeanBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPMean : public IBGS
+    {
+    private:
+      long frameNumber;
+      int threshold;
+      double alpha;
+      int learningFrames;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::MeanParams params;
+      dp::MeanBGS bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPMean();
+      ~DPMean();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPMean);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPPratiMediod.cpp b/src/algorithms/DPPratiMediod.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b53552b5e8b0d335ef7669ba534fe837b1996caf
--- /dev/null
+++ b/src/algorithms/DPPratiMediod.cpp
@@ -0,0 +1,94 @@
+#include "DPPratiMediod.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPPratiMediod::DPPratiMediod() :
+  IBGS(quote(DPPratiMediod)),
+  frameNumber(0), threshold(30), samplingRate(5), 
+  historySize(16), weight(5)
+{
+  debug_construction(DPPratiMediod);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPPratiMediod::~DPPratiMediod() {
+  debug_destruction(DPPratiMediod);
+}
+
+void DPPratiMediod::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    params.SamplingRate() = samplingRate;
+    params.HistorySize() = historySize;
+    params.Weight() = weight;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPPratiMediod::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "samplingRate" << samplingRate;
+  fs << "historySize" << historySize;
+  fs << "weight" << weight;
+  fs << "showOutput" << showOutput;
+}
+
+void DPPratiMediod::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["samplingRate"] >> samplingRate;
+  fs["historySize"] >> historySize;
+  fs["weight"] >> weight;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPPratiMediod.h b/src/algorithms/DPPratiMediod.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb93683ac93acee4fa32ab4db18c8d88cd1813bb
--- /dev/null
+++ b/src/algorithms/DPPratiMediod.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/PratiMediodBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPPratiMediod : public IBGS
+    {
+    private:
+      long frameNumber;
+      int threshold;
+      int samplingRate;
+      int historySize;
+      int weight;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::PratiParams params;
+      dp::PratiMediodBGS bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPPratiMediod();
+      ~DPPratiMediod();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPPratiMediod);
+  }
+}
+
+#endif
diff --git a/package_bgs/DPTexture.cpp b/src/algorithms/DPTexture.cpp
similarity index 57%
rename from package_bgs/DPTexture.cpp
rename to src/algorithms/DPTexture.cpp
index 3285ccf83ecdcd0698bcfcfb9622188784144050..ba33e9f0053278120a5d9a1ce31f2db2e84cb183 100644
--- a/package_bgs/DPTexture.cpp
+++ b/src/algorithms/DPTexture.cpp
@@ -1,32 +1,19 @@
-/*
-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 "DPTexture.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 using namespace bgslibrary::algorithms;
 
-DPTexture::DPTexture()
-// : enableFiltering(true)
+DPTexture::DPTexture() :
+  IBGS(quote(DPTexture))
+  //, enableFiltering(true)
 {
-  std::cout << "DPTexture()" << std::endl;
-  setup("./config/DPTexture.xml");
+  debug_construction(DPTexture);
+  initLoadSaveConfig(algorithmName);
 }
 
-DPTexture::~DPTexture()
-{
+DPTexture::~DPTexture() {
+  debug_destruction(DPTexture);
   delete[] bgModel; // ~10Kb (25.708-15.968)
   delete[] modeArray;
   delete[] curTextureHist; // ~10Kb (16-6.396)
@@ -36,17 +23,20 @@ DPTexture::~DPTexture()
   fgMask.ReleaseImage();
   tempMask.ReleaseImage();
   texture.ReleaseImage();
-  std::cout << "~DPTexture()" << std::endl;
 }
 
 void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
 {
   init(img_input, img_output, img_bgmodel);
 
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
   frame = new IplImage(img_input);
+#endif
 
-  if (firstTime)
-  {
+  if (firstTime) {
     width = img_input.size().width;
     height = img_input.size().height;
     size = width * height;
@@ -62,25 +52,20 @@ void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
     cvZero(tempMask.Ptr());
 
     // create background model
-    bgModel = new TextureArray[size];
+    bgModel = new dp::TextureArray[size];
     texture = cvCreateImage(cvSize(width, height), 8, 3);
     cvZero(texture.Ptr());
     modeArray = new unsigned char[size];
-    curTextureHist = new TextureHistogram[size];
+    curTextureHist = new dp::TextureHistogram[size];
 
     // initialize background model
     bgs.LBP(image, texture);
     bgs.Histogram(texture, curTextureHist);
-    for (int y = REGION_R + TEXTURE_R; y < height - REGION_R - TEXTURE_R; ++y)
-    {
-      for (int x = REGION_R + TEXTURE_R; x < width - REGION_R - TEXTURE_R; ++x)
-      {
+    for (int y = dp::REGION_R + dp::TEXTURE_R; y < height - dp::REGION_R - dp::TEXTURE_R; ++y) {
+      for (int x = dp::REGION_R + dp::TEXTURE_R; x < width - dp::REGION_R - dp::TEXTURE_R; ++x) {
         int index = x + y*width;
-
-        for (int m = 0; m < NUM_MODES; ++m)
-        {
-          for (int i = 0; i < NUM_BINS; ++i)
-          {
+        for (int m = 0; m < dp::NUM_MODES; ++m) {
+          for (int i = 0; i < dp::NUM_BINS; ++i) {
             bgModel[index].mode[m].r[i] = curTextureHist[index].r[i];
             bgModel[index].mode[m].g[i] = curTextureHist[index].g[i];
             bgModel[index].mode[m].b[i] = curTextureHist[index].b[i];
@@ -99,7 +84,7 @@ void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
   // perform background subtraction
   bgs.LBP(image, texture);
   bgs.Histogram(texture, curTextureHist);
-  bgs.BgsCompare(bgModel, curTextureHist, modeArray, THRESHOLD, fgMask);
+  bgs.BgsCompare(bgModel, curTextureHist, modeArray, dp::THRESHOLD, fgMask);
 
   //if(enableFiltering)
   //{
@@ -124,7 +109,7 @@ void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
 
 #ifndef MEX_COMPILE_FLAG
   if (showOutput)
-    cv::imshow("Texture BGS (Donovan Parks)", img_foreground);
+    cv::imshow(algorithmName + "_FG", img_foreground);
 #endif
 
   img_foreground.copyTo(img_output);
@@ -136,24 +121,16 @@ void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
   delete frame;
 }
 
-void DPTexture::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  //cvWriteReal(fs, "alpha", alpha);
-  //cvWriteInt(fs, "enableFiltering", enableFiltering);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void DPTexture::save_config(cv::FileStorage &fs) {
+  //fs << "alpha" << alpha;
+  //fs << "enableFiltering" << enableFiltering;
+  fs << "showOutput" << showOutput;
 }
 
-void DPTexture::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  //alpha = cvReadRealByName(fs, nullptr, "alpha", 1e-6f);
-  //enableFiltering = cvReadIntByName(fs, nullptr, "enableFiltering", true);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void DPTexture::load_config(cv::FileStorage &fs) {
+  //fs["alpha"] >> alpha;
+  //fs["enableFiltering"] >> enableFiltering;
+  fs["showOutput"] >> showOutput;
 }
+
+#endif
diff --git a/src/algorithms/DPTexture.h b/src/algorithms/DPTexture.h
new file mode 100644
index 0000000000000000000000000000000000000000..b78dffeca593a7fae41486d9262b4248eb0ffc9e
--- /dev/null
+++ b/src/algorithms/DPTexture.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+// opencv legacy includes
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/types_c.h"
+#include "opencv2/imgproc/imgproc_c.h"
+
+#include "dp/TextureBGS.h"
+//#include "ConnectedComponents.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPTexture : public IBGS
+    {
+    private:
+      int width;
+      int height;
+      int size;
+      unsigned char* modeArray;
+      IplImage* frame;
+      dp::TextureBGS bgs;
+      dp::RgbImage image;
+      dp::BwImage fgMask;
+      dp::BwImage tempMask;
+      dp::TextureArray* bgModel;
+      dp::RgbImage texture;
+      dp::TextureHistogram* curTextureHist;
+      //ConnectedComponents cc;
+      //CBlobResult largeBlobs;
+      //IplConvKernel* dilateElement;
+      //IplConvKernel* erodeElement;
+      //bool enableFiltering;
+
+    public:
+      DPTexture();
+      ~DPTexture();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPTexture);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPWrenGA.cpp b/src/algorithms/DPWrenGA.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3f5df22e33260126363a4b5aa5c315f268fc016
--- /dev/null
+++ b/src/algorithms/DPWrenGA.cpp
@@ -0,0 +1,90 @@
+#include "DPWrenGA.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPWrenGA::DPWrenGA() :
+  IBGS(quote(DPWrenGA)),
+  frameNumber(0), threshold(12.25f), 
+  alpha(0.005f), learningFrames(30)
+{
+  debug_construction(DPWrenGA);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPWrenGA::~DPWrenGA() {
+  debug_destruction(DPWrenGA);
+}
+
+void DPWrenGA::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold; //3.5f*3.5f;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    params.Alpha() = alpha; //0.005f;
+    params.LearningFrames() = learningFrames; //30;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPWrenGA::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "learningFrames" << learningFrames;
+  fs << "showOutput" << showOutput;
+}
+
+void DPWrenGA::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["learningFrames"] >> learningFrames;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPWrenGA.h b/src/algorithms/DPWrenGA.h
new file mode 100644
index 0000000000000000000000000000000000000000..4be0d8ca907677df681ef9ece231c5f4ceb41d09
--- /dev/null
+++ b/src/algorithms/DPWrenGA.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/WrenGA.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPWrenGA : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      int learningFrames;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::WrenParams params;
+      dp::WrenGA bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPWrenGA();
+      ~DPWrenGA();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPWrenGA);
+  }
+}
+
+#endif
diff --git a/src/algorithms/DPZivkovicAGMM.cpp b/src/algorithms/DPZivkovicAGMM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6fd403ca0959513b0a072e480ceccb38ad051896
--- /dev/null
+++ b/src/algorithms/DPZivkovicAGMM.cpp
@@ -0,0 +1,90 @@
+#include "DPZivkovicAGMM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+DPZivkovicAGMM::DPZivkovicAGMM() :
+  IBGS(quote(DPZivkovicAGMM)),
+  frameNumber(0), threshold(25.0f), 
+  alpha(0.001f), gaussians(3)
+{
+  debug_construction(DPZivkovicAGMM);
+  initLoadSaveConfig(algorithmName);
+}
+
+DPZivkovicAGMM::~DPZivkovicAGMM() {
+  debug_destruction(DPZivkovicAGMM);
+}
+
+void DPZivkovicAGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold; //5.0f*5.0f;
+    params.HighThreshold() = 2 * params.LowThreshold();	// Note: high threshold is used by post-processing
+    params.Alpha() = alpha; //0.001f;
+    params.MaxModes() = gaussians; //3;
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void DPZivkovicAGMM::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
+}
+
+void DPZivkovicAGMM::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/DPZivkovicAGMM.h b/src/algorithms/DPZivkovicAGMM.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca2c1a6e2e210f42de1a8bff3fa8f3c43cc141fa
--- /dev/null
+++ b/src/algorithms/DPZivkovicAGMM.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "dp/ZivkovicAGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class DPZivkovicAGMM : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      int gaussians;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::ZivkovicParams params;
+      dp::ZivkovicAGMM bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      DPZivkovicAGMM();
+      ~DPZivkovicAGMM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(DPZivkovicAGMM);
+  }
+}
+
+#endif
diff --git a/src/algorithms/FrameDifference.cpp b/src/algorithms/FrameDifference.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..197aac48e4af9fd7cd7359e64767cf0c895e0bdf
--- /dev/null
+++ b/src/algorithms/FrameDifference.cpp
@@ -0,0 +1,57 @@
+#include "FrameDifference.h"
+
+using namespace bgslibrary::algorithms;
+
+FrameDifference::FrameDifference() :
+  IBGS(quote(FrameDifference)),
+  enableThreshold(true), threshold(15)
+{
+  debug_construction(FrameDifference);
+  initLoadSaveConfig(algorithmName);
+}
+
+FrameDifference::~FrameDifference() {
+  debug_destruction(FrameDifference);
+}
+
+void FrameDifference::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (img_background.empty()) {
+    img_input.copyTo(img_background);
+    return;
+  }
+
+  cv::absdiff(img_background, img_input, img_foreground);
+
+  if (img_foreground.channels() == 3)
+    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
+
+  if (enableThreshold)
+    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+
+  img_input.copyTo(img_background);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void FrameDifference::save_config(cv::FileStorage &fs) {
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void FrameDifference::load_config(cv::FileStorage &fs) {
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/FrameDifference.h b/src/algorithms/FrameDifference.h
new file mode 100644
index 0000000000000000000000000000000000000000..b877313cb0b4018bfc8af4e26aab7632491d9443
--- /dev/null
+++ b/src/algorithms/FrameDifference.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class FrameDifference : public IBGS
+    {
+    private:
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      FrameDifference();
+      ~FrameDifference();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(FrameDifference);
+  }
+}
diff --git a/package_bgs/FuzzyChoquetIntegral.cpp b/src/algorithms/FuzzyChoquetIntegral.cpp
similarity index 62%
rename from package_bgs/FuzzyChoquetIntegral.cpp
rename to src/algorithms/FuzzyChoquetIntegral.cpp
index 3d24126b4a089ddb7b026786146529876637c1e5..2145eaea6e428bb556289a7e1f16800a97ce09f8 100644
--- a/package_bgs/FuzzyChoquetIntegral.cpp
+++ b/src/algorithms/FuzzyChoquetIntegral.cpp
@@ -1,34 +1,21 @@
-/*
-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 "FuzzyChoquetIntegral.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 using namespace bgslibrary::algorithms;
 
 FuzzyChoquetIntegral::FuzzyChoquetIntegral() :
-  frameNumber(0), framesToLearn(10), alphaLearn(0.1), alphaUpdate(0.01),
-  colorSpace(1), option(2), smooth(true), threshold(0.67)
+  IBGS(quote(FuzzyChoquetIntegral)),
+  frameNumber(0), framesToLearn(10), alphaLearn(0.1),
+  alphaUpdate(0.01), colorSpace(1), option(2),
+  smooth(true), threshold(0.67)
 {
-  std::cout << "FuzzyChoquetIntegral()" << std::endl;
-  setup("./config/FuzzyChoquetIntegral.xml");
+  debug_construction(FuzzyChoquetIntegral);
+  initLoadSaveConfig(algorithmName);
 }
 
-FuzzyChoquetIntegral::~FuzzyChoquetIntegral()
-{
-  std::cout << "~FuzzyChoquetIntegral()" << std::endl;
+FuzzyChoquetIntegral::~FuzzyChoquetIntegral() {
+  debug_destruction(FuzzyChoquetIntegral);
 }
 
 void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
@@ -38,9 +25,8 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
   cv::Mat img_input_f3(img_input.size(), CV_32F);
   img_input.convertTo(img_input_f3, CV_32F, 1. / 255.);
 
-  if (firstTime)
-  {
-    std::cout << "FuzzyChoquetIntegral parameters:" << std::endl;
+  if (firstTime) {
+    std::cout << algorithmName + " parameters:" << std::endl;
 
     std::string colorSpaceName = "";
     switch (colorSpace)
@@ -58,10 +44,9 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
       std::cout << "Fuzzing by 2 color components + 1 texture component" << std::endl;
   }
 
-  if (frameNumber <= framesToLearn)
-  {
+  if (frameNumber <= framesToLearn) {
     if (frameNumber == 0)
-      std::cout << "FuzzyChoquetIntegral initializing background model by adaptive learning..." << std::endl;
+      std::cout << algorithmName + " initializing background model by adaptive learning" << std::endl;
 
     if (img_background_f3.empty())
       img_input_f3.copyTo(img_background_f3);
@@ -77,7 +62,7 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
 
 #ifndef MEX_COMPILE_FLAG
     if (showOutput)
-      cv::imshow("CI BG Model", img_background);
+      cv::imshow(algorithmName + "_BG", img_background);
 #endif
   }
   else
@@ -88,10 +73,24 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
     cv::Mat img_background_f1;
     cv::cvtColor(img_background_f3, img_background_f1, CV_BGR2GRAY);
 
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+    IplImage _input_f3 = cvIplImage(img_input_f3);
+    IplImage* input_f3 = &_input_f3;
+
+    IplImage _input_f1 = cvIplImage(img_input_f1);
+    IplImage* input_f1 = &_input_f1;
+
+    IplImage _background_f3 = cvIplImage(img_background_f3);
+    IplImage* background_f3 = &_background_f3;
+
+    IplImage _background_f1 = cvIplImage(img_background_f1);
+    IplImage* background_f1 = &_background_f1;
+#else
     IplImage* input_f3 = new IplImage(img_input_f3);
     IplImage* input_f1 = new IplImage(img_input_f1);
     IplImage* background_f3 = new IplImage(img_background_f3);
     IplImage* background_f1 = new IplImage(img_background_f1);
+#endif
 
     IplImage* lbp_input_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1);
     cvSetZero(lbp_input_f1);
@@ -111,15 +110,13 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
     IplImage* integral_choquet_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1);
 
     // 3 color components
-    if (option == 1)
-    {
+    if (option == 1) {
       fu.FuzzyMeasureG(0.4f, 0.3f, 0.3f, measureG);
       fu.getFuzzyIntegralChoquet(sim_texture_f1, sim_color_f3, option, measureG, integral_choquet_f1);
     }
 
     // 2 color components + 1 texture component
-    if (option == 2)
-    {
+    if (option == 2) {
       fu.FuzzyMeasureG(0.6f, 0.3f, 0.1f, measureG);
       fu.getFuzzyIntegralChoquet(sim_texture_f1, sim_color_f3, option, measureG, integral_choquet_f1);
     }
@@ -144,19 +141,17 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
     img_background.copyTo(img_bgmodel);
 
 #ifndef MEX_COMPILE_FLAG
-    if (showOutput)
-    {
-      cvShowImage("CI LBP Input", lbp_input_f1);
-      cvShowImage("CI LBP Background", lbp_background_f1);
-      cvShowImage("CI Prob FG Mask", integral_choquet_f1);
-
-      cv::imshow("CI BG Model", img_background);
-      cv::imshow("CI FG Mask", img_foreground);
+    if (showOutput) {
+      cv::imshow(algorithmName + "_LBP_IN", cv::cvarrToMat(lbp_input_f1));
+      cv::imshow(algorithmName + "_LBP_BG", cv::cvarrToMat(lbp_background_f1));
+      cv::imshow(algorithmName + "_FG_PROB", cv::cvarrToMat(integral_choquet_f1));
+      cv::imshow(algorithmName + "_BG", img_background);
+      cv::imshow(algorithmName + "_FG", img_foreground);
     }
 #endif
 
     if (frameNumber == (framesToLearn + 1))
-      std::cout << "FuzzyChoquetIntegral updating background model by adaptive-selective learning..." << std::endl;
+      std::cout << algorithmName + " updating background model by adaptive-selective learning" << std::endl;
 
     IplImage* updated_background_f3 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 3);
     cvSetZero(updated_background_f3);
@@ -181,34 +176,26 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output
   frameNumber++;
 }
 
-void FuzzyChoquetIntegral::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-  cvWriteInt(fs, "framesToLearn", framesToLearn);
-  cvWriteReal(fs, "alphaLearn", alphaLearn);
-  cvWriteReal(fs, "alphaUpdate", alphaUpdate);
-  cvWriteInt(fs, "colorSpace", colorSpace);
-  cvWriteInt(fs, "option", option);
-  cvWriteInt(fs, "smooth", smooth);
-  cvWriteReal(fs, "threshold", threshold);
-
-  cvReleaseFileStorage(&fs);
+void FuzzyChoquetIntegral::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "framesToLearn" << framesToLearn;
+  fs << "alphaLearn" << alphaLearn;
+  fs << "alphaUpdate" << alphaUpdate;
+  fs << "colorSpace" << colorSpace;
+  fs << "option" << option;
+  fs << "smooth" << smooth;
+  fs << "showOutput" << showOutput;
 }
 
-void FuzzyChoquetIntegral::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-  framesToLearn = cvReadIntByName(fs, nullptr, "framesToLearn", 10);
-  alphaLearn = cvReadRealByName(fs, nullptr, "alphaLearn", 0.1);
-  alphaUpdate = cvReadRealByName(fs, nullptr, "alphaUpdate", 0.01);
-  colorSpace = cvReadIntByName(fs, nullptr, "colorSpace", 1);
-  option = cvReadIntByName(fs, nullptr, "option", 2);
-  smooth = cvReadIntByName(fs, nullptr, "smooth", true);
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 0.67);
-
-  cvReleaseFileStorage(&fs);
+void FuzzyChoquetIntegral::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["framesToLearn"] >> framesToLearn;
+  fs["alphaLearn"] >> alphaLearn;
+  fs["alphaUpdate"] >> alphaUpdate;
+  fs["colorSpace"] >> colorSpace;
+  fs["option"] >> option;
+  fs["smooth"] >> smooth;
+  fs["showOutput"] >> showOutput;
 }
+
+#endif
diff --git a/src/algorithms/FuzzyChoquetIntegral.h b/src/algorithms/FuzzyChoquetIntegral.h
new file mode 100644
index 0000000000000000000000000000000000000000..992f65148b61a15579b020a3f69aa6679920a3e0
--- /dev/null
+++ b/src/algorithms/FuzzyChoquetIntegral.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "../tools/FuzzyUtils.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class FuzzyChoquetIntegral : public IBGS
+    {
+    public:
+      FuzzyChoquetIntegral();
+      ~FuzzyChoquetIntegral();
+
+      typedef bgslibrary::tools::FuzzyUtils FuzzyUtils;
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      long frameNumber;
+      int framesToLearn;
+      double alphaLearn;
+      double alphaUpdate;
+      int colorSpace;
+      int option;
+      bool smooth;
+      double threshold;
+      FuzzyUtils fu;
+      cv::Mat img_background_f3;
+      
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(FuzzyChoquetIntegral);
+  }
+}
+
+#endif
diff --git a/package_bgs/FuzzySugenoIntegral.cpp b/src/algorithms/FuzzySugenoIntegral.cpp
similarity index 64%
rename from package_bgs/FuzzySugenoIntegral.cpp
rename to src/algorithms/FuzzySugenoIntegral.cpp
index e62fa029637af565142fdd70ae857e180f553ae6..1c70dc4cda71c2ee0a08bef880e500b0643f893f 100644
--- a/package_bgs/FuzzySugenoIntegral.cpp
+++ b/src/algorithms/FuzzySugenoIntegral.cpp
@@ -1,34 +1,20 @@
-/*
-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 "FuzzySugenoIntegral.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 using namespace bgslibrary::algorithms;
 
 FuzzySugenoIntegral::FuzzySugenoIntegral() :
+  IBGS(quote(FuzzySugenoIntegral)),
   frameNumber(0), framesToLearn(10), alphaLearn(0.1), alphaUpdate(0.01),
   colorSpace(1), option(2), smooth(true), threshold(0.67)
 {
-  std::cout << "FuzzySugenoIntegral()" << std::endl;
-  setup("./config/FuzzySugenoIntegral.xml");
+  debug_construction(FuzzySugenoIntegral);
+  initLoadSaveConfig(algorithmName);
 }
 
-FuzzySugenoIntegral::~FuzzySugenoIntegral()
-{
-  std::cout << "~FuzzySugenoIntegral()" << std::endl;
+FuzzySugenoIntegral::~FuzzySugenoIntegral() {
+  debug_destruction(FuzzySugenoIntegral);
 }
 
 void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
@@ -38,9 +24,8 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
   cv::Mat img_input_f3(img_input.size(), CV_32F);
   img_input.convertTo(img_input_f3, CV_32F, 1. / 255.);
 
-  if (firstTime)
-  {
-    std::cout << "FuzzySugenoIntegral parameters:" << std::endl;
+  if (firstTime) {
+    std::cout << algorithmName + " parameters:" << std::endl;
 
     std::string colorSpaceName = "";
     switch (colorSpace)
@@ -58,10 +43,9 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
       std::cout << "Fuzzing by 2 color components + 1 texture component" << std::endl;
   }
 
-  if (frameNumber <= framesToLearn)
-  {
+  if (frameNumber <= framesToLearn) {
     if (frameNumber == 0)
-      std::cout << "FuzzySugenoIntegral initializing background model by adaptive learning..." << std::endl;
+      std::cout << algorithmName + " initializing background model by adaptive learning" << std::endl;
 
     if (img_background_f3.empty())
       img_input_f3.copyTo(img_background_f3);
@@ -77,7 +61,7 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
 
 #ifndef MEX_COMPILE_FLAG
     if (showOutput)
-      cv::imshow("SI BG Model", img_background);
+      cv::imshow(algorithmName + "_BG", img_background);
 #endif
   }
   else
@@ -88,10 +72,24 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
     cv::Mat img_background_f1;
     cv::cvtColor(img_background_f3, img_background_f1, CV_BGR2GRAY);
 
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+    IplImage _input_f3 = cvIplImage(img_input_f3);
+    IplImage* input_f3 = &_input_f3;
+
+    IplImage _input_f1 = cvIplImage(img_input_f1);
+    IplImage* input_f1 = &_input_f1;
+
+    IplImage _background_f3 = cvIplImage(img_background_f3);
+    IplImage* background_f3 = &_background_f3;
+
+    IplImage _background_f1 = cvIplImage(img_background_f1);
+    IplImage* background_f1 = &_background_f1;
+#else
     IplImage* input_f3 = new IplImage(img_input_f3);
     IplImage* input_f1 = new IplImage(img_input_f1);
     IplImage* background_f3 = new IplImage(img_background_f3);
     IplImage* background_f1 = new IplImage(img_background_f1);
+#endif
 
     IplImage* lbp_input_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1);
     cvSetZero(lbp_input_f1);
@@ -111,15 +109,13 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
     IplImage* integral_sugeno_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1);
 
     // 3 color components
-    if (option == 1)
-    {
+    if (option == 1) {
       fu.FuzzyMeasureG(0.4f, 0.3f, 0.3f, measureG);
       fu.getFuzzyIntegralSugeno(sim_texture_f1, sim_color_f3, option, measureG, integral_sugeno_f1);
     }
 
     // 2 color components + 1 texture component
-    if (option == 2)
-    {
+    if (option == 2) {
       fu.FuzzyMeasureG(0.6f, 0.3f, 0.1f, measureG);
       fu.getFuzzyIntegralSugeno(sim_texture_f1, sim_color_f3, option, measureG, integral_sugeno_f1);
     }
@@ -144,19 +140,17 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
     img_background.copyTo(img_bgmodel);
 
 #ifndef MEX_COMPILE_FLAG
-    if (showOutput)
-    {
-      cvShowImage("SI LBP Input", lbp_input_f1);
-      cvShowImage("SI LBP Background", lbp_background_f1);
-      cvShowImage("SI Prob FG Mask", integral_sugeno_f1);
-
-      cv::imshow("SI BG Model", img_background);
-      cv::imshow("SI FG Mask", img_foreground);
+    if (showOutput) {
+      cv::imshow(algorithmName + "_LBP_IN", cv::cvarrToMat(lbp_input_f1));
+      cv::imshow(algorithmName + "_LBP_BG", cv::cvarrToMat(lbp_background_f1));
+      cv::imshow(algorithmName + "_FG_PROB", cv::cvarrToMat(integral_sugeno_f1));
+      cv::imshow(algorithmName + "_BG", img_background);
+      cv::imshow(algorithmName + "_FG", img_foreground);
     }
 #endif
 
     if (frameNumber == (framesToLearn + 1))
-      std::cout << "FuzzySugenoIntegral updating background model by adaptive-selective learning..." << std::endl;
+      std::cout << algorithmName + " updating background model by adaptive-selective learning" << std::endl;
 
     IplImage* updated_background_f3 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 3);
     cvSetZero(updated_background_f3);
@@ -181,34 +175,26 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output,
   frameNumber++;
 }
 
-void FuzzySugenoIntegral::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-  cvWriteInt(fs, "framesToLearn", framesToLearn);
-  cvWriteReal(fs, "alphaLearn", alphaLearn);
-  cvWriteReal(fs, "alphaUpdate", alphaUpdate);
-  cvWriteInt(fs, "colorSpace", colorSpace);
-  cvWriteInt(fs, "option", option);
-  cvWriteInt(fs, "smooth", smooth);
-  cvWriteReal(fs, "threshold", threshold);
-
-  cvReleaseFileStorage(&fs);
+void FuzzySugenoIntegral::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "framesToLearn" << framesToLearn;
+  fs << "alphaLearn" << alphaLearn;
+  fs << "alphaUpdate" << alphaUpdate;
+  fs << "colorSpace" << colorSpace;
+  fs << "option" << option;
+  fs << "smooth" << smooth;
+  fs << "showOutput" << showOutput;
 }
 
-void FuzzySugenoIntegral::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-  framesToLearn = cvReadIntByName(fs, nullptr, "framesToLearn", 10);
-  alphaLearn = cvReadRealByName(fs, nullptr, "alphaLearn", 0.1);
-  alphaUpdate = cvReadRealByName(fs, nullptr, "alphaUpdate", 0.01);
-  colorSpace = cvReadIntByName(fs, nullptr, "colorSpace", 1);
-  option = cvReadIntByName(fs, nullptr, "option", 2);
-  smooth = cvReadIntByName(fs, nullptr, "smooth", true);
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 0.67);
-
-  cvReleaseFileStorage(&fs);
+void FuzzySugenoIntegral::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["framesToLearn"] >> framesToLearn;
+  fs["alphaLearn"] >> alphaLearn;
+  fs["alphaUpdate"] >> alphaUpdate;
+  fs["colorSpace"] >> colorSpace;
+  fs["option"] >> option;
+  fs["smooth"] >> smooth;
+  fs["showOutput"] >> showOutput;
 }
+
+#endif
diff --git a/src/algorithms/FuzzySugenoIntegral.h b/src/algorithms/FuzzySugenoIntegral.h
new file mode 100644
index 0000000000000000000000000000000000000000..fefd11be42bcea2e44d7045971d1ec155d1c3827
--- /dev/null
+++ b/src/algorithms/FuzzySugenoIntegral.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "../tools/FuzzyUtils.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class FuzzySugenoIntegral : public IBGS
+    {
+    public:
+      FuzzySugenoIntegral();
+      ~FuzzySugenoIntegral();
+
+      typedef bgslibrary::tools::FuzzyUtils FuzzyUtils;
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      long frameNumber;
+      int framesToLearn;
+      double alphaLearn;
+      double alphaUpdate;
+      int colorSpace;
+      int option;
+      bool smooth;
+      double threshold;
+      cv::Mat img_background_f3;
+      FuzzyUtils fu;
+
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(FuzzySugenoIntegral);
+  }
+}
+
+#endif
diff --git a/src/algorithms/GMG.cpp b/src/algorithms/GMG.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6abe1f40adcf5b6f1979cd43c212d688f7a0d103
--- /dev/null
+++ b/src/algorithms/GMG.cpp
@@ -0,0 +1,70 @@
+#include "GMG.h"
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+
+using namespace bgslibrary::algorithms;
+
+GMG::GMG() : 
+  IBGS(quote(GMG)),
+  initializationFrames(20), decisionThreshold(0.7)
+{
+  debug_construction(GMG);
+  initLoadSaveConfig(algorithmName);
+
+  cv::initModule_video();
+  cv::setUseOptimized(true);
+  cv::setNumThreads(4);
+
+  fgbg = cv::Algorithm::create<cv::BackgroundSubtractorGMG>("BackgroundSubtractor.GMG");
+}
+
+GMG::~GMG() {
+  debug_destruction(GMG);
+}
+
+void GMG::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    fgbg->set("initializationFrames", initializationFrames);
+    fgbg->set("decisionThreshold", decisionThreshold);
+  }
+
+  if (fgbg.empty()) {
+    std::cerr << "Failed to create " + algorithmName << std::endl;
+    return;
+  }
+
+  (*fgbg)(img_input, img_foreground);
+  (*fgbg).getBackgroundImage(img_background);
+
+  img_input.copyTo(img_segmentation);
+  cv::add(img_input, cv::Scalar(100, 100, 0), img_segmentation, img_foreground);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void GMG::save_config(cv::FileStorage &fs) {
+  fs << "initializationFrames" << initializationFrames;
+  fs << "decisionThreshold" << decisionThreshold;
+  fs << "showOutput" << showOutput;
+}
+
+void GMG::load_config(cv::FileStorage &fs) {
+  fs["initializationFrames"] >> initializationFrames;
+  fs["decisionThreshold"] >> decisionThreshold;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/GMG.h b/src/algorithms/GMG.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5edd6b9393e4622265e3299c110e9405a3e2668
--- /dev/null
+++ b/src/algorithms/GMG.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class GMG : public IBGS
+    {
+    private:
+      cv::Ptr<cv::BackgroundSubtractorGMG> fgbg;
+      int initializationFrames;
+      double decisionThreshold;
+      cv::Mat img_segmentation;
+
+    public:
+      GMG();
+      ~GMG();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(GMG);
+  }
+}
+
+#endif
diff --git a/src/algorithms/IBGS.h b/src/algorithms/IBGS.h
new file mode 100644
index 0000000000000000000000000000000000000000..d92b5df2b61b5eb6b7a953cfd3e861efac31887d
--- /dev/null
+++ b/src/algorithms/IBGS.h
@@ -0,0 +1,158 @@
+#pragma once
+
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <memory>
+#include <string>
+#include <functional>
+#include <map>
+
+#include <opencv2/opencv.hpp>
+
+// opencv legacy includes
+#include <opencv2/imgproc/types_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui_c.h>
+#endif
+
+#include "../utils/ILoadSaveConfig.h"
+
+#ifndef CV_RGB && CV_MAJOR_VERSION > 3
+#define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
+#endif
+
+#if !defined(bgs_register)
+#define bgs_register(x) static BGS_Register<x> register_##x(quote(x))
+#endif
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class IBGS : public ILoadSaveConfig
+    {
+    private:
+      friend std::ostream& operator<<(std::ostream& o, const std::shared_ptr<IBGS>& ibgs) {
+        return ibgs.get()->dump(o);
+      }
+      friend std::ostream& operator<<(std::ostream& o, const IBGS *ibgs) {
+        return ibgs->dump(o);
+      }
+      friend std::string to_string(const std::shared_ptr<IBGS>& ibgs) {
+        std::ostringstream ss;
+        ss << ibgs;
+        return ss.str();
+      }
+    public:
+      virtual std::ostream& dump(std::ostream& o) const {
+        return o << getAlgorithmName();
+      }
+      std::string getAlgorithmName() const {
+        return algorithmName;
+      }
+      void setShowOutput(const bool _showOutput) {
+        showOutput = _showOutput;
+      }
+      cv::Mat apply(const cv::Mat &img_input) {
+        setShowOutput(false);
+        cv::Mat _img_foreground;
+        cv::Mat _img_background;
+        process(img_input, _img_foreground, _img_background);
+                _img_background.copyTo(img_background);
+        return _img_foreground;
+      }
+      cv::Mat getBackgroundModel() {
+        return img_background;
+      }
+      IBGS(const std::string _algorithmName){
+        //debug_construction(IBGS);
+        algorithmName = _algorithmName;
+      }
+      IBGS(){
+        //debug_construction(IBGS);
+        algorithmName = "";
+      }
+      virtual ~IBGS() {
+        //debug_destruction(IBGS);
+      }
+      virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground, cv::Mat &img_background) = 0;
+    protected:
+      std::string algorithmName;
+      bool firstTime = true;
+      bool showOutput = true;
+      cv::Mat img_background;
+      cv::Mat img_foreground;
+      void init(const cv::Mat &img_input, cv::Mat &img_outfg, cv::Mat &img_outbg) {
+        assert(img_input.empty() == false);
+        //img_outfg = cv::Mat::zeros(img_input.size(), img_input.type());
+        //img_outbg = cv::Mat::zeros(img_input.size(), img_input.type());
+        img_outfg = cv::Mat::zeros(img_input.size(), CV_8UC1);
+        img_outbg = cv::Mat::zeros(img_input.size(), CV_8UC3);
+      }
+    };
+    
+    class BGS_Factory
+    {
+    public:
+      BGS_Factory() {
+        //debug_construction(BGS_Factory);
+      }
+      virtual ~BGS_Factory() {
+        //debug_destruction(BGS_Factory);
+      }
+      static BGS_Factory* Instance() {
+        static BGS_Factory factory;
+        return &factory;
+      }
+
+      std::shared_ptr<IBGS> Create(std::string name) {
+        IBGS* instance = nullptr;
+
+        // find name in the registry and call factory method.
+        auto it = factoryFunctionRegistry.find(name);
+        if (it != factoryFunctionRegistry.end())
+          instance = it->second();
+
+        // wrap instance in a shared ptr and return
+        if (instance != nullptr)
+          return std::shared_ptr<IBGS>(instance);
+        else
+          return nullptr;
+      }
+
+      std::vector<std::string> GetRegisteredAlgorithmsName() {
+        std::vector<std::string> algorithmsName;
+        for (auto it = factoryFunctionRegistry.begin(); it != factoryFunctionRegistry.end(); ++it) {
+          algorithmsName.push_back(it->first);
+        }
+        return algorithmsName;
+      }
+
+      void RegisterFactoryFunction(std::string name,
+        std::function<IBGS*(void)> classFactoryFunction) {
+        // register the class factory function
+        factoryFunctionRegistry[name] = classFactoryFunction;
+      }
+      
+    private:
+      std::map<std::string, std::function<IBGS*(void)>> factoryFunctionRegistry;
+    };
+
+    template<class T>
+    class BGS_Register
+    {
+    public:
+      BGS_Register(const std::string className) {
+        //debug_construction(BGS_Register);
+        // register the class factory function
+        BGS_Factory::Instance()->RegisterFactoryFunction(className,
+          [](void) -> IBGS* { return new T(); });
+      }
+      virtual ~BGS_Register() {
+        //debug_destruction(BGS_Register);
+      }
+    };
+  }
+}
diff --git a/package_bgs/IMBS/IMBS.cpp b/src/algorithms/IMBS/IMBS.cpp
similarity index 92%
rename from package_bgs/IMBS/IMBS.cpp
rename to src/algorithms/IMBS/IMBS.cpp
index b1e177b3e806a7e3a4302e9b370494d5b6d9d40a..bab74da8deb60b83f84b49a64d6869c085ca45c5 100644
--- a/package_bgs/IMBS/IMBS.cpp
+++ b/src/algorithms/IMBS/IMBS.cpp
@@ -1,42 +1,6 @@
-/*
-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/>.
-*/
-/*
-*  IMBS Background Subtraction Library
-*
-*  This file imbs.hpp contains the C++ OpenCV based implementation for
-*  IMBS algorithm described in
-*  D. D. Bloisi and L. Iocchi
-*  "Independent Multimodal Background Subtraction"
-*  In Proc. of the Third Int. Conf. on Computational Modeling of Objects
-*  Presented in Images: Fundamentals, Methods and Applications, pp. 39-44, 2012.
-*  Please, cite the above paper if you use IMBS.
-*
-*  This software is provided without any warranty about its usability.
-*  It is for educational purposes and should be regarded as such.
-*
-*  Written by Domenico D. Bloisi
-*
-*  Please, report suggestions/comments/bugs to
-*  domenico.bloisi@gmail.com
-*
-*/
-
 #include "IMBS.hpp"
 
+using namespace bgslibrary::algorithms::imbs;
 using namespace std;
 using namespace cv;
 
@@ -53,6 +17,10 @@ BackgroundSubtractorIMBS::BackgroundSubtractorIMBS()
   tau_s = 60;
   tau_h = 40;
   minArea = 30.;
+  nframes = 0;
+  bgBins = NULL;
+  bgModel = NULL;
+  persistenceMap = NULL;
   persistencePeriod = samplingPeriod*numSamples / 3.;//ms
 
   initial_tick_count = (double)getTickCount();
@@ -94,6 +62,10 @@ BackgroundSubtractorIMBS::BackgroundSubtractorIMBS(
   this->tau_s = tau_s;
   this->tau_h = tau_h;
   this->minArea = minArea;
+  nframes = 0;
+  bgBins = NULL;
+  bgModel = NULL;
+  persistenceMap = NULL;
 
   if (fps == 0.)
     initial_tick_count = (double)getTickCount();
@@ -165,15 +137,8 @@ void BackgroundSubtractorIMBS::initialize(Size frameSize, int frameType)
 
   for (unsigned int p = 0; p < numPixels; ++p)
   {
-    bgBins[p].binValues = new Vec3b[numSamples];
-    bgBins[p].binHeights = new uchar[numSamples];
-    bgBins[p].isFg = new bool[numSamples];
-
-    bgModel[p].values = new Vec3b[maxBgBins];
-    bgModel[p].isValid = new bool[maxBgBins];
-    bgModel[p].isValid[0] = false;
-    bgModel[p].isFg = new bool[maxBgBins];
-    bgModel[p].counter = new uchar[maxBgBins];
+    bgBins[p].initialize(numSamples);
+    bgModel[p].initialize(maxBgBins);
   }
 }
 
@@ -183,6 +148,8 @@ void BackgroundSubtractorIMBS::apply(InputArray _frame, OutputArray _fgmask, dou
 
   CV_Assert(frame.depth() == CV_8U);
   CV_Assert(frame.channels() == 3);
+  CV_Assert(frame.size().width > 0);
+  CV_Assert(frame.size().height > 0);
 
   bool needToInitialize = nframes == 0 || frame.type() != frameType;
   if (needToInitialize) {
@@ -739,7 +706,7 @@ void BackgroundSubtractorIMBS::changeBg() {
   }
 }
 
-void BackgroundSubtractorIMBS::getBgModel(BgModel bgModel_copy[], int size) {
+void BackgroundSubtractorIMBS::getBgModel(BgModel bgModel_copy[], unsigned int size) {
   if (size != numPixels) {
     return;
   }
diff --git a/src/algorithms/IMBS/IMBS.hpp b/src/algorithms/IMBS/IMBS.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d17f05164b88d36148c04cd7a8df77f736d0a8fb
--- /dev/null
+++ b/src/algorithms/IMBS/IMBS.hpp
@@ -0,0 +1,186 @@
+#pragma once
+
+#include <iostream>
+#include <vector>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/features2d/features2d.hpp>
+// opencv legacy includes
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/highgui/highgui_c.h>
+#endif
+#include <opencv2/imgproc/types_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace imbs
+    {
+      class BackgroundSubtractorIMBS
+      {
+      public:
+        //! the default constructor
+        BackgroundSubtractorIMBS();
+        //! the full constructor
+        BackgroundSubtractorIMBS(double fps,
+          unsigned int fgThreshold = 15,
+          unsigned int associationThreshold = 5,
+          double samplingPeriod = 500.,
+          unsigned int minBinHeight = 2,
+          unsigned int numSamples = 30,
+          double alpha = 0.65,
+          double beta = 1.15,
+          double tau_s = 60.,
+          double tau_h = 40.,
+          double minArea = 30.,
+          double persistencePeriod = 10000.,
+          bool morphologicalFiltering = false
+        );
+        //! the destructor
+        ~BackgroundSubtractorIMBS();
+        //! the update operator
+        void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = -1.);
+
+        //! computes a background image which shows only the highest bin for each pixel
+        void getBackgroundImage(cv::OutputArray backgroundImage) const;
+
+        //! re-initiaization method
+        void initialize(cv::Size frameSize, int frameType);
+
+      private:
+        //method for creating the background model
+        void createBg(unsigned int bg_sample_number);
+        //method for updating the background model
+        void updateBg();
+        //method for computing the foreground mask
+        void getFg();
+        //method for suppressing shadows and highlights
+        void hsvSuppression();
+        //method for refining foreground mask
+        void filterFg();
+        //method for filtering out blobs smaller than a given area
+        void areaThresholding();
+        //method for getting the current time
+        double getTimestamp();
+        //method for converting from RGB to HSV
+        cv::Mat convertImageRGBtoHSV(const cv::Mat& imageRGB);
+        //method for changing the bg in case of sudden changes
+        void changeBg();
+
+        //current input RGB frame
+        cv::Mat frame;
+        std::vector<cv::Mat> frameBGR;
+        //frame size
+        cv::Size frameSize;
+        //frame type
+        int frameType;
+        //total number of pixels in frame
+        unsigned int numPixels;
+        //current background sample
+        cv::Mat bgSample;
+        std::vector<cv::Mat> bgSampleBGR;
+        //current background image which shows only the highest bin for each pixel
+        //(just for displaying purposes)
+        cv::Mat bgImage;
+        //current foreground mask
+        cv::Mat fgmask;
+        cv::Mat fgfiltered;
+        //number of fps
+        double fps;
+        //time stamp in milliseconds (ms)
+        double timestamp;
+        //previous time stamp in milliseconds (ms)
+        double prev_timestamp;
+        double initial_tick_count;
+        //initial message to be shown until the first bg model is ready
+        cv::Mat initialMsgGray;
+        cv::Mat initialMsgRGB;
+
+        //struct for modeling the background values for a single pixel
+        typedef struct Bins {
+          void initialize(unsigned int numSamples) {
+            binValues = new cv::Vec3b[numSamples];
+            binHeights = new uchar[numSamples];
+            isFg = new bool[numSamples];
+          }
+          ~Bins() {
+            if (binValues)  { delete[] binValues; }
+            if (binHeights) { delete[] binHeights; }
+            if (isFg)       { delete[] isFg; }
+          }
+          cv::Vec3b* binValues;
+          uchar* binHeights;
+          bool* isFg;
+        } Bins;
+        Bins* bgBins;
+
+      public:
+        //struct for modeling the background values for the entire frame
+        typedef struct BgModel {
+          void initialize(unsigned int maxBgBins) {
+            values = new cv::Vec3b[maxBgBins];
+            isValid = new bool[maxBgBins];
+            isValid[0] = false;
+            isFg = new bool[maxBgBins];
+            counter = new uchar[maxBgBins];
+          }
+          ~BgModel() {
+            if (values)  { delete[] values; }
+            if (isValid) { delete[] isValid; }
+            if (isFg)    { delete[] isFg; }
+            if (counter) { delete[] counter; }
+          }
+          cv::Vec3b* values;
+          bool* isValid;
+          bool* isFg;
+          uchar* counter;
+        } BgModel;
+      private:
+        BgModel* bgModel;
+
+        //SHADOW SUPPRESSION PARAMETERS
+        float alpha;
+        float beta;
+        uchar tau_s;
+        uchar tau_h;
+
+        unsigned int minBinHeight;
+        unsigned int numSamples;
+        unsigned int samplingPeriod;
+        unsigned long prev_bg_frame_time;
+        unsigned int bg_frame_counter;
+        unsigned int associationThreshold;
+        unsigned int maxBgBins;
+        unsigned int nframes;
+
+        double minArea;
+        bool bg_reset;
+        unsigned int persistencePeriod;
+        bool prev_area;
+        bool sudden_change;
+        unsigned int fgThreshold;
+        uchar SHADOW_LABEL;
+        uchar PERSISTENCE_LABEL;
+        uchar FOREGROUND_LABEL;
+        //persistence map
+        unsigned int* persistenceMap;
+        cv::Mat persistenceImage;
+
+        bool morphologicalFiltering;
+
+      public:
+        unsigned int getMaxBgBins() {
+          return maxBgBins;
+        }
+        unsigned int getFgThreshold() {
+          return fgThreshold;
+        }
+        void getBgModel(BgModel bgModel_copy[], unsigned int size);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/IndependentMultimodal.cpp b/src/algorithms/IndependentMultimodal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..10d3ccaba2497d565aeec55facdd710bfd14ae3f
--- /dev/null
+++ b/src/algorithms/IndependentMultimodal.cpp
@@ -0,0 +1,53 @@
+#include "IndependentMultimodal.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+IndependentMultimodal::IndependentMultimodal() : 
+  IBGS(quote(IndependentMultimodal)), fps(10)
+{
+  debug_construction(IndependentMultimodal);
+  initLoadSaveConfig(algorithmName);
+  pIMBS = new imbs::BackgroundSubtractorIMBS(fps);
+}
+
+IndependentMultimodal::~IndependentMultimodal() {
+  debug_destruction(IndependentMultimodal);
+  delete pIMBS;
+}
+
+void IndependentMultimodal::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  //get the fgmask and update the background model
+  pIMBS->apply(img_input, img_foreground);
+
+  //get background image
+  pIMBS->getBackgroundImage(img_background);
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  firstTime = false;
+}
+
+void IndependentMultimodal::save_config(cv::FileStorage &fs) {
+  fs << "fps" << fps;
+  fs << "showOutput" << showOutput;
+}
+
+void IndependentMultimodal::load_config(cv::FileStorage &fs) {
+  fs["fps"] >> fps;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/IndependentMultimodal.h b/src/algorithms/IndependentMultimodal.h
new file mode 100644
index 0000000000000000000000000000000000000000..6dc654da5e02dcca98f2121a36090cbbf7bb06a0
--- /dev/null
+++ b/src/algorithms/IndependentMultimodal.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IMBS/IMBS.hpp"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class IndependentMultimodal : public IBGS
+    {
+    private:
+      imbs::BackgroundSubtractorIMBS* pIMBS;
+      int fps;
+
+    public:
+      IndependentMultimodal();
+      ~IndependentMultimodal();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(IndependentMultimodal);
+  }
+}
+
+#endif
diff --git a/src/algorithms/KDE.cpp b/src/algorithms/KDE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac6832a1dcf63dec35f79c8901ca42dbd97c9229
--- /dev/null
+++ b/src/algorithms/KDE.cpp
@@ -0,0 +1,108 @@
+#include "KDE.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+KDE::KDE() :
+  IBGS(quote(KDE)),
+  SequenceLength(50), TimeWindowSize(100), 
+  SDEstimationFlag(1), lUseColorRatiosFlag(1),
+  th(10e-8), alpha(0.3), framesToLearn(10), frameNumber(0)
+{
+  debug_construction(KDE);
+  initLoadSaveConfig(algorithmName);
+  p = new kde::NPBGSubtractor;
+}
+
+KDE::~KDE() {
+  debug_destruction(KDE);
+  delete FGImage;
+  delete p;
+}
+
+void KDE::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    rows = img_input.size().height;
+    cols = img_input.size().width;
+    color_channels = img_input.channels();
+
+    // SequenceLength: number of samples for each pixel.
+    // TimeWindowSize: Time window for sampling. for example in the call above, the bg will sample 50 points out of 100 frames.
+    // this rate will affect how fast the model adapt.
+    // SDEstimationFlag: True means to estimate suitable kernel bandwidth to each pixel, False uses a default value.
+    // lUseColorRatiosFlag: True means use normalized RGB for color (recommended.)
+    p->Intialize(rows, cols, color_channels, SequenceLength, TimeWindowSize, SDEstimationFlag, lUseColorRatiosFlag);
+    // th: 0-1 is the probability threshold for a pixel to be a foregroud. typically make it small as 10e-8. the smaller the value the less false positive and more false negative.
+    // alpha: 0-1, for color. typically set to 0.3. this affect shadow suppression.
+    p->SetThresholds(th, alpha);
+
+    FGImage = new unsigned char[rows*cols];
+    //FilteredFGImage = new unsigned char[rows*cols];
+    FilteredFGImage = 0;
+    DisplayBuffers = 0;
+
+    img_foreground = cv::Mat::zeros(img_input.size(), CV_8UC1);
+    img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+    frameNumber = 0;
+    firstTime = false;
+  }
+
+  // Stores the first N frames to build the background model
+  if (frameNumber < framesToLearn) {
+    p->AddFrame(img_input.data);
+    frameNumber++;
+  }
+  else {
+    // Build the background model with first 10 frames
+    if (frameNumber == framesToLearn) {
+      p->Estimation();
+      frameNumber++;
+    }
+
+    // Now, we can subtract the background
+    ((kde::NPBGSubtractor*)p)->NBBGSubtraction(img_input.data, FGImage, FilteredFGImage, DisplayBuffers);
+
+    // At each frame also you can call the update function to adapt the bg
+    // here you pass a mask where pixels with true value will be masked out of the update.
+    ((kde::NPBGSubtractor*)p)->Update(FGImage);
+
+    img_foreground.data = FGImage;
+  }
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+}
+
+void KDE::save_config(cv::FileStorage &fs) {
+  fs << "framesToLearn" << framesToLearn;
+  fs << "SequenceLength" << SequenceLength;
+  fs << "TimeWindowSize" << TimeWindowSize;
+  fs << "SDEstimationFlag" << SDEstimationFlag;
+  fs << "lUseColorRatiosFlag" << lUseColorRatiosFlag;
+  fs << "th" << th;
+  fs << "alpha" << alpha;
+  fs << "showOutput" << showOutput;
+}
+
+void KDE::load_config(cv::FileStorage &fs) {
+  fs["framesToLearn"] >> framesToLearn;
+  fs["SequenceLength"] >> SequenceLength;
+  fs["TimeWindowSize"] >> TimeWindowSize;
+  fs["SDEstimationFlag"] >> SDEstimationFlag;
+  fs["lUseColorRatiosFlag"] >> lUseColorRatiosFlag;
+  fs["th"] >> th;
+  fs["alpha"] >> alpha;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/KDE.h b/src/algorithms/KDE.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0eee8ab46be6fd7a5acd3536013e8f6da205ca0
--- /dev/null
+++ b/src/algorithms/KDE.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "KDE/NPBGSubtractor.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class KDE : public IBGS
+    {
+    private:
+      kde::NPBGSubtractor *p;
+      int rows;
+      int cols;
+      int color_channels;
+      int SequenceLength;
+      int TimeWindowSize;
+      int SDEstimationFlag;
+      int lUseColorRatiosFlag;
+      double th;
+      double alpha;
+      int framesToLearn;
+      int frameNumber;
+
+      unsigned char *FGImage;
+      unsigned char *FilteredFGImage;
+      unsigned char **DisplayBuffers;
+
+    public:
+      KDE();
+      ~KDE();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(KDE);
+  }
+}
+
+#endif
diff --git a/src/algorithms/KDE/KernelTable.cpp b/src/algorithms/KDE/KernelTable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b796556458185b3aa0dfb2f37201bdc7b31ef92
--- /dev/null
+++ b/src/algorithms/KDE/KernelTable.cpp
@@ -0,0 +1,73 @@
+#include <math.h>
+
+#include "KernelTable.h"
+
+#ifndef PI
+#define PI 3.141592653589793f
+#endif
+
+using namespace bgslibrary::algorithms::kde;
+
+KernelLUTable::KernelLUTable()
+{
+  std::cout << "KernelLUTable()" << std::endl;
+}
+
+KernelLUTable::~KernelLUTable()
+{
+  delete kerneltable;
+  delete kernelsums;
+  std::cout << "~KernelLUTable()" << std::endl;
+}
+
+KernelLUTable::KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmamax, int Segmabins)
+{
+  std::cout << "KernelLUTable()" << std::endl;
+
+  double C1, C2, v, segma, sum;
+  int bin, b;
+
+  minsegma = Segmamin;
+  maxsegma = Segmamax;
+  segmabins = Segmabins;
+  tablehalfwidth = KernelHalfWidth;
+
+  // Generate the Kernel
+
+  // allocate memory for the Kernal Table
+  kerneltable = new double[segmabins*(2 * KernelHalfWidth + 1)];
+  kernelsums = new double[segmabins];
+
+  double segmastep = (maxsegma - minsegma) / segmabins;
+  double y;
+
+  for (segma = minsegma, bin = 0; bin < segmabins; segma += segmastep, bin++)
+  {
+    C1 = 1 / (sqrt(2 * PI)*segma);
+    C2 = -1 / (2 * segma*segma);
+
+    b = (2 * KernelHalfWidth + 1)*bin;
+    sum = 0;
+
+    for (int x = 0; x <= KernelHalfWidth; x++)
+    {
+      y = x / 1.0;
+      v = C1*exp(C2*y*y);
+      kerneltable[b + KernelHalfWidth + x] = v;
+      kerneltable[b + KernelHalfWidth - x] = v;
+      sum += 2 * v;
+    }
+
+    sum -= C1;
+
+    kernelsums[bin] = sum;
+
+    // Normailization
+    for (int x = 0; x <= KernelHalfWidth; x++)
+    {
+      v = kerneltable[b + KernelHalfWidth + x] / sum;
+      kerneltable[b + KernelHalfWidth + x] = v;
+      kerneltable[b + KernelHalfWidth - x] = v;
+    }
+  }
+}
diff --git a/src/algorithms/KDE/KernelTable.h b/src/algorithms/KDE/KernelTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..98d6c67adde1060f74c494b3f2b3b32429835234
--- /dev/null
+++ b/src/algorithms/KDE/KernelTable.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <iostream>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace kde
+    {
+      class KernelLUTable
+      {
+      public:
+        double minsegma;
+        double maxsegma;
+        int segmabins;
+        int tablehalfwidth;
+        double *kerneltable;
+        double *kernelsums;
+
+      public:
+        KernelLUTable();
+        ~KernelLUTable();
+
+        KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmamax, int Segmabins);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/KDE/NPBGSubtractor.cpp b/src/algorithms/KDE/NPBGSubtractor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..812fffcb19147a9a79a88d0e55136b582b56828d
--- /dev/null
+++ b/src/algorithms/KDE/NPBGSubtractor.cpp
@@ -0,0 +1,1119 @@
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+
+#include "NPBGSubtractor.h"
+
+//#ifdef _DEBUG
+//#undef THIS_FILE
+//static char THIS_FILE[]=__FILE__;
+//#define new DEBUG_NEW
+//#endif
+//using namespace bgslibrary::algorithms::kde;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace kde
+    {
+      void BGR2SnGnRn(unsigned char * in_image,
+        unsigned char * out_image,
+        unsigned int rows,
+        unsigned int cols)
+      {
+        unsigned int i;
+        unsigned int r2, r3;
+        unsigned int r, g, b;
+        double s;
+
+        for (i = 0; i < rows*cols * 3; i += 3)
+        {
+          b = in_image[i];
+          g = in_image[i + 1];
+          r = in_image[i + 2];
+
+          // calculate color ratios
+          s = (double)255 / (double)(b + g + r + 30);
+
+          r2 = (unsigned int)((g + 10) * s);
+          r3 = (unsigned int)((r + 10) * s);
+
+          out_image[i] = (unsigned char)(((unsigned int)b + g + r) / 3);
+          out_image[i + 1] = (unsigned char)(r2 > 255 ? 255 : r2);
+          out_image[i + 2] = (unsigned char)(r3 > 255 ? 255 : r3);
+        }
+      }
+
+      void UpdateDiffHist(unsigned char * image1, unsigned char * image2, DynamicMedianHistogram * pHist)
+      {
+        unsigned int j;
+        int bin, diff;
+
+        unsigned int  imagesize = pHist->imagesize;
+        unsigned char histbins = pHist->histbins;
+        unsigned char *pAbsDiffHist = pHist->Hist;
+
+        int histbins_1 = histbins - 1;
+
+        for (j = 0; j < imagesize; j++)
+        {
+          diff = (int)image1[j] - (int)image2[j];
+          diff = abs(diff);
+          // update histogram
+          bin = (diff < histbins ? diff : histbins_1);
+          pAbsDiffHist[j*histbins + bin]++;
+        }
+      }
+
+      void FindHistMedians(DynamicMedianHistogram * pAbsDiffHist)
+      {
+        unsigned char * Hist = pAbsDiffHist->Hist;
+        unsigned char * MedianBins = pAbsDiffHist->MedianBins;
+        unsigned char * AccSum = pAbsDiffHist->AccSum;
+        unsigned char histsum = pAbsDiffHist->histsum;
+        unsigned char histbins = pAbsDiffHist->histbins;
+        unsigned int imagesize = pAbsDiffHist->imagesize;
+
+        int sum;
+        int bin;
+        unsigned int histindex;
+        unsigned char medianCount = histsum / 2;
+        unsigned int j;
+
+        // find medians
+        for (j = 0; j < imagesize; j++)
+        {
+          // find the median
+          bin = 0;
+          sum = 0;
+
+          histindex = j*histbins;
+
+          while (sum < medianCount)
+          {
+            sum += Hist[histindex + bin];
+            bin++;
+          }
+
+          bin--;
+
+          MedianBins[j] = bin;
+          AccSum[j] = sum;
+        }
+      }
+
+      DynamicMedianHistogram BuildAbsDiffHist(unsigned char * pSequence,
+        unsigned int rows,
+        unsigned int cols,
+        unsigned int color_channels,
+        unsigned int SequenceLength,
+        unsigned int histbins)
+      {
+
+        unsigned int imagesize = rows*cols*color_channels;
+        unsigned int i;
+
+        DynamicMedianHistogram Hist;
+
+        unsigned char *pAbsDiffHist = new unsigned char[rows*cols*color_channels*histbins];
+        unsigned char *pMedianBins = new unsigned char[rows*cols*color_channels];
+        unsigned char *pMedianFreq = new unsigned char[rows*cols*color_channels];
+        unsigned char *pAccSum = new unsigned char[rows*cols*color_channels];
+
+        memset(pAbsDiffHist, 0, rows*cols*color_channels*histbins);
+
+        Hist.Hist = pAbsDiffHist;
+        Hist.MedianBins = pMedianBins;
+        Hist.MedianFreq = pMedianFreq;
+        Hist.AccSum = pAccSum;
+        Hist.histbins = histbins;
+        Hist.imagesize = rows*cols*color_channels;
+        Hist.histsum = SequenceLength - 1;
+
+        unsigned char *image1, *image2;
+        for (i = 1; i < SequenceLength; i++)
+        {
+          // find diff between frame i,i-1;
+          image1 = pSequence + (i - 1)*imagesize;
+          image2 = pSequence + (i)*imagesize;
+
+          UpdateDiffHist(image1, image2, &Hist);
+        }
+
+        FindHistMedians(&Hist);
+
+        return Hist;
+      }
+
+      void EstimateSDsFromAbsDiffHist(DynamicMedianHistogram * pAbsDiffHist,
+        unsigned char * pSDs,
+        unsigned int imagesize,
+        double MinSD,
+        double MaxSD,
+        unsigned int kernelbins)
+      {
+        double v;
+        double kernelbinfactor = (kernelbins - 1) / (MaxSD - MinSD);
+        int medianCount;
+        int sum;
+        int bin;
+        unsigned int histindex;
+        unsigned int j;
+        unsigned int x1, x2;
+
+        unsigned char *Hist = pAbsDiffHist->Hist;
+        unsigned char *MedianBins = pAbsDiffHist->MedianBins;
+        unsigned char *AccSum = pAbsDiffHist->AccSum;
+        unsigned char histsum = pAbsDiffHist->histsum;
+        unsigned char histbins = pAbsDiffHist->histbins;
+
+        medianCount = (histsum) / 2;
+
+        for (j = 0; j < imagesize; j++)
+        {
+          histindex = j*histbins;
+
+          bin = MedianBins[j];
+          sum = AccSum[j];
+
+          x1 = sum - Hist[histindex + bin];
+          x2 = sum;
+
+          // interpolate to get the median
+          // x1 < 50 % < x2
+
+          v = 1.04 * ((double)bin - (double)(x2 - medianCount) / (double)(x2 - x1));
+          v = (v <= MinSD ? MinSD : v);
+
+          // convert sd to kernel table bin
+
+          bin = (int)(v >= MaxSD ? kernelbins - 1 : floor((v - MinSD)*kernelbinfactor + .5));
+
+          assert(bin >= 0 && bin < kernelbins);
+
+          pSDs[j] = bin;
+        }
+      }
+
+      //////////////////////////////////////////////////////////////////////
+      // Construction/Destruction
+      //////////////////////////////////////////////////////////////////////
+
+      NPBGSubtractor::NPBGSubtractor() {}
+
+      NPBGSubtractor::~NPBGSubtractor()
+      {
+        delete AbsDiffHist.Hist;
+        delete AbsDiffHist.MedianBins;
+        delete AbsDiffHist.MedianFreq;
+        delete AbsDiffHist.AccSum;
+        delete KernelTable;
+        delete BGModel->SDbinsImage;
+        delete BGModel;
+        delete Pimage1;
+        delete Pimage2;
+        delete tempFrame;
+        delete imageindex->List;
+        delete imageindex;
+      }
+
+      int NPBGSubtractor::Intialize(unsigned int prows,
+        unsigned int pcols,
+        unsigned int pcolor_channels,
+        unsigned int SequenceLength,
+        unsigned int pTimeWindowSize,
+        unsigned char pSDEstimationFlag,
+        unsigned char pUseColorRatiosFlag)
+      {
+
+        rows = prows;
+        cols = pcols;
+        color_channels = pcolor_channels;
+        imagesize = rows*cols*color_channels;
+        SdEstimateFlag = pSDEstimationFlag;
+        UseColorRatiosFlag = pUseColorRatiosFlag;
+        //SampleSize = SequenceLength;
+
+        AdaptBGFlag = FALSE;
+        //
+        SubsetFlag = TRUE;
+
+        UpdateSDRate = 0;
+
+        BGModel = new NPBGmodel(rows, cols, color_channels, SequenceLength, pTimeWindowSize, 500);
+
+        Pimage1 = new double[rows*cols];
+        Pimage2 = new double[rows*cols];
+
+        tempFrame = new unsigned char[rows*cols * 3];
+
+        imageindex = new ImageIndex;
+        imageindex->List = new unsigned int[rows*cols];
+
+        // error checking
+        if (BGModel == NULL)
+          return 0;
+
+        return 1;
+      }
+
+      void NPBGSubtractor::AddFrame(unsigned char *ImageBuffer)
+      {
+        if (UseColorRatiosFlag && color_channels == 3)
+          BGR2SnGnRn(ImageBuffer, ImageBuffer, rows, cols);
+
+        BGModel->AddFrame(ImageBuffer);
+      }
+
+      void NPBGSubtractor::Estimation()
+      {
+        int SampleSize = BGModel->SampleSize;
+
+        memset(BGModel->TemporalMask, 0, rows*cols*BGModel->TemporalBufferLength);
+
+        //BGModel->AccMask= new unsigned int [rows*cols];
+        memset(BGModel->AccMask, 0, rows*cols * sizeof(unsigned int));
+
+        unsigned char *pSDs = new unsigned char[rows*cols*color_channels];
+
+        //DynamicMedianHistogram AbsDiffHist;
+
+        int Abshistbins = 20;
+
+        TimeIndex = 0;
+
+        // estimate standard deviations
+
+        if (SdEstimateFlag)
+        {
+          AbsDiffHist = BuildAbsDiffHist(BGModel->Sequence, rows, cols, color_channels, SampleSize, Abshistbins);
+          EstimateSDsFromAbsDiffHist(&AbsDiffHist, pSDs, imagesize, SEGMAMIN, SEGMAMAX, SEGMABINS);
+        }
+        else
+        {
+          unsigned int bin;
+          bin = (unsigned int)floor(((DEFAULTSEGMA - SEGMAMIN)*SEGMABINS) / (SEGMAMAX - SEGMAMIN));
+          memset(pSDs, bin, rows*cols*color_channels * sizeof(unsigned char));
+        }
+
+        BGModel->SDbinsImage = pSDs;
+
+        // Generate the Kernel
+        KernelTable = new KernelLUTable(KERNELHALFWIDTH, SEGMAMIN, SEGMAMAX, SEGMABINS);
+      }
+
+      /*********************************************************************/
+
+      void BuildImageIndex(unsigned char * Image,
+        ImageIndex * imageIndex,
+        unsigned int rows,
+        unsigned int cols)
+      {
+        unsigned int i, j;
+        unsigned int r, c;
+        unsigned int * image_list;
+
+        j = cols + 1;
+        i = 0;
+        image_list = imageIndex->List;
+
+        for (r = 1; r < rows - 1; r++)
+        {
+          for (c = 1; c < cols - 1; c++)
+          {
+            if (Image[j])
+              image_list[i++] = j;
+
+            j++;
+          }
+          j += 2;
+        }
+
+        imageIndex->cnt = i;
+      }
+
+      /*********************************************************************/
+
+      void HystExpandOperatorIndexed(unsigned char * inImage,
+        ImageIndex * inIndex,
+        double * Pimage,
+        double hyst_th,
+        unsigned char * outImage,
+        ImageIndex * outIndex,
+        unsigned int urows,
+        unsigned int ucols)
+      {
+        unsigned int * in_list;
+        unsigned int in_cnt;
+        unsigned int * out_list;
+
+        int rows, cols;
+
+        int Nbr[9];
+        unsigned int i, j;
+        unsigned int k;
+        unsigned int idx;
+
+        rows = (int)urows;
+        cols = (int)ucols;
+
+        in_cnt = inIndex->cnt;
+        in_list = inIndex->List;
+
+        Nbr[0] = -cols - 1;
+        Nbr[1] = -cols;
+        Nbr[2] = -cols + 1;
+        Nbr[3] = -1;
+        Nbr[4] = 0;
+        Nbr[5] = 1;
+        Nbr[6] = cols - 1;
+        Nbr[7] = cols;
+        Nbr[8] = cols + 1;
+
+        memset(outImage, 0, rows*cols);
+
+        out_list = outIndex->List;
+        k = 0;
+
+        for (i = 0; i < in_cnt; i++)
+        {
+          for (j = 0; j < 9; j++)
+          {
+            idx = in_list[i] + Nbr[j];
+
+            if (Pimage[idx] < hyst_th)
+              outImage[idx] = 255;
+          }
+        }
+
+        // build index for out image
+        BuildImageIndex(outImage, outIndex, urows, ucols);
+      }
+
+      /*********************************************************************/
+
+      void HystShrinkOperatorIndexed(unsigned char * inImage,
+        ImageIndex * inIndex,
+        double * Pimage,
+        double hyst_th,
+        unsigned char * outImage,
+        ImageIndex * outIndex,
+        unsigned int urows,
+        unsigned int ucols)
+      {
+        unsigned int * in_list;
+        unsigned int in_cnt;
+        unsigned int * out_list;
+
+        int rows, cols;
+
+        int Nbr[9];
+        unsigned int i, j;
+        unsigned int k, idx;
+
+        rows = (int)urows;
+        cols = (int)ucols;
+
+        in_cnt = inIndex->cnt;
+        in_list = inIndex->List;
+
+        Nbr[0] = -cols - 1;
+        Nbr[1] = -cols;
+        Nbr[2] = -cols + 1;
+        Nbr[3] = -1;
+        Nbr[4] = 0;
+        Nbr[5] = 1;
+        Nbr[6] = cols - 1;
+        Nbr[7] = cols;
+        Nbr[8] = cols + 1;
+
+        memset(outImage, 0, rows*cols);
+
+        out_list = outIndex->List;
+        k = 0;
+
+        for (i = 0; i < in_cnt; i++)
+        {
+          idx = in_list[i];
+          j = 0;
+
+          while (j < 9 && inImage[idx + Nbr[j]])
+            j++;
+
+          if (j >= 9 || Pimage[idx] <= hyst_th)
+            outImage[idx] = 255;
+        }
+
+        BuildImageIndex(outImage, outIndex, rows, cols);
+      }
+
+      /*********************************************************************/
+
+      void ExpandOperatorIndexed(unsigned char * inImage,
+        ImageIndex * inIndex,
+        unsigned char * outImage,
+        ImageIndex * outIndex,
+        unsigned int urows,
+        unsigned int ucols)
+      {
+        unsigned int * in_list;
+        unsigned int in_cnt;
+        unsigned int * out_list;
+
+        int rows, cols;
+
+        int Nbr[9];
+        unsigned int i, j;
+        unsigned int k;
+        unsigned int idx;
+
+        rows = (int)urows;
+        cols = (int)ucols;
+
+        in_cnt = inIndex->cnt;
+        in_list = inIndex->List;
+
+        Nbr[0] = -cols - 1;
+        Nbr[1] = -cols;
+        Nbr[2] = -cols + 1;
+        Nbr[3] = -1;
+        Nbr[4] = 0;
+        Nbr[5] = 1;
+        Nbr[6] = cols - 1;
+        Nbr[7] = cols;
+        Nbr[8] = cols + 1;
+
+
+        memset(outImage, 0, rows*cols);
+
+
+        out_list = outIndex->List;
+        k = 0;
+        for (i = 0; i < in_cnt; i++)
+          for (j = 0; j < 9; j++) {
+            idx = in_list[i] + Nbr[j];
+            outImage[idx] = 255;
+          }
+
+
+        // build index for out image
+
+        BuildImageIndex(outImage, outIndex, rows, cols);
+
+      }
+
+      /*********************************************************************/
+
+      void ShrinkOperatorIndexed(unsigned char * inImage,
+        ImageIndex * inIndex,
+        unsigned char * outImage,
+        ImageIndex * outIndex,
+        unsigned int urows,
+        unsigned int ucols)
+      {
+
+        unsigned int * in_list;
+        unsigned int in_cnt;
+        unsigned int * out_list;
+
+        int rows, cols;
+
+        int Nbr[9];
+        unsigned int i, j;
+        unsigned int k, idx;
+
+        rows = (int)urows;
+        cols = (int)ucols;
+
+        in_cnt = inIndex->cnt;
+        in_list = inIndex->List;
+
+        Nbr[0] = -cols - 1;
+        Nbr[1] = -cols;
+        Nbr[2] = -cols + 1;
+        Nbr[3] = -1;
+        Nbr[4] = 0;
+        Nbr[5] = 1;
+        Nbr[6] = cols - 1;
+        Nbr[7] = cols;
+        Nbr[8] = cols + 1;
+
+
+        memset(outImage, 0, rows*cols);
+
+        out_list = outIndex->List;
+        k = 0;
+        for (i = 0; i < in_cnt; i++) {
+          idx = in_list[i];
+          j = 0;
+
+          while (j < 9 && inImage[idx + Nbr[j]]) {
+            j++;
+          }
+
+          if (j >= 9) {
+            outImage[idx] = 255;
+          }
+        }
+
+        BuildImageIndex(outImage, outIndex, rows, cols);
+      }
+
+      /*********************************************************************/
+
+      void NoiseFilter_o(unsigned char * Image,
+        unsigned char * ResultIm,
+        int rows,
+        int cols,
+        unsigned char th)
+      {
+        /* assuming input is 1 for on, 0 for off */
+
+
+        int r, c;
+        unsigned char *p, *n, *nw, *ne, *e, *w, *s, *sw, *se;
+        unsigned int v;
+        unsigned int TH;
+
+        unsigned char * ResultPtr;
+
+        TH = 255 * th;
+
+        memset(ResultIm, 0, rows*cols);
+
+        p = Image + cols + 1;
+        ResultPtr = ResultIm + cols + 1;
+
+        for (r = 1; r < rows - 1; r++)
+        {
+          for (c = 1; c < cols - 1; c++)
+          {
+            if (*p)
+            {
+              n = p - cols;
+              ne = n + 1;
+              nw = n - 1;
+              e = p + 1;
+              w = p - 1;
+              s = p + cols;
+              se = s + 1;
+              sw = s - 1;
+
+              v = (unsigned int)*nw + *n + *ne + *w + *e + *sw + *s + *se;
+
+              if (v >= TH)
+                *ResultPtr = 255;
+              else
+                *ResultPtr = 0;
+            }
+            p++;
+            ResultPtr++;
+          }
+          p += 2;
+          ResultPtr += 2;
+        }
+      }
+
+      /*********************************************************************/
+
+      void NPBGSubtractor::SequenceBGUpdate_Pairs(unsigned char * image,
+        unsigned char * Mask)
+      {
+        unsigned int i, ic;
+        unsigned char * pSequence = BGModel->Sequence;
+        unsigned char * PixelQTop = BGModel->PixelQTop;
+        //unsigned int Top = BGModel->Top;
+        unsigned int rate;
+
+        int TemporalBufferTop = (int)BGModel->TemporalBufferTop;
+        unsigned char * pTemporalBuffer = BGModel->TemporalBuffer;
+        unsigned char * pTemporalMask = BGModel->TemporalMask;
+        int TemporalBufferLength = BGModel->TemporalBufferLength;
+
+        unsigned int * AccMask = BGModel->AccMask;
+        unsigned int ResetMaskTh = BGModel->ResetMaskTh;
+
+        unsigned char *pAbsDiffHist = AbsDiffHist.Hist;
+        unsigned char histbins = AbsDiffHist.histbins;
+        int histbins_1 = histbins - 1;
+
+        int TimeWindowSize = BGModel->TimeWindowSize;
+        int SampleSize = BGModel->SampleSize;
+
+        int TemporalBufferNext;
+
+        unsigned int imagebuffersize = rows*cols*color_channels;
+        unsigned int imagespatialsize = rows*cols;
+
+        unsigned char mask;
+
+        unsigned int histindex;
+        unsigned char diff;
+        unsigned char bin;
+
+        static int TBCount = 0;
+
+        unsigned char * pTBbase1, *pTBbase2;
+        unsigned char * pModelbase1, *pModelbase2;
+
+        rate = TimeWindowSize / SampleSize;
+        rate = (rate > 2) ? rate : 2;
+
+
+        TemporalBufferNext = (TemporalBufferTop + 1)
+          % TemporalBufferLength;
+
+        // pointers to Masks : Top and Next
+        unsigned char * pTMaskTop = pTemporalMask + TemporalBufferTop*imagespatialsize;
+        unsigned char * pTMaskNext = pTemporalMask + TemporalBufferNext*imagespatialsize;
+
+        // pointers to TB frames: Top and Next
+        unsigned char * pTBTop = pTemporalBuffer + TemporalBufferTop*imagebuffersize;
+        unsigned char * pTBNext = pTemporalBuffer + TemporalBufferNext*imagebuffersize;
+
+        if (((TimeIndex) % rate == 0) && TBCount >= TemporalBufferLength)
+        {
+          for (i = 0, ic = 0; i < imagespatialsize; i++, ic += color_channels)
+          {
+            mask = *(pTMaskTop + i) || *(pTMaskNext + i);
+
+            if (!mask)
+            {
+              // pointer to TB pixels to be added to the model
+              pTBbase1 = pTBTop + ic;
+              pTBbase2 = pTBNext + ic;
+
+              // pointers to Model pixels to be replaced
+              pModelbase1 = pSequence + PixelQTop[i] * imagebuffersize + ic;
+              pModelbase2 = pSequence + ((PixelQTop[i] + 1) % SampleSize)*imagebuffersize + ic;
+
+              // update Deviation Histogram
+              if (SdEstimateFlag)
+              {
+                if (color_channels == 1)
+                {
+                  histindex = i*histbins;
+
+                  // add new pair from temporal buffer
+                  diff = (unsigned char)abs((int)*pTBbase1 - (int)*pTBbase2);
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]++;
+
+
+                  // remove old pair from the model
+                  diff = (unsigned char)abs((int)*pModelbase1 - (int)*pModelbase2);
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]--;
+                }
+                else
+                {
+                  // color
+
+                  // add new pair from temporal buffer
+                  histindex = ic*histbins;
+                  diff = abs(*pTBbase1 -
+                    *pTBbase2);
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]++;
+
+                  histindex += histbins;
+                  diff = abs(*(pTBbase1 + 1) -
+                    *(pTBbase2 + 1));
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]++;
+
+                  histindex += histbins;
+                  diff = abs(*(pTBbase1 + 2) -
+                    *(pTBbase2 + 2));
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]++;
+
+                  // remove old pair from the model
+                  histindex = ic*histbins;
+
+                  diff = abs(*pModelbase1 -
+                    *pModelbase2);
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]--;
+
+                  histindex += histbins;
+                  diff = abs(*(pModelbase1 + 1) -
+                    *(pModelbase2 + 1));
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]--;
+
+                  histindex += histbins;
+                  diff = abs(*(pModelbase1 + 2) -
+                    *(pModelbase2 + 2));
+                  bin = (diff < histbins ? diff : histbins_1);
+                  pAbsDiffHist[histindex + bin]--;
+                }
+              }
+
+              // add new pair into the model
+              memcpy(pModelbase1, pTBbase1, color_channels * sizeof(unsigned char));
+
+              memcpy(pModelbase2, pTBbase2, color_channels * sizeof(unsigned char));
+
+              PixelQTop[i] = (PixelQTop[i] + 2) % SampleSize;
+            }
+          }
+        } // end if (sampling event)
+
+        // update temporal buffer
+        // add new frame to Temporal buffer.
+        memcpy(pTBTop, image, imagebuffersize);
+
+        // update AccMask
+        // update new Mask with information in AccMask
+
+        for (i = 0; i < rows*cols; i++)
+        {
+          if (Mask[i])
+            AccMask[i]++;
+          else
+            AccMask[i] = 0;
+
+          if (AccMask[i] > ResetMaskTh)
+            Mask[i] = 0;
+        }
+
+        // add new mask
+        memcpy(pTMaskTop, Mask, imagespatialsize);
+
+        // advance Temporal buffer pointer
+        TemporalBufferTop = (TemporalBufferTop + 1) % TemporalBufferLength;
+
+        BGModel->TemporalBufferTop = TemporalBufferTop;
+
+        TBCount++;
+
+        // estimate SDs
+
+        if (SdEstimateFlag && UpdateSDRate && ((TimeIndex) % UpdateSDRate == 0))
+        {
+          double MaxSD = KernelTable->maxsegma;
+          double MinSD = KernelTable->minsegma;
+          int KernelBins = KernelTable->segmabins;
+
+          unsigned char * pSDs = BGModel->SDbinsImage;
+
+          FindHistMedians(&(AbsDiffHist));
+          EstimateSDsFromAbsDiffHist(&(AbsDiffHist), pSDs, imagebuffersize, MinSD, MaxSD, KernelBins);
+        }
+
+        TimeIndex++;
+      }
+
+      /*********************************************************************/
+
+      void DisplayPropabilityImageWithThresholding(double * Pimage,
+        unsigned char * DisplayImage,
+        double Threshold,
+        unsigned int rows,
+        unsigned int cols)
+      {
+        double p;
+
+        for (unsigned int i = 0; i < rows*cols; i++)
+        {
+          p = Pimage[i];
+
+          DisplayImage[i] = (p > Threshold) ? 0 : 255;
+        }
+      }
+
+      /*********************************************************************/
+
+      void NPBGSubtractor::NPBGSubtraction_Subset_Kernel(
+        unsigned char * image,
+        unsigned char * FGImage,
+        unsigned char * FilteredFGImage)
+      {
+        unsigned int i, j;
+        unsigned char *pSequence = BGModel->Sequence;
+
+        unsigned int SampleSize = BGModel->SampleSize;
+
+        double *kerneltable = KernelTable->kerneltable;
+        int KernelHalfWidth = KernelTable->tablehalfwidth;
+        //double *KernelSum = KernelTable->kernelsums;
+        double KernelMaxSigma = KernelTable->maxsegma;
+        double KernelMinSigma = KernelTable->minsegma;
+        int KernelBins = KernelTable->segmabins;
+        unsigned char * SDbins = BGModel->SDbinsImage;
+
+        //unsigned char * SaturationImage = FilteredFGImage;
+
+        // default sigmas .. to be removed.
+        double sigma1;
+        double sigma2;
+        double sigma3;
+
+        sigma1 = 2.25;
+        sigma2 = 2.25;
+        sigma3 = 2.25;
+
+        double p;
+        double th;
+
+        double alpha;
+
+        alpha = AlphaValue;
+
+        /* intialize FG image */
+
+        memset(FGImage, 0, rows*cols);
+
+        //Threshold=1;
+        th = Threshold * SampleSize;
+
+        double sum = 0, kernel1, kernel2, kernel3;
+        int k, g;
+
+
+        if (color_channels == 1)
+        {
+          // gray scale
+
+          int kernelbase;
+
+          for (i = 0; i < rows*cols; i++)
+          {
+            kernelbase = SDbins[i] * (2 * KernelHalfWidth + 1);
+            sum = 0;
+            j = 0;
+
+            while (j < SampleSize && sum < th)
+            {
+              g = pSequence[j*imagesize + i];
+              k = g - image[i] + KernelHalfWidth;
+              sum += kerneltable[kernelbase + k];
+              j++;
+            }
+
+            p = sum / j;
+            Pimage1[i] = p;
+          }
+        }
+        else if (UseColorRatiosFlag && SubsetFlag)
+        {
+          // color ratios
+
+          unsigned int ig;
+          int base;
+
+          int kernelbase1;
+          int kernelbase2;
+          int kernelbase3;
+
+          unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
+
+          double beta = 3.0;    // minimum bound on the range.
+          double betau = 100.0;
+
+          double beta_over_alpha = beta / alpha;
+          double betau_over_alpha = betau / alpha;
+
+
+          double brightness_lowerbound = 1 - alpha;
+          double brightness_upperbound = 1 + alpha;
+          int x1, x2;
+          unsigned int SubsampleCount;
+
+          for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
+          {
+            kernelbase1 = SDbins[i] * kerneltablewidth;
+            kernelbase2 = SDbins[i + 1] * kerneltablewidth;
+            kernelbase3 = SDbins[i + 2] * kerneltablewidth;
+
+            sum = 0;
+            j = 0;
+            SubsampleCount = 0;
+
+            while (j < SampleSize && sum < th)
+            {
+              base = j*imagesize + i;
+              g = pSequence[base];
+
+              if (g < beta_over_alpha)
+              {
+                x1 = (int)(g - beta);
+                x2 = (int)(g + beta);
+              }
+              else if (g > betau_over_alpha)
+              {
+                x1 = (int)(g - betau);
+                x2 = (int)(g + betau);
+              }
+              else
+              {
+                x1 = (int)(g*brightness_lowerbound + 0.5);
+                x2 = (int)(g*brightness_upperbound + 0.5);
+              }
+
+              if (x1 < image[i] && image[i] < x2)
+              {
+                g = pSequence[base + 1];
+                k = (g - image[i + 1]) + KernelHalfWidth;
+                kernel2 = kerneltable[kernelbase2 + k];
+
+                g = pSequence[base + 2];
+                k = (g - image[i + 2]) + KernelHalfWidth;
+                kernel3 = kerneltable[kernelbase3 + k];
+
+                sum += kernel2*kernel3;
+
+                SubsampleCount++;
+              }
+              j++;
+            }
+
+            p = sum / j;
+            Pimage1[ig] = p;
+          }
+        }
+        else if (UseColorRatiosFlag && !SubsetFlag)
+        {
+          // color ratios
+
+          unsigned int ig;
+          int base;
+          int bin;
+
+          int kernelbase1;
+          int kernelbase2;
+          int kernelbase3;
+
+          unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
+
+          int gmin, gmax;
+          double gfactor;
+
+          gmax = 200;
+          gmin = 10;
+
+          gfactor = (KernelMaxSigma - KernelMinSigma) / (double)(gmax - gmin);
+
+          for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
+          {
+
+            bin = (int)floor(((alpha * 16 - KernelMinSigma)*KernelBins) / (KernelMaxSigma - KernelMinSigma));
+
+            kernelbase1 = bin*kerneltablewidth;
+            kernelbase2 = SDbins[i + 1] * kerneltablewidth;
+            kernelbase3 = SDbins[i + 2] * kerneltablewidth;
+
+            sum = 0;
+            j = 0;
+
+            while (j < SampleSize && sum < th)
+            {
+              base = j*imagesize + i;
+              g = pSequence[base];
+
+              if (g < gmin)
+                bin = 0;
+              else if (g > gmax)
+                bin = KernelBins - 1;
+              else
+                bin = (int)((g - gmin) * gfactor + 0.5);
+
+              kernelbase1 = bin*kerneltablewidth;
+
+              k = (g - image[i]) + KernelHalfWidth;
+              kernel1 = kerneltable[kernelbase1 + k];
+
+              g = pSequence[base + 1];
+              k = (g - image[i + 1]) + KernelHalfWidth;
+              kernel2 = kerneltable[kernelbase2 + k];
+
+              g = pSequence[base + 2];
+              k = (g - image[i + 2]) + KernelHalfWidth;
+              kernel3 = kerneltable[kernelbase3 + k];
+
+              sum += kernel1*kernel2*kernel3;
+              j++;
+            }
+
+            p = sum / j;
+            Pimage1[ig] = p;
+          }
+        }
+        else // RGB color
+        {
+          unsigned int ig;
+          int base;
+
+          int kernelbase1;
+          int kernelbase2;
+          int kernelbase3;
+          unsigned int kerneltablewidth = 2 * KernelHalfWidth + 1;
+
+          for (i = 0, ig = 0; i < imagesize; i += 3, ig++)
+          {
+            // used extimated kernel width to access the right kernel
+            kernelbase1 = SDbins[i] * kerneltablewidth;
+            kernelbase2 = SDbins[i + 1] * kerneltablewidth;
+            kernelbase3 = SDbins[i + 2] * kerneltablewidth;
+
+            sum = 0;
+            j = 0;
+            while (j < SampleSize && sum < th)
+            {
+              base = j*imagesize + i;
+              g = pSequence[base];
+              k = (g - image[i]) + KernelHalfWidth;
+              kernel1 = kerneltable[kernelbase1 + k];
+
+              g = pSequence[base + 1];
+              k = (g - image[i + 1]) + KernelHalfWidth;
+              kernel2 = kerneltable[kernelbase2 + k];
+
+              g = pSequence[base + 2];
+              k = (g - image[i + 2]) + KernelHalfWidth;
+              kernel3 = kerneltable[kernelbase3 + k];
+
+              sum += kernel1*kernel2*kernel3;
+              j++;
+            }
+
+            p = sum / j;
+            Pimage1[ig] = p;
+          }
+        }
+
+        DisplayPropabilityImageWithThresholding(Pimage1, FGImage, Threshold, rows, cols);
+      }
+
+      /*********************************************************************/
+
+      void NPBGSubtractor::NBBGSubtraction(unsigned char * Frame,
+        unsigned char * FGImage,
+        unsigned char * FilteredFGImage,
+        unsigned char ** DisplayBuffers)
+      {
+        if (UseColorRatiosFlag)
+          BGR2SnGnRn(Frame, tempFrame, rows, cols);
+        else
+          memcpy(tempFrame, Frame, rows*cols*color_channels);
+
+        NPBGSubtraction_Subset_Kernel(tempFrame, FGImage, FilteredFGImage);
+        /*NoiseFilter_o(FGImage,DisplayBuffers[3],rows,cols,4);
+        BuildImageIndex(DisplayBuffers[3],imageindex,rows,cols);
+
+        ExpandOperatorIndexed(DisplayBuffers[3],imageindex,DisplayBuffers[4],imageindex,rows,cols);
+        ShrinkOperatorIndexed(DisplayBuffers[4],imageindex,FilteredFGImage,imageindex,rows,cols);
+
+        memset(DisplayBuffers[3],0,rows*cols);*/
+      }
+
+      void NPBGSubtractor::Update(unsigned char * FGMask)
+      {
+        if (UpdateBGFlag)
+          SequenceBGUpdate_Pairs(tempFrame, FGMask);
+      }
+    }
+  }
+}
diff --git a/src/algorithms/KDE/NPBGSubtractor.h b/src/algorithms/KDE/NPBGSubtractor.h
new file mode 100644
index 0000000000000000000000000000000000000000..837fc85cb36a4aaa353ee9396ccfa6404e73ec5f
--- /dev/null
+++ b/src/algorithms/KDE/NPBGSubtractor.h
@@ -0,0 +1,104 @@
+#pragma once
+
+#include "NPBGmodel.h"
+#include "KernelTable.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace kde
+    {
+      const int FALSE = 0;
+      const int TRUE = 1;
+
+      // kernal look up table settings
+      const int KERNELHALFWIDTH = 255;
+      const float SEGMAMAX = 36.5;
+      const float SEGMAMIN = 0.5;
+      const int SEGMABINS = 80;
+      const float DEFAULTSEGMA = 1.0;
+
+      typedef struct
+      {
+        unsigned char *Hist;
+        unsigned char *MedianBins;
+        unsigned char *MedianFreq;
+        unsigned char *AccSum;
+        unsigned char histbins;
+        unsigned char histsum;
+        unsigned int  imagesize;
+      } DynamicMedianHistogram;
+
+      typedef struct
+      {
+        unsigned int cnt;
+        unsigned int *List;
+      } ImageIndex;
+
+      class NPBGSubtractor
+      {
+      private:
+        unsigned int rows;
+        unsigned int cols;
+        unsigned int color_channels;
+        unsigned int imagesize;
+        // flags
+        unsigned char UpdateBGFlag;
+        unsigned char SdEstimateFlag;
+        unsigned char UseColorRatiosFlag;
+        unsigned char AdaptBGFlag;
+        unsigned char SubsetFlag;
+        //
+        int UpdateSDRate;
+        double Threshold;
+        double AlphaValue;
+        unsigned int TimeIndex;
+        ImageIndex  *imageindex;
+        unsigned char *tempFrame;
+        KernelLUTable *KernelTable;
+        NPBGmodel *BGModel;
+        DynamicMedianHistogram AbsDiffHist;
+        double *Pimage1;
+        double *Pimage2;
+        //
+        void NPBGSubtraction_Subset_Kernel(unsigned char * image, unsigned char * FGImage, unsigned char * FilteredFGImage);
+        void SequenceBGUpdate_Pairs(unsigned char * image, unsigned char * Mask);
+
+      public:
+        NPBGSubtractor();
+        virtual ~NPBGSubtractor();
+        //~NPBGSubtractor();
+
+        int Intialize(unsigned int rows,
+          unsigned int cols,
+          unsigned int color_channels,
+          unsigned int SequenceLength,
+          unsigned int TimeWindowSize,
+          unsigned char SDEstimationFlag,
+          unsigned char UseColorRatiosFlag);
+
+        void AddFrame(unsigned char * ImageBuffer);
+
+        void Estimation();
+
+        void NBBGSubtraction(unsigned char *Frame,
+          unsigned char *FGImage,
+          unsigned char *FilteredFGImage,
+          unsigned char **DisplayBuffers);
+
+        void Update(unsigned char *);
+
+        void SetThresholds(double th, double alpha)
+        {
+          Threshold = th;
+          AlphaValue = alpha;
+        };
+
+        void SetUpdateFlag(unsigned int bgflag) {
+          UpdateBGFlag = bgflag;
+        };
+      };
+    }
+  }
+}
diff --git a/src/algorithms/KDE/NPBGmodel.cpp b/src/algorithms/KDE/NPBGmodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4e5b3cc9a37850d6c72bcd0dc575ab60caa8118a
--- /dev/null
+++ b/src/algorithms/KDE/NPBGmodel.cpp
@@ -0,0 +1,67 @@
+#include "memory.h"
+
+#include "NPBGmodel.h"
+
+//#ifdef _DEBUG
+//#undef THIS_FILE
+//static char THIS_FILE[] = __FILE__;
+////#define new DEBUG_NEW
+//#endif
+
+using namespace bgslibrary::algorithms::kde;
+
+NPBGmodel::NPBGmodel() {}
+
+NPBGmodel::~NPBGmodel() {
+  delete Sequence;
+  delete PixelQTop;
+  delete TemporalBuffer;
+  delete TemporalMask;
+  delete AccMask;
+  //delete SDbinsImage;
+}
+
+NPBGmodel::NPBGmodel(unsigned int Rows,
+  unsigned int Cols,
+  unsigned int ColorChannels,
+  unsigned int Length,
+  unsigned int pTimeWindowSize,
+  unsigned int bg_suppression_time)
+{
+  imagesize = Rows*Cols*ColorChannels;
+
+  rows = Rows;
+  cols = Cols;
+  color_channels = ColorChannels;
+
+  SampleSize = Length;
+
+  TimeWindowSize = pTimeWindowSize;
+
+  Sequence = new unsigned char[imagesize*Length];
+  Top = 0;
+  memset(Sequence, 0, imagesize*Length);
+
+  PixelQTop = new unsigned char[rows*cols];
+
+  // temporalBuffer
+  TemporalBufferLength = (TimeWindowSize / Length > 2 ? TimeWindowSize / Length : 2);
+  TemporalBuffer = new unsigned char[imagesize*TemporalBufferLength];
+  TemporalMask = new unsigned char[rows*cols*TemporalBufferLength];
+
+  TemporalBufferTop = 0;
+
+  AccMask = new unsigned int[rows*cols];
+
+  ResetMaskTh = bg_suppression_time;
+}
+
+void NPBGmodel::AddFrame(unsigned char *ImageBuffer)
+{
+  memcpy(Sequence + Top*imagesize, ImageBuffer, imagesize);
+  Top = (Top + 1) % SampleSize;
+
+  memset(PixelQTop, (unsigned char)Top, rows*cols);
+
+  memcpy(TemporalBuffer, ImageBuffer, imagesize);
+}
diff --git a/src/algorithms/KDE/NPBGmodel.h b/src/algorithms/KDE/NPBGmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..02a1f731b83e19adaa714c546fda6dc6e62655c5
--- /dev/null
+++ b/src/algorithms/KDE/NPBGmodel.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <iostream>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace kde
+    {
+      class NPBGmodel
+      {
+      private:
+        unsigned char *Sequence;
+        unsigned int SampleSize;
+        unsigned int TimeWindowSize;
+
+        unsigned int rows, cols, color_channels;
+        unsigned int imagesize;
+
+        unsigned int Top;
+        unsigned char *PixelQTop;
+
+        //unsigned int *PixelUpdateCounter;
+
+        unsigned char *SDbinsImage;
+
+        unsigned char *TemporalBuffer;
+        unsigned char TemporalBufferLength;
+        unsigned char TemporalBufferTop;
+        unsigned char *TemporalBufferMask;
+
+        unsigned char *TemporalMask;
+        unsigned char TemporalMaskLength;
+        unsigned char TemporalMaskTop;
+
+        unsigned int *AccMask;
+        unsigned int ResetMaskTh;	// Max continous duration a pixel can be detected before
+        // it is forced to be updated...
+
+        double *weights;
+
+      public:
+        NPBGmodel();
+        //~NPBGmodel();
+        virtual ~NPBGmodel();
+
+        NPBGmodel(unsigned int Rows,
+          unsigned int Cols,
+          unsigned int ColorChannels,
+          unsigned int Length,
+          unsigned int pTimeWindowSize,
+          unsigned int bg_suppression_time);
+
+        void AddFrame(unsigned char *ImageBuffer);
+
+        friend class NPBGSubtractor;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/KNN.cpp b/src/algorithms/KNN.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..332709498a65d80b7beba13e0d93999ae8d55459
--- /dev/null
+++ b/src/algorithms/KNN.cpp
@@ -0,0 +1,85 @@
+#include "KNN.h"
+
+#if CV_MAJOR_VERSION >= 3
+
+using namespace bgslibrary::algorithms;
+
+KNN::KNN() :
+  IBGS(quote(KNN)),
+  history(500), nSamples(7), dist2Threshold(20.0f * 20.0f),
+  knnSamples(0), doShadowDetection(true), shadowValue(127),
+  shadowThreshold(0.5f)
+{
+  debug_construction(KNN);
+  initLoadSaveConfig(algorithmName);
+}
+
+KNN::~KNN() {
+  debug_destruction(KNN);
+}
+
+void KNN::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  //------------------------------------------------------------------
+  // BackgroundSubtractorKNN
+  // http://docs.opencv.org/trunk/modules/video/doc/motion_analysis_and_object_tracking.html#backgroundsubtractorknn
+  //
+  //  The class implements the K nearest neigbours algorithm from:
+  //  "Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction"
+  //  Z.Zivkovic, F. van der Heijden
+  //  Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006
+  //  http:  //www.zoranz.net/Publications/zivkovicPRL2006.pdf
+  //
+  //  Fast for small foreground object. Results on the benchmark data is at http://www.changedetection.net.
+  //------------------------------------------------------------------
+
+  int prevNSamples = nSamples;
+  if (firstTime)
+    knn = cv::createBackgroundSubtractorKNN(history, dist2Threshold, doShadowDetection);
+
+  knn->setNSamples(nSamples);
+  knn->setkNNSamples(knnSamples);
+  knn->setShadowValue(shadowValue);
+  knn->setShadowThreshold(shadowThreshold);
+
+  knn->apply(img_input, img_foreground, prevNSamples != nSamples ? 0.f : 1.f);
+  knn->getBackgroundImage(img_background);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void KNN::save_config(cv::FileStorage &fs) {
+  fs << "history" << history;
+  fs << "nSamples" << nSamples;
+  fs << "dist2Threshold" << dist2Threshold;
+  fs << "knnSamples" << knnSamples;
+  fs << "doShadowDetection" << doShadowDetection;
+  fs << "shadowValue" << shadowValue;
+  fs << "shadowThreshold" << shadowThreshold;
+  fs << "showOutput" << showOutput;
+}
+
+void KNN::load_config(cv::FileStorage &fs) {
+  fs["history"] >> history;
+  fs["nSamples"] >> nSamples;
+  fs["dist2Threshold"] >> dist2Threshold;
+  fs["knnSamples"] >> knnSamples;
+  fs["doShadowDetection"] >> doShadowDetection;
+  fs["shadowValue"] >> shadowValue;
+  fs["shadowThreshold"] >> shadowThreshold;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/KNN.h b/src/algorithms/KNN.h
new file mode 100644
index 0000000000000000000000000000000000000000..6950472604ee43f7b9ec238f8579a26a3340231a
--- /dev/null
+++ b/src/algorithms/KNN.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <iostream>
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 3
+
+#include <opencv2/opencv.hpp>
+#include <opencv2/video/background_segm.hpp>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class KNN : public IBGS
+    {
+    private:
+      cv::Ptr<cv::BackgroundSubtractorKNN> knn;
+      int history;
+      int nSamples;
+      float dist2Threshold;
+      int knnSamples;
+      bool doShadowDetection;
+      int shadowValue;
+      float shadowThreshold;
+
+    public:
+      KNN();
+      ~KNN();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(KNN);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBAdaptiveSOM.cpp b/src/algorithms/LBAdaptiveSOM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4c0303571468a742b88f4c1164502c0e16fab64e
--- /dev/null
+++ b/src/algorithms/LBAdaptiveSOM.cpp
@@ -0,0 +1,84 @@
+#include "LBAdaptiveSOM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBAdaptiveSOM::LBAdaptiveSOM() :
+  IBGS(quote(LBAdaptiveSOM)),
+  sensitivity(75), trainingSensitivity(245),
+  learningRate(62), trainingLearningRate(255),
+  trainingSteps(55)
+{
+  debug_construction(LBAdaptiveSOM);
+  initLoadSaveConfig(algorithmName);
+}
+
+LBAdaptiveSOM::~LBAdaptiveSOM() {
+  debug_destruction(LBAdaptiveSOM);
+  delete m_pBGModel;
+}
+
+void LBAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage *frame = &_frame;
+#else
+  IplImage *frame = new IplImage(img_input);
+#endif
+  if (firstTime) {
+    int w = cvGetSize(frame).width;
+    int h = cvGetSize(frame).height;
+
+    m_pBGModel = new lb::BGModelSom(w, h);
+    m_pBGModel->InitModel(frame);
+  }
+
+  m_pBGModel->setBGModelParameter(0, sensitivity);
+  m_pBGModel->setBGModelParameter(1, trainingSensitivity);
+  m_pBGModel->setBGModelParameter(2, learningRate);
+  m_pBGModel->setBGModelParameter(3, trainingLearningRate);
+  m_pBGModel->setBGModelParameter(5, trainingSteps);
+
+  m_pBGModel->UpdateModel(frame);
+
+  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
+  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+
+  firstTime = false;
+}
+
+void LBAdaptiveSOM::save_config(cv::FileStorage &fs) {
+  fs << "sensitivity" << sensitivity;
+  fs << "trainingSensitivity" << trainingSensitivity;
+  fs << "learningRate" << learningRate;
+  fs << "trainingLearningRate" << trainingLearningRate;
+  fs << "trainingSteps" << trainingSteps;
+  fs << "showOutput" << showOutput;
+}
+
+void LBAdaptiveSOM::load_config(cv::FileStorage &fs) {
+  fs["sensitivity"] >> sensitivity;
+  fs["trainingSensitivity"] >> trainingSensitivity;
+  fs["learningRate"] >> learningRate;
+  fs["trainingLearningRate"] >> trainingLearningRate;
+  fs["trainingSteps"] >> trainingSteps;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBAdaptiveSOM.h b/src/algorithms/LBAdaptiveSOM.h
new file mode 100644
index 0000000000000000000000000000000000000000..7141f91e0fcda5cd0b831c28883835a111774cb7
--- /dev/null
+++ b/src/algorithms/LBAdaptiveSOM.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "lb/BGModelSom.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBAdaptiveSOM : public IBGS
+    {
+    private:
+      lb::BGModel* m_pBGModel;
+      int sensitivity;
+      int trainingSensitivity;
+      int learningRate;
+      int trainingLearningRate;
+      int trainingSteps;
+
+    public:
+      LBAdaptiveSOM();
+      ~LBAdaptiveSOM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBAdaptiveSOM);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBFuzzyAdaptiveSOM.cpp b/src/algorithms/LBFuzzyAdaptiveSOM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a88b5780e4d2c03cbea7d52be5ec384480ac8ff6
--- /dev/null
+++ b/src/algorithms/LBFuzzyAdaptiveSOM.cpp
@@ -0,0 +1,84 @@
+#include "LBFuzzyAdaptiveSOM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBFuzzyAdaptiveSOM::LBFuzzyAdaptiveSOM() :
+  IBGS(quote(LBFuzzyAdaptiveSOM)),
+  sensitivity(90), trainingSensitivity(240), learningRate(38), 
+  trainingLearningRate(255), trainingSteps(81)
+{
+  debug_construction(LBFuzzyAdaptiveSOM);
+  initLoadSaveConfig(algorithmName);
+}
+
+LBFuzzyAdaptiveSOM::~LBFuzzyAdaptiveSOM() {
+  debug_destruction(LBFuzzyAdaptiveSOM);
+  delete m_pBGModel;
+}
+
+void LBFuzzyAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage *frame = &_frame;
+#else
+  IplImage *frame = new IplImage(img_input);
+#endif
+
+  if (firstTime) {
+    int w = cvGetSize(frame).width;
+    int h = cvGetSize(frame).height;
+
+    m_pBGModel = new lb::BGModelFuzzySom(w, h);
+    m_pBGModel->InitModel(frame);
+  }
+
+  m_pBGModel->setBGModelParameter(0, sensitivity);
+  m_pBGModel->setBGModelParameter(1, trainingSensitivity);
+  m_pBGModel->setBGModelParameter(2, learningRate);
+  m_pBGModel->setBGModelParameter(3, trainingLearningRate);
+  m_pBGModel->setBGModelParameter(5, trainingSteps);
+
+  m_pBGModel->UpdateModel(frame);
+
+  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
+  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+
+  firstTime = false;
+}
+
+void LBFuzzyAdaptiveSOM::save_config(cv::FileStorage &fs) {
+  fs << "sensitivity" << sensitivity;
+  fs << "trainingSensitivity" << trainingSensitivity;
+  fs << "learningRate" << learningRate;
+  fs << "trainingLearningRate" << trainingLearningRate;
+  fs << "trainingSteps" << trainingSteps;
+  fs << "showOutput" << showOutput;
+}
+
+void LBFuzzyAdaptiveSOM::load_config(cv::FileStorage &fs) {
+  fs["sensitivity"] >> sensitivity;
+  fs["trainingSensitivity"] >> trainingSensitivity;
+  fs["learningRate"] >> learningRate;
+  fs["trainingLearningRate"] >> trainingLearningRate;
+  fs["trainingSteps"] >> trainingSteps;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBFuzzyAdaptiveSOM.h b/src/algorithms/LBFuzzyAdaptiveSOM.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c45382913d35ca941b05f2cc29be89b1216fb6c
--- /dev/null
+++ b/src/algorithms/LBFuzzyAdaptiveSOM.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "lb/BGModelFuzzySom.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBFuzzyAdaptiveSOM : public IBGS
+    {
+    private:
+      lb::BGModel* m_pBGModel;
+      int sensitivity;
+      int trainingSensitivity;
+      int learningRate;
+      int trainingLearningRate;
+      int trainingSteps;
+
+    public:
+      LBFuzzyAdaptiveSOM();
+      ~LBFuzzyAdaptiveSOM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBFuzzyAdaptiveSOM);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBFuzzyGaussian.cpp b/src/algorithms/LBFuzzyGaussian.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31e3232d795b14573c73a2259446bea894ef31f4
--- /dev/null
+++ b/src/algorithms/LBFuzzyGaussian.cpp
@@ -0,0 +1,80 @@
+#include "LBFuzzyGaussian.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBFuzzyGaussian::LBFuzzyGaussian() :
+  IBGS(quote(LBFuzzyGaussian)),
+  sensitivity(72), bgThreshold(162), 
+  learningRate(49), noiseVariance(195)
+{
+  debug_construction(LBFuzzyGaussian);
+  initLoadSaveConfig(algorithmName);
+}
+
+LBFuzzyGaussian::~LBFuzzyGaussian() {
+  debug_destruction(LBFuzzyGaussian);
+  delete m_pBGModel;
+}
+
+void LBFuzzyGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage *frame = &_frame;
+#else
+  IplImage *frame = new IplImage(img_input);
+#endif
+  if (firstTime) {
+    int w = cvGetSize(frame).width;
+    int h = cvGetSize(frame).height;
+
+    m_pBGModel = new lb::BGModelFuzzyGauss(w, h);
+    m_pBGModel->InitModel(frame);
+  }
+
+  m_pBGModel->setBGModelParameter(0, sensitivity);
+  m_pBGModel->setBGModelParameter(1, bgThreshold);
+  m_pBGModel->setBGModelParameter(2, learningRate);
+  m_pBGModel->setBGModelParameter(3, noiseVariance);
+
+  m_pBGModel->UpdateModel(frame);
+
+  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
+  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+
+  firstTime = false;
+}
+
+void LBFuzzyGaussian::save_config(cv::FileStorage &fs) {
+  fs << "sensitivity" << sensitivity;
+  fs << "bgThreshold" << bgThreshold;
+  fs << "learningRate" << learningRate;
+  fs << "noiseVariance" << noiseVariance;
+  fs << "showOutput" << showOutput;
+}
+
+void LBFuzzyGaussian::load_config(cv::FileStorage &fs) {
+  fs["sensitivity"] >> sensitivity;
+  fs["bgThreshold"] >> bgThreshold;
+  fs["learningRate"] >> learningRate;
+  fs["noiseVariance"] >> noiseVariance;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBFuzzyGaussian.h b/src/algorithms/LBFuzzyGaussian.h
new file mode 100644
index 0000000000000000000000000000000000000000..3725fda48aff1e7641d85e28d4d514a2883f36a6
--- /dev/null
+++ b/src/algorithms/LBFuzzyGaussian.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "lb/BGModelFuzzyGauss.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBFuzzyGaussian : public IBGS
+    {
+    private:
+      lb::BGModel* m_pBGModel;
+      int sensitivity;
+      int bgThreshold;
+      int learningRate;
+      int noiseVariance;
+
+    public:
+      LBFuzzyGaussian();
+      ~LBFuzzyGaussian();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBFuzzyGaussian);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBMixtureOfGaussians.cpp b/src/algorithms/LBMixtureOfGaussians.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..449b99c71fdb00fc45a5786dbe2a1cac2c474242
--- /dev/null
+++ b/src/algorithms/LBMixtureOfGaussians.cpp
@@ -0,0 +1,80 @@
+#include "LBMixtureOfGaussians.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBMixtureOfGaussians::LBMixtureOfGaussians() :
+  IBGS(quote(LBMixtureOfGaussians)),
+  sensitivity(81), bgThreshold(83), 
+  learningRate(59), noiseVariance(206)
+{
+  debug_construction(LBMixtureOfGaussians);
+  initLoadSaveConfig(algorithmName);
+}
+
+LBMixtureOfGaussians::~LBMixtureOfGaussians() {
+  debug_destruction(LBMixtureOfGaussians);
+  delete m_pBGModel;
+}
+
+void LBMixtureOfGaussians::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage *frame = &_frame;
+#else
+  IplImage *frame = new IplImage(img_input);
+#endif
+  if (firstTime) {
+    int w = cvGetSize(frame).width;
+    int h = cvGetSize(frame).height;
+
+    m_pBGModel = new lb::BGModelMog(w, h);
+    m_pBGModel->InitModel(frame);
+  }
+
+  m_pBGModel->setBGModelParameter(0, sensitivity);
+  m_pBGModel->setBGModelParameter(1, bgThreshold);
+  m_pBGModel->setBGModelParameter(2, learningRate);
+  m_pBGModel->setBGModelParameter(3, noiseVariance);
+
+  m_pBGModel->UpdateModel(frame);
+
+  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
+  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+
+  firstTime = false;
+}
+
+void LBMixtureOfGaussians::save_config(cv::FileStorage &fs) {
+  fs << "sensitivity" << sensitivity;
+  fs << "bgThreshold" << bgThreshold;
+  fs << "learningRate" << learningRate;
+  fs << "noiseVariance" << noiseVariance;
+  fs << "showOutput" << showOutput;
+}
+
+void LBMixtureOfGaussians::load_config(cv::FileStorage &fs) {
+  fs["sensitivity"] >> sensitivity;
+  fs["bgThreshold"] >> bgThreshold;
+  fs["learningRate"] >> learningRate;
+  fs["noiseVariance"] >> noiseVariance;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBMixtureOfGaussians.h b/src/algorithms/LBMixtureOfGaussians.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4211561ba04442c6b5ed0a6effd43b4fa6821bb
--- /dev/null
+++ b/src/algorithms/LBMixtureOfGaussians.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "lb/BGModelMog.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBMixtureOfGaussians : public IBGS
+    {
+    private:
+      lb::BGModel* m_pBGModel;
+      int sensitivity;
+      int bgThreshold;
+      int learningRate;
+      int noiseVariance;
+
+    public:
+      LBMixtureOfGaussians();
+      ~LBMixtureOfGaussians();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBMixtureOfGaussians);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF.cpp b/src/algorithms/LBP_MRF.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c0f31de1bdc87791a299d9dc69e44e8394653480
--- /dev/null
+++ b/src/algorithms/LBP_MRF.cpp
@@ -0,0 +1,63 @@
+#include "LBP_MRF.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBP_MRF::LBP_MRF() :
+  IBGS(quote(LBP_MRF)),
+  Detector(nullptr)
+{
+  debug_construction(LBP_MRF);
+  initLoadSaveConfig(algorithmName);
+  Detector = new lbp_mrf::MotionDetection();
+  Detector->SetMode(lbp_mrf::MotionDetection::md_LBPHistograms);
+}
+
+LBP_MRF::~LBP_MRF() {
+  debug_destruction(LBP_MRF);
+  delete Detector;
+  Detector = nullptr;
+}
+
+void LBP_MRF::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage TempImage = cvIplImage(img_input);
+#else
+  IplImage TempImage(img_input);
+#endif
+
+  lbp_mrf::MEImage InputImage(img_input.cols, img_input.rows, img_input.channels());
+  lbp_mrf::MEImage OutputImage(img_input.cols, img_input.rows, img_input.channels());
+
+  InputImage.SetIplImage((void*)&TempImage);
+
+  Detector->DetectMotions(InputImage);
+  Detector->GetMotionsMask(OutputImage);
+  img_foreground = cv::cvarrToMat((IplImage*)OutputImage.GetIplImage());
+  //bitwise_not(img_foreground, img_background);
+  img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void LBP_MRF::save_config(cv::FileStorage &fs) {
+  fs << "showOutput" << showOutput;
+}
+
+void LBP_MRF::load_config(cv::FileStorage &fs) {
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF.h b/src/algorithms/LBP_MRF.h
new file mode 100644
index 0000000000000000000000000000000000000000..0edb3873155940fa683ba053a095a0f12380f479
--- /dev/null
+++ b/src/algorithms/LBP_MRF.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "LBP_MRF/MotionDetection.hpp"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBP_MRF : public IBGS
+    {
+    private:
+      lbp_mrf::MotionDetection* Detector;
+      cv::Mat img_segmentation;
+
+    public:
+      LBP_MRF();
+      ~LBP_MRF();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBP_MRF);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MEDefs.cpp b/src/algorithms/LBP_MRF/MEDefs.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..817d7d15f261258da15251b70d9dd70129790680
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MEDefs.cpp
@@ -0,0 +1,33 @@
+#include <math.h>
+
+#include "MEDefs.hpp"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//using namespace bgslibrary::algorithms::lbp_mrf;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      float MERound(float number)
+      {
+        double FracPart = 0.0;
+        double IntPart = 0.0;
+        float Ret = 0.0;
+
+        FracPart = modf((double)number, &IntPart);
+        if (number >= 0)
+          Ret = (float)(FracPart >= 0.5 ? IntPart + 1 : IntPart);
+        else
+          Ret = (float)(FracPart <= -0.5 ? IntPart - 1 : IntPart);
+
+        return Ret;
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MEDefs.hpp b/src/algorithms/LBP_MRF/MEDefs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..386dc9610c203f5add6462bfd42b5024c2cf2760
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MEDefs.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      const double ME_PI_VALUE = 3.14159265;
+      
+      /*! Process state */
+      typedef enum {
+        ps_Min = 0,                /*!< Minimum value */
+        ps_Uninitialized = ps_Min, /*!< Uninitialized state */
+        ps_Initialized,            /*!< Initialized state */
+        ps_InProgress,             /*!< In progress state */
+        ps_Successful,             /*!< Successful state */
+        ps_Max = ps_Successful     /*!< Maximum value */
+      } MEProcessStateType;
+
+      template <typename T>
+      const T& MEMin(const T& a, const T& b)
+      {
+        if (a < b)
+          return a;
+        return b;
+      }
+
+      template <typename T>
+      const T& MEMax(const T& a, const T& b)
+      {
+        if (a < b)
+          return b;
+        return a;
+      }
+
+      template <typename T>
+      const T& MEBound(const T& min, const T& val, const T& max)
+      {
+        return MEMax(min, MEMin(max, val));
+      }
+
+      /*!
+      * @brief Round a float number
+      *
+      * @param number number to round
+      *
+      * @return New float number
+      *
+      * This method rounds a float number, if the fraction is .5 or lower
+      * then it rounds down, otherwise up.
+      *
+      */
+
+      float MERound(float number);
+
+      /** @} */
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/LBP_MRF/MEHistogram.cpp b/src/algorithms/LBP_MRF/MEHistogram.cpp
similarity index 85%
rename from package_bgs/LBP_MRF/MEHistogram.cpp
rename to src/algorithms/LBP_MRF/MEHistogram.cpp
index 17c77fdb9079f40391229f37401e64dd5b0e2b1e..78875ddb87ec4c7a9925e5aba891fe92fc8ef2d4 100644
--- a/package_bgs/LBP_MRF/MEHistogram.cpp
+++ b/src/algorithms/LBP_MRF/MEHistogram.cpp
@@ -1,70 +1,27 @@
-/*
-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/>.
-*/
-/*
- *  This file is part of the AiBO+ project
- *
- *  Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com)
- *
- *  AiBO+ 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 2 of the License, or
- *  (at your option) any later version.
- *
- *  AiBO+ 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 this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- *  Some histogram stretch codes are based on how Gimp does it, the same
- *  GPL 2 license applies for the following authors:
- *
- *  The GIMP -- an image manipulation program
- *  Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- */
-
-#include "MEHistogram.hpp"
-
 #include <opencv2/opencv.hpp>
+// opencv legacy includes
+#include <opencv2/core/core_c.h>
+#include <opencv2/imgproc/types_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
 
+#include "MEHistogram.hpp"
 #include "MEDefs.hpp"
 #include "MEImage.hpp"
 
-MEHistogram::MEHistogram()
-{
-  Clear();
-}
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
 
+using namespace bgslibrary::algorithms::lbp_mrf;
 
-MEHistogram::~MEHistogram()
-{
+MEHistogram::MEHistogram() {
+  Clear();
 }
 
+MEHistogram::~MEHistogram(){}
 
-void MEHistogram::Clear()
-{
+void MEHistogram::Clear() {
   memset(&HistogramData, 0, 256 * sizeof(int));
 }
 
-
 bool MEHistogram::operator==(MEHistogram& histogram) const
 {
   bool ret = true;
@@ -80,7 +37,6 @@ bool MEHistogram::operator==(MEHistogram& histogram) const
   return ret;
 }
 
-
 void MEHistogram::Calculate(MEImage& image, int channel, HistogramType mode)
 {
   int Channel = (channel < 1) ? 1 : ((channel > image.GetLayers()) ? image.GetLayers() : channel);
@@ -103,7 +59,6 @@ void MEHistogram::Calculate(MEImage& image, int channel, HistogramType mode)
   }
 }
 
-
 void MEHistogram::Calculate(MEImage& image, HistogramType mode)
 {
   if (mode == h_Overwrite)
@@ -125,7 +80,6 @@ void MEHistogram::Calculate(MEImage& image, HistogramType mode)
   }
 }
 
-
 void MEHistogram::Calculate(MEImage& image, int channel, int x0, int y0, int x1, int y1)
 {
   int Channel = (channel < 1) ? 1 : ((channel > image.GetLayers()) ? image.GetLayers() : channel);
@@ -157,7 +111,6 @@ void MEHistogram::Calculate(MEImage& image, int channel, int x0, int y0, int x1,
   }
 }
 
-
 int MEHistogram::GetPeakIndex() const
 {
   int PeakIndex = 0;
@@ -174,7 +127,6 @@ int MEHistogram::GetPeakIndex() const
   return PeakIndex;
 }
 
-
 int MEHistogram::GetLowestLimitIndex(int threshold) const
 {
   int MinIndex = 0;
@@ -190,7 +142,6 @@ int MEHistogram::GetLowestLimitIndex(int threshold) const
   return MinIndex;
 }
 
-
 int MEHistogram::GetHighestLimitIndex(int threshold) const
 {
   int MaxIndex = 255;
@@ -206,7 +157,6 @@ int MEHistogram::GetHighestLimitIndex(int threshold) const
   return MaxIndex;
 }
 
-
 int MEHistogram::GetPowerAmount(int minindex, int maxindex) const
 {
   int ValueAmount = 0;
@@ -227,7 +177,6 @@ int MEHistogram::GetPowerAmount(int minindex, int maxindex) const
   return ValueAmount;
 }
 
-
 int MEHistogram::GetCentroidIndex() const
 {
   int ValueAmount = GetPowerAmount(0, 255);
@@ -244,7 +193,6 @@ int MEHistogram::GetCentroidIndex() const
   return CentroidIndex;
 }
 
-
 bool MEHistogram::Stretch(StretchType mode)
 {
   int MinIndex = -1;
@@ -353,25 +301,21 @@ bool MEHistogram::Stretch(StretchType mode)
   return Ret;
 }
 
-
 MEHistogramTransform::MEHistogramTransform() : ChannelMode(p_SeparateChannels),
 StretchMode(MEHistogram::s_GimpMode), DiscreteStretchingDone(false)
 {
 }
 
-
 MEHistogramTransform::~MEHistogramTransform()
 {
 }
 
-
 void MEHistogramTransform::HistogramStretch(MEImage& image)
 {
   SetStretchProcessingMode(p_SeparateChannels, MEHistogram::s_GimpMode);
   HistogramStretch(image, t_Continuous);
 }
 
-
 void MEHistogramTransform::HistogramStretch(MEImage& image, TransformType time_mode)
 {
   if (time_mode == t_Continuous)
@@ -441,7 +385,6 @@ void MEHistogramTransform::HistogramStretch(MEImage& image, TransformType time_m
     }
 }
 
-
 void MEHistogramTransform::HistogramEqualize(MEImage& image)
 {
   DiscreteStretchingDone = false;
@@ -485,7 +428,6 @@ void MEHistogramTransform::HistogramEqualize(MEImage& image)
   }
 }
 
-
 void MEHistogramTransform::SetStretchProcessingMode(ProcessingType new_channel_mode,
   MEHistogram::StretchType new_stretch_mode)
 {
@@ -519,3 +461,5 @@ void MEHistogramTransform::SetStretchProcessingMode(ProcessingType new_channel_m
     break;
   }
 }
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MEHistogram.hpp b/src/algorithms/LBP_MRF/MEHistogram.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe0868c94f1e3309b680d3b93ea53fa6424aae8c
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MEHistogram.hpp
@@ -0,0 +1,331 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      class MEImage;
+
+      /**
+       * MEHistogram
+       * @brief The class provides basic histogram operations
+       */
+      class MEHistogram
+      {
+      public:
+
+        /// Types of histogram calculation
+        typedef enum {
+          h_Min = 0,           /*!< Minimum value */
+          h_Overwrite = h_Min, /*!< Overwrite */
+          h_Add,               /*!< Add */
+          h_Max = h_Add        /*!< Maximum value */
+        } HistogramType;
+
+        /// Types of histogram stretching
+        typedef enum {
+          s_Min = 0,          /*!< Minimum value */
+          s_OwnMode = s_Min,  /*!< Own mode */
+          s_GimpMode,         /*!< Gimp mode */
+          s_Max = s_GimpMode  /*!< Maximum value */
+        } StretchType;
+
+        /// Constructor of class
+        MEHistogram();
+        /// Destructor of class
+        ~MEHistogram();
+
+        /*!
+        * @brief Clear histogram data
+        *
+        * Clear histogram data.
+        *
+        */
+
+        void Clear();
+
+        /*!
+        * @brief Equality (==) operator
+        *
+        * @param histogram Histogram to be compared
+        *
+        * @return True if the two histograms are equal.
+        *
+        * Compare two histograms.
+        *
+        */
+
+        bool operator==(MEHistogram& histogram) const;
+
+        /*!
+        * @brief Calculate the histogram of one color channel
+        *
+        * @param image Given image for the calculations
+        * @param channel Selected color channel for calculation (Range: 1..x)
+        * @param mode The mode of calculation.
+        *
+        * The method calculates the histograms of a color channel.
+        * There is two different type of the function:
+        *
+        * - h_Add: Add the data to the existing histogram.
+        * - h_Overwrite: Clear the histogram data before the
+        * calculation.
+        *
+        */
+
+        void Calculate(MEImage& image, int channel, HistogramType mode);
+
+        /*!
+        * @brief Calculate the average histogram of an image
+        *
+        * @param image Given image for the calculations
+        * @param mode Histogram calculation mode
+        *
+        * The method calculates the average histogram of an image.
+        *
+        */
+
+        void Calculate(MEImage& image, HistogramType mode = h_Overwrite);
+
+        /*!
+        * @brief Calculate the histogram of an image region
+        *
+        * @param image Given image for the calculations
+        * @param channel Selected color channel for calculation (Range: 1..x)
+        * @param x0 x0 coordinate of the region
+        * @param y0 y0 coordinate of the region
+        * @param x1 x1 coordinate of the region
+        * @param y1 y1 coordinate of the region
+        *
+        * The method calculates the average histogram of an image region
+        * (x0,y0)-(x1,y1).
+        *
+        */
+
+        void Calculate(MEImage& image, int channel, int x0, int y0, int x1, int y1);
+
+        /*!
+        * @brief Get the index of maximum value of the histogram
+        *
+        * @return Index number
+        *
+        * Function gives an index value back where is the highest
+        * peak of the histogram.
+        *
+        */
+
+        int GetPeakIndex() const;
+
+        /*!
+        * @brief Get the lowest histogram index with an threshold value
+        *
+        * @param threshold Specified threshold (in percent: 0..100 %)
+        *
+        * @return Index number
+        *
+        * Function gives the lowest index back whose value reaches
+        * an threshold value calculated by (counted pixel number /
+        * 10*threshold / 100).
+        *
+        */
+
+        int GetLowestLimitIndex(int threshold) const;
+
+        /*!
+        * @brief Get the highest histogram index with an threshold value
+        *
+        * @param threshold Specified threshold (in percent: 0..100 %)
+        *
+        * @return Index number
+        *
+        * Function gives the highest index back whose value reaches
+        * an threshold value calculated by (counted pixel number /
+        * 10*threshold / 100).
+        *
+        */
+
+        int GetHighestLimitIndex(int threshold) const;
+
+        /*!
+        * @brief Get the amount of the histogram values in an interval
+        *
+        * @param minindex Minimal index of the interval
+        * @param maxindex Maximal index of the interval
+        *
+        * @return Amount of the values
+        *
+        * Function calculates the amount of the histogram values
+        * in a given interval.
+        *
+        */
+
+        int GetPowerAmount(int min_index, int max_index) const;
+
+        /*!
+        * @brief Get index value of the centroid point of the histogram
+        *
+        * @return Index number
+        *
+        * Function calculates the centre of area of the histogram and
+        * gives the index number back.
+        *
+        */
+
+        int GetCentroidIndex() const;
+
+        /*!
+        * @brief Stretch the histogram
+        *
+        * @param mode Mode of the histogram stretching
+        *
+        * @return True if successful, otherwise false.
+        *
+        * The function selects and stretches the main power
+        * interval of the histogram. The following calculation
+        * modes are available:
+        *
+        * - s_OwnMode: The calculation of the power
+        * interval is selected by functions Histogram::GetHistogramLowestLimitIndex()
+        * and Histogram::GetHistogramHighestLimitIndex() where the
+        * threshold is 20, 10, 5, 2, 1 in order. The power range will
+        * be selected if the length is at least 52 long or the used
+        * threshold reaches the 1 value.
+        * - s_GimpMode: The minimum index of power interval is
+        * specified by the first fulfilled abs(percentage[i]-0.006) <
+        * fabs(percentage[i+1]-0.006) where the percentage[i] means
+        * the amount of the histogram values in the interval [0, i].
+        * The maximum index is specified by the first fulfilled
+        * (from the end of the histogram) abs(percentage[i]-0.006) <
+        * fabs(percentage[i-1]-0.006) where the percentage[i] means
+        * the amount of the histogram values in the interval [i, 255].
+        *
+        * The stretch operation is rejected if the power interval is
+        * less than 10 or less than 20 and the percentage[min_index, max_index]
+        * / percentage[0, 255] < 0.2.
+        *
+        */
+
+        bool Stretch(StretchType mode);
+
+        /// Histogram spectrum
+        int HistogramData[256];
+      };
+
+
+      /**
+       * MEHistogramTransform
+       * @brief The class provides histogram operations
+       */
+      class MEHistogramTransform
+      {
+      public:
+        /// Types of histogram processing
+        typedef enum {
+          p_Min = 0,                   /*!< Minimum value */
+          p_SeparateChannels = p_Min, /*!< Separate channels */
+          p_Average,                   /*!< Average */
+          p_Max = p_Average           /*!< Maximum value */
+        } ProcessingType;
+
+        /// Types of histogram transformations
+        typedef enum {
+          t_Min = 0,             /*!< Minimum value */
+          t_Continuous = t_Min, /*!< Continuous */
+          t_Discrete,            /*!< Discrete */
+          t_Max = t_Discrete    /*!< Maximum value */
+        } TransformType;
+
+        /// Constructor of class
+        MEHistogramTransform();
+        /// Destructor of class
+        ~MEHistogramTransform();
+
+        /*!
+        * @brief Histogram stretching an image
+        *
+        * @param image Source image to stretch
+        *
+        * The function stretches the histogram of the given image with
+        * default parameters: process the color channels separately
+        * and continuously.
+        *
+        */
+
+        void HistogramStretch(MEImage& image);
+
+        /*!
+        * @brief Histogram stretching with specified parameters
+        *
+        * @param image Source image to stretch
+        * @param time_mode Mode of the histogram stretching
+        *
+        * The function transformations the histogram of the image.
+        * There is some different possibilities to make the operation:
+        *
+        * - t_Continuous: The function always stretches the
+        * image at each call of the method.
+        * - t_Discrete: A histogram is calculated at the first
+        * call of the function and all further images will be
+        * stretched by this initial histogram.
+        *
+        */
+
+        void HistogramStretch(MEImage& image, TransformType time_mode);
+
+        /*!
+        * @brief Histogram equalization on an image
+        *
+        * @param image Source image to equalize
+        *
+        * The source image is transformed by histogram
+        * equalization.
+        *
+        */
+
+        void HistogramEqualize(MEImage& image);
+
+        /*!
+        * @brief Set the process mode of the histogram transformation
+        *
+        * @param new_channel_mode New mode of processing channels
+        * @param new_stretch_mode New mode of histogram stretching
+        *
+        * The process mode of histogram transformation can be
+        * set by this method. Two process modes are available for
+        * processing channels:
+        *
+        * - p_SeparateChannels: The class processes the color channels
+        * separately.
+        * - p_Average: The color channels are averaged
+        * in the histogram operations.
+        *
+        * Two process modes are usable for histogram stretching:
+        * s_OwnMode and s_GimpMode. See Histogram::Stretch()
+        * for more details.
+        *
+        */
+
+        void SetStretchProcessingMode(ProcessingType new_channel_mode, MEHistogram::StretchType new_stretch_mode);
+
+      private:
+        /// Type of the process of histograms
+        ProcessingType ChannelMode;
+        /// Stretch mode
+        MEHistogram::StretchType StretchMode;
+        /// Histograms for red, green and blue color channels
+        MEHistogram RedChannel, GreenChannel, BlueChannel;
+        /// Histogram for average calculation
+        MEHistogram AverageChannel;
+        /// Continuous histogram stretch is done already
+        bool DiscreteStretchingDone;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MEImage.cpp b/src/algorithms/LBP_MRF/MEImage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3103e73f594e48d2c0f99153f7af2f0e80526ae9
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MEImage.cpp
@@ -0,0 +1,1408 @@
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "MEImage.hpp"
+#include "MEDefs.hpp"
+
+//#if CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9
+//#define CV_RGB(r, g, b) cvScalar((b), (g), (r), 0)
+//#endif
+#define CV_RGB_LEGACY(r, g, b) cvScalar((b), (g), (r), 0)
+
+//using namespace bgslibrary::algorithms::lbp_mrf;
+
+#define ME_CAST_TO_IPLIMAGE(image_ptr) ((IplImage*)image_ptr)
+#define ME_RELEASE_IPLIMAGE(image_ptr) \
+  cvReleaseImage((IplImage**)&image_ptr); \
+  image_ptr = NULL;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      // RGB to YUV transform
+      const float RGBtoYUVMatrix[3][3] =
+      { { 0.299, 0.587, 0.114 },
+       { -0.147, -0.289, 0.436 },
+       { 0.615, -0.515, -0.100 } };
+
+      // RGB to YIQ transform
+      const float RGBtoYIQMatrix[3][3] =
+      { { 0.299, 0.587, 0.114 },
+       { 0.596, -0.274, -0.322 },
+       { 0.212, -0.523, 0.311 } };
+
+      MEImage::MEImage(int width, int height, int layers) : cvImg(NULL)
+      {
+        _Init(width, height, layers);
+      }
+
+      MEImage::MEImage(const MEImage& other) : cvImg(NULL)
+      {
+        _Copy(other);
+      }
+
+      MEImage::~MEImage()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg))
+        {
+          ME_RELEASE_IPLIMAGE(cvImg);
+        }
+      }
+
+      void MEImage::Clear()
+      {
+        cvSetZero(ME_CAST_TO_IPLIMAGE(cvImg));
+      }
+
+      void MEImage::GetLayer(MEImage& new_layer, int layer_number) const
+      {
+        int LayerNumber = layer_number;
+
+        if ((new_layer.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width) ||
+          (new_layer.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height) ||
+          (new_layer.GetLayers() != 1))
+        {
+          new_layer.Realloc(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height, 1);
+        }
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels < LayerNumber)
+        {
+          printf("The given layer number is too large (%d > %d)\n",
+            LayerNumber, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+          LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
+        }
+        if (LayerNumber <= 0)
+        {
+          printf("The given layer number is too small (%d <= 0)\n", LayerNumber);
+          LayerNumber = 1;
+        }
+
+        cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), LayerNumber);
+        cvCopy(ME_CAST_TO_IPLIMAGE(cvImg), (IplImage*)new_layer.GetIplImage(), NULL);
+        cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), 0);
+      }
+
+      void MEImage::SetLayer(MEImage& layer, int layer_number)
+      {
+        int LayerNumber = layer_number;
+
+        if (layer.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          layer.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height)
+        {
+          printf("The dimensions of the layer and "
+            "destination image is different (%dx%d <> %dx%d)\n",
+            layer.GetWidth(), layer.GetHeight(), ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height);
+          return;
+        }
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels < LayerNumber)
+        {
+          printf("The given layer number is too large (%d > %d)\n",
+            LayerNumber, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
+        }
+        if (LayerNumber <= 0)
+        {
+          printf("The given layer number is too small (%d <= 0)\n", LayerNumber);
+          LayerNumber = 1;
+        }
+        if (layer.GetLayers() != 1)
+        {
+          printf("The layer image has not one color channel (1 != %d)\n",
+            layer.GetLayers());
+          return;
+        }
+        cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), LayerNumber);
+        cvCopy((IplImage*)layer.GetIplImage(), ME_CAST_TO_IPLIMAGE(cvImg), NULL);
+        cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), 0);
+      }
+
+      void MEImage::CopyImageData(unsigned char* data)
+      {
+        memcpy(ME_CAST_TO_IPLIMAGE(cvImg)->imageData, data, ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+      }
+
+      void* MEImage::GetIplImage() const
+      {
+        return (void*)ME_CAST_TO_IPLIMAGE(cvImg);
+      }
+
+      void MEImage::SetIplImage(void* image)
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg))
+        {
+          ME_RELEASE_IPLIMAGE(cvImg);
+        }
+        cvImg = cvCloneImage((IplImage*)image);
+        // Correct the origin of the image
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->origin == 1)
+        {
+          MirrorVertical();
+          ME_CAST_TO_IPLIMAGE(cvImg)->origin = 0;
+        }
+      }
+
+      bool MEImage::operator==(const MEImage& image)
+      {
+        return Equal(image);
+      }
+
+      bool MEImage::operator!=(const MEImage& image)
+      {
+        return !operator==(image);
+      }
+
+      MEImage& MEImage::operator=(const MEImage& other_image)
+      {
+        if (&other_image == this)
+          return *this;
+
+        _Copy(other_image);
+        return *this;
+      }
+
+      int MEImage::GetWidth() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : 0;
+      }
+
+      int MEImage::GetRowWidth() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->widthStep : 0;
+      }
+
+      int MEImage::GetHeight() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : 0;
+      }
+
+      int MEImage::GetLayers() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? ME_CAST_TO_IPLIMAGE(cvImg)->nChannels : 0;
+      }
+
+      int MEImage::GetPixelDataNumber() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? GetWidth()*GetHeight()*GetLayers() : 0;
+      }
+
+      unsigned char* MEImage::GetImageData() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData : NULL;
+      }
+
+      void MEImage::SetData(unsigned char* image_data, int width, int height, int channels)
+      {
+        _Init(width, height, channels);
+
+        for (int y = height - 1; y >= 0; --y)
+        {
+          int Start = GetRowWidth()*y;
+          int Start2 = width*channels*y;
+
+          memcpy(&ME_CAST_TO_IPLIMAGE(cvImg)->imageData[Start], &image_data[Start2], width*channels);
+        }
+      }
+
+      float MEImage::GetRatio() const
+      {
+        return ME_CAST_TO_IPLIMAGE(cvImg) ? (float)ME_CAST_TO_IPLIMAGE(cvImg)->height / (float)ME_CAST_TO_IPLIMAGE(cvImg)->width : 0.0;
+      }
+
+      void MEImage::Realloc(int width, int height)
+      {
+        Realloc(width, height, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+      }
+
+      void MEImage::Realloc(int width, int height, int layers)
+      {
+        _Init(width, height, layers);
+      }
+
+      void MEImage::Resize(int new_width, int new_height)
+      {
+        if (new_height < 1)
+        {
+          printf("Invalid new height: %d < 1\n", new_height);
+          return;
+        }
+        if (new_width < 1)
+        {
+          printf("Invalid new width: %d < 1\n", new_width);
+          return;
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(new_width, new_height), 8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        cvResize(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_INTER_NN);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+
+      void MEImage::ResizeScaleX(int new_width)
+      {
+        if (new_width < 1)
+        {
+          printf("Invalid new width: %d < 1\n", new_width);
+          return;
+        }
+        Resize(new_width, (int)((float)new_width*GetRatio()));
+      }
+
+      void MEImage::ResizeScaleY(int new_height)
+      {
+        if (new_height < 1)
+        {
+          printf("Invalid new height: %d < 1\n", new_height);
+          return;
+        }
+        Resize((int)((float)new_height * 1 / GetRatio()), new_height);
+      }
+
+      void MEImage::MirrorHorizontal()
+      {
+        cvFlip(ME_CAST_TO_IPLIMAGE(cvImg), NULL, 1);
+      }
+
+      void MEImage::MirrorVertical()
+      {
+        cvFlip(ME_CAST_TO_IPLIMAGE(cvImg), NULL, 0);
+      }
+
+      void MEImage::Crop(int x1, int y1, int x2, int y2)
+      {
+        int NewX1 = x1;
+        int NewY1 = y1;
+        int NewX2 = x2;
+        int NewY2 = y2;
+
+        NewX1 = (NewX1 < 0) ? 0 : NewX1;
+        NewX1 = (NewX1 > ME_CAST_TO_IPLIMAGE(cvImg)->width) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : NewX1;
+        NewY1 = (NewY1 < 0) ? 0 : NewY1;
+        NewY1 = (NewY1 > ME_CAST_TO_IPLIMAGE(cvImg)->height) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : NewY1;
+
+        NewX2 = (NewX2 < 0) ? 0 : NewX2;
+        NewX2 = (NewX2 > ME_CAST_TO_IPLIMAGE(cvImg)->width) ? ME_CAST_TO_IPLIMAGE(cvImg)->width : NewX2;
+        NewY2 = (NewY2 < 0) ? 0 : NewY2;
+        NewY2 = (NewY2 > ME_CAST_TO_IPLIMAGE(cvImg)->height) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : NewY2;
+
+        if ((NewX2 - NewX1) <= 0)
+        {
+          printf("Invalid new width: %d <= 0\n", NewX2 - NewX1);
+          return;
+        }
+        if ((NewY2 - NewY1) <= 0)
+        {
+          printf("Invalid new height: %d <= 0\n", NewY2 - NewY1);
+          return;
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(NewX2 - NewX1, NewY2 - NewY1), 8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        cvSetImageROI(ME_CAST_TO_IPLIMAGE(cvImg), cvRect(NewX1, NewY1, NewX2 - NewX1, NewY2 - NewY1));
+        cvCopy(ME_CAST_TO_IPLIMAGE(cvImg), TempImg);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::CopyImageInside(int x, int y, MEImage& source_image)
+      {
+        int NewX = x;
+        int NewY = y;
+        int PasteLengthX = source_image.GetWidth();
+        int PasteLengthY = source_image.GetHeight();
+
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != source_image.GetLayers())
+        {
+          if (source_image.GetLayers() == 1 && ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 3)
+          {
+            source_image.ConvertGrayscaleToRGB();
+          }
+          if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1 && source_image.GetLayers() == 3)
+          {
+            source_image.ConvertToGrayscale(g_OpenCV);
+          }
+        }
+        if (NewX < 0)
+          NewX = 0;
+        if (NewX > ME_CAST_TO_IPLIMAGE(cvImg)->width)
+          NewX = ME_CAST_TO_IPLIMAGE(cvImg)->width;
+        if (NewY < 0)
+          NewY = 0;
+        if (NewY > ME_CAST_TO_IPLIMAGE(cvImg)->height)
+          NewY = ME_CAST_TO_IPLIMAGE(cvImg)->height;
+        if (NewX + PasteLengthX > ME_CAST_TO_IPLIMAGE(cvImg)->width)
+          PasteLengthX = ME_CAST_TO_IPLIMAGE(cvImg)->width - NewX;
+        if (NewY + PasteLengthY > ME_CAST_TO_IPLIMAGE(cvImg)->height)
+          PasteLengthY = ME_CAST_TO_IPLIMAGE(cvImg)->height - NewY;
+
+        if (PasteLengthX != source_image.GetWidth() ||
+          PasteLengthY != source_image.GetHeight())
+        {
+          source_image.Resize(PasteLengthX, PasteLengthY);
+        }
+        cvSetImageROI(ME_CAST_TO_IPLIMAGE(cvImg), cvRect(NewX, NewY, PasteLengthX, PasteLengthY));
+        cvCopy((IplImage*)source_image.GetIplImage(), ME_CAST_TO_IPLIMAGE(cvImg));
+        cvResetImageROI(ME_CAST_TO_IPLIMAGE(cvImg));
+      }
+
+      void MEImage::Erode(int iterations)
+      {
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+          ME_CAST_TO_IPLIMAGE(cvImg)->height),
+          8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        cvErode(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, NULL, iterations);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::Dilate(int iterations)
+      {
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+          ME_CAST_TO_IPLIMAGE(cvImg)->height),
+          8, ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        cvDilate(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, NULL, iterations);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::Smooth()
+      {
+        SmoothAdvanced(s_Median, 3);
+      }
+
+      void MEImage::SmoothAdvanced(SmoothType filtermode, int filtersize)
+      {
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+          ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        switch (filtermode)
+        {
+        case s_Blur:
+          cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_BLUR, filtersize, filtersize, 0);
+          break;
+        case s_Median:
+          cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_MEDIAN, filtersize, 0, 0);
+          break;
+        case s_Gaussian:
+          cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_GAUSSIAN, filtersize, filtersize, 0);
+          break;
+        default:
+          cvSmooth(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_MEDIAN, filtersize, 0, 0);
+          break;
+        }
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::Canny()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+          ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+        cvCanny(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 800, 1100, 5);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::Laplace()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+          ME_CAST_TO_IPLIMAGE(cvImg)->height),
+          IPL_DEPTH_16S, 1);
+        cvLaplace(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 3);
+        cvConvertScale(TempImg, ME_CAST_TO_IPLIMAGE(cvImg), 1, 0);
+        ME_RELEASE_IPLIMAGE(cvImg);
+      }
+
+      void MEImage::Quantize(int levels)
+      {
+        if (levels <= 0)
+        {
+          printf("Level number is too small (%d <= 0)\n", levels);
+          return;
+        }
+        if (levels > 256)
+        {
+          printf("Level number is too large (%d > 256)\n", levels);
+          return;
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+
+        for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
+        {
+          ImageData[i] = ImageData[i] / (256 / levels)*(256 / levels);
+        }
+      }
+
+      void MEImage::Threshold(int threshold_limit)
+      {
+        if (threshold_limit < 0)
+        {
+          printf("Threshold number is too small (%d <= 0)\n", threshold_limit);
+          return;
+        }
+        if (threshold_limit > 255)
+        {
+          printf("Threshold number is too large (%d > 255)\n", threshold_limit);
+          return;
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+
+        for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
+        {
+          if (ImageData[i] < threshold_limit)
+          {
+            ImageData[i] = 0;
+          }
+        }
+      }
+
+      void MEImage::AdaptiveThreshold()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+          ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+        cvAdaptiveThreshold(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 25,
+          CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, -7);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::ThresholdByMask(MEImage& mask_image)
+      {
+        if (mask_image.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          mask_image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height)
+        {
+          printf("Image properties are different\n");
+          return;
+        }
+        if (mask_image.GetLayers() != 3 && ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 3)
+        {
+          mask_image.ConvertGrayscaleToRGB();
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* MaskImageData = mask_image.GetImageData();
+
+        for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i)
+        {
+          if (MaskImageData[i] == 0)
+          {
+            ImageData[i] = 0;
+          }
+        }
+      }
+
+      void MEImage::ColorSpace(ColorSpaceConvertType mode)
+      {
+        IplImage* TempImg = NULL;
+        unsigned char* ImageData = NULL;
+        int WidthStep = 0;
+        int RowStart = 0;
+
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1)
+        {
+          printf("No sense to convert: source image is greyscale\n");
+          ConvertGrayscaleToRGB();
+        }
+        switch (mode)
+        {
+        case csc_RGBtoXYZCIED65:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+            ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2XYZ);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_XYZCIED65toRGB:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+            ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_XYZ2RGB);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_RGBtoHSV:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+            ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2HSV);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_HSVtoRGB:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width,
+            ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_HSV2RGB);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_RGBtoHLS:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2HLS);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_HLStoRGB:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_HLS2RGB);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_RGBtoCIELab:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2Lab);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_CIELabtoRGB:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_Lab2RGB);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_RGBtoCIELuv:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2Luv);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_CIELuvtoRGB:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_Luv2RGB);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case csc_RGBtoYUV:
+          ComputeColorSpace(csc_RGBtoYUV);
+          break;
+
+        case csc_RGBtoYIQ:
+          ComputeColorSpace(csc_RGBtoYIQ);
+          break;
+
+        case csc_RGBtorgI:
+          ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+          WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+          RowStart = 0;
+          for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+          {
+            for (int x = (ME_CAST_TO_IPLIMAGE(cvImg)->width - 1) * 3; x >= 0; x -= 3)
+            {
+              int r = 0;
+              int g = 0;
+              int I = 0;
+
+              I = (int)ImageData[RowStart + x] + (int)ImageData[RowStart + x + 1] + (int)ImageData[RowStart + x + 2];
+              r = (int)((float)ImageData[RowStart + x] / I * 255);
+              g = (int)((float)ImageData[RowStart + x + 1] / I * 255);
+              ImageData[RowStart + x] = (unsigned char)r;
+              ImageData[RowStart + x + 1] = (unsigned char)g;
+              ImageData[RowStart + x + 2] = (unsigned char)(I / 3);
+            }
+            RowStart += WidthStep;
+          }
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MEImage::ConvertToGrayscale(GrayscaleType grayscale_mode)
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels == 1)
+        {
+          printf("Image is already grayscale\n");
+          return;
+        }
+        IplImage* TempImg = NULL;
+        unsigned char* ImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* ImageData = NULL;
+
+        switch (grayscale_mode)
+        {
+        case g_Average:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
+          ImageData = (unsigned char*)TempImg->imageData;
+
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 3; i >= 0; i -= 3)
+          {
+            ImageData[i / 3] = (ImgData[i] + ImgData[i + 1] + ImgData[i + 2]) / 3;
+          }
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        case g_OpenCV:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
+          cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_RGB2GRAY);
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MEImage::ConvertGrayscaleToRGB()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 1)
+        {
+          return;
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 3);
+
+        cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, CV_GRAY2RGB);
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::ConvertBGRToRGB()
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 3)
+        {
+          return;
+        }
+        cvCvtColor(ME_CAST_TO_IPLIMAGE(cvImg), ME_CAST_TO_IPLIMAGE(cvImg), CV_RGB2BGR);
+      }
+
+      void MEImage::LBP(LBPType mode)
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, 1);
+        unsigned char* TempImgData = (unsigned char*)TempImg->imageData;
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int WidthStep_2 = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep * 2;
+
+        cvSetZero(TempImg);
+        switch (mode)
+        {
+        case lbp_Normal:
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*(ME_CAST_TO_IPLIMAGE(cvImg)->height - 2) - 1; i >= ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1; --i)
+          {
+            TempImgData[i] =
+              (ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1]) +
+              ((ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep]) * 2) +
+              ((ImageData[i] <= ImageData[i - ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1]) * 4) +
+              ((ImageData[i] <= ImageData[i - 1]) * 8) +
+              ((ImageData[i] <= ImageData[i + 1]) * 16) +
+              ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1]) * 32) +
+              ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep]) * 64) +
+              ((ImageData[i] <= ImageData[i + ME_CAST_TO_IPLIMAGE(cvImg)->widthStep + 1]) * 128);
+          }
+          break;
+
+        case lbp_Special:
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*(ME_CAST_TO_IPLIMAGE(cvImg)->height - 3) - 2; i >= ME_CAST_TO_IPLIMAGE(cvImg)->widthStep * 2 + 2; --i)
+          {
+            int CenterPixel = (ImageData[i + 1] + ImageData[i - 1] +
+              ImageData[i - WidthStep] + ImageData[i + WidthStep]) / 4;
+            TempImgData[i] = ((CenterPixel <= (ImageData[i - (WidthStep_2)-2] +
+              ImageData[i - (WidthStep_2)-1] +
+              ImageData[i - WidthStep - 2] +
+              ImageData[i - WidthStep - 1]) / 4)) +
+              ((CenterPixel <= (ImageData[i - WidthStep] +
+                ImageData[i - (WidthStep_2)]) / 2) * 2) +
+                ((CenterPixel <= ((ImageData[i - (WidthStep_2)+2] +
+                  ImageData[i - (WidthStep_2)+1] +
+                  ImageData[i - WidthStep + 2] +
+                  ImageData[i - WidthStep + 1]) / 4)) * 4) +
+                  ((CenterPixel <= (ImageData[i - 1] +
+                    ImageData[i - 2]) / 2) * 8) +
+                    ((CenterPixel <= (ImageData[i + 1] +
+                      ImageData[i + 2]) / 2) * 16) +
+                      ((CenterPixel <= ((ImageData[i + (WidthStep_2)-2] +
+                        ImageData[i + (WidthStep_2)-1] +
+                        ImageData[i + WidthStep - 2] +
+                        ImageData[i + WidthStep - 1]) / 4)) * 32) +
+                        ((CenterPixel <= (ImageData[i + WidthStep] +
+                          ImageData[i - WidthStep_2]) / 2) * 64) +
+                          ((CenterPixel <= ((ImageData[i + (WidthStep_2)+2] +
+                            ImageData[i + (WidthStep_2)+1] +
+                            ImageData[i + WidthStep + 2] +
+                            ImageData[i + WidthStep + 1]) / 4)) * 128);
+          }
+          break;
+
+        default:
+          break;
+        }
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      void MEImage::Binarize(int threshold)
+      {
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+
+        for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
+        {
+          if (ImageData[i] >= threshold)
+          {
+            ImageData[i] = 255;
+          }
+          else {
+            ImageData[i] = 0;
+          }
+        }
+      }
+
+      void MEImage::Subtract(MEImage& source, SubtractModeType mode)
+      {
+        if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
+          source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
+        {
+          printf("Image properties are different.\n");
+          return;
+        }
+        unsigned char* ImageData = NULL;
+        unsigned char* DstData = NULL;
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+
+        switch (mode)
+        {
+        case sub_Normal:
+          ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+          DstData = source.GetImageData();
+          RowStart = 0;
+
+          for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+          {
+            for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+            {
+              ImageData[RowStart + x] =
+                ImageData[RowStart + x] - DstData[RowStart + x] < 0 ? 0 :
+                ImageData[RowStart + x] - DstData[RowStart + x];
+            }
+            RowStart += WidthStep;
+          }
+          break;
+
+        case sub_Absolut:
+          ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+          DstData = source.GetImageData();
+          RowStart = 0;
+
+          for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+          {
+            for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+            {
+              ImageData[RowStart + x] = ImageData[RowStart + x] -
+                DstData[RowStart + x] < 0 ? -ImageData[RowStart + x] +
+                DstData[RowStart + x] : ImageData[RowStart + x] - DstData[RowStart + x];
+            }
+            RowStart += WidthStep;
+          }
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MEImage::Multiple(MEImage& source, MultiplicationType mode)
+      {
+        if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
+          source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
+        {
+          printf("Image properties are different.\n");
+          return;
+        }
+        float Result = 0.0;
+        IplImage* TempImg = NULL;
+        unsigned char* ImageData = NULL;
+        unsigned char* ImageData2 = NULL;
+        unsigned char* ImageData3 = NULL;
+        unsigned char* DstData = NULL;
+
+        switch (mode)
+        {
+        case m_Normal:
+          Result = 0;
+          ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+          DstData = source.GetImageData();
+
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
+          {
+            if ((ImageData[i] >= 128) && (DstData[i] >= 128))
+            {
+              Result = (float)ImageData[i] / 128 * (float)DstData[i] / 128;
+
+              if (Result >= 1)
+              {
+                ImageData[i] = 255;
+              }
+              else {
+                ImageData[i] = 0;
+              }
+            }
+            else {
+              ImageData[i] = 0;
+            }
+          }
+          break;
+
+        case m_Neighbourhood:
+          TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+            ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          ImageData2 = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+          DstData = source.GetImageData();
+          ImageData3 = (unsigned char*)TempImg->imageData;
+
+          for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+            for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width - 1; x >= 0; --x)
+              for (int l = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; l >= 0; --l)
+              {
+                if (((DstData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
+                  x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] == 255) ||
+                  (ImageData2[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
+                    x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] == 255)) &&
+                    (NeighbourhoodCounter(x - 2, y - 2, n_5x5) > 3) &&
+                  (source.NeighbourhoodCounter(x - 2, y - 2, n_5x5) > 3))
+                {
+                  ImageData3[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels +
+                    x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] = 255;
+                }
+              }
+          ME_RELEASE_IPLIMAGE(cvImg);
+          cvImg = TempImg;
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MEImage::Addition(MEImage& source, AdditionType mode)
+      {
+        if (source.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
+          source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
+        {
+          printf("Image properties are different.\n");
+          return;
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* DstData = source.GetImageData();
+
+        switch (mode)
+        {
+        case a_Average:
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
+          {
+            ImageData[i] = (ImageData[i] + DstData[i]) / 2;
+          }
+          break;
+
+        case a_Union:
+          for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep - 1; i >= 0; --i)
+          {
+            if (DstData[i] > ImageData[i])
+            {
+              ImageData[i] = DstData[i];
+            }
+          }
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MEImage::EliminateSinglePixels()
+      {
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+          ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* DstData = (unsigned char*)TempImg->imageData;
+        int sum = 0;
+        int xy = 0;
+        int ywidth = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width - 1; x >= 0; --x)
+          {
+            xy = y*ywidth + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
+
+            for (int l = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; l >= 0; --l)
+            {
+              if ((ImageData[xy + l] > 0) && (x > 0) && (y > 0) && (x < ME_CAST_TO_IPLIMAGE(cvImg)->width - 1) && (y < ME_CAST_TO_IPLIMAGE(cvImg)->height - 1))
+              {
+                sum = (ImageData[xy - ywidth - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
+                  (ImageData[xy - ywidth + l] > 0) +
+                  (ImageData[xy - ywidth + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
+                  (ImageData[xy - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
+                  (ImageData[xy + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
+                  (ImageData[xy + ywidth - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0) +
+                  (ImageData[xy + ywidth + l] > 0) +
+                  (ImageData[xy + ywidth + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l] > 0);
+
+                if (sum > 3)
+                {
+                  DstData[xy + l] = 255;
+                }
+                else {
+                  DstData[xy + l] = 0;
+                }
+              }
+              else {
+                DstData[xy + l] = 0;
+              }
+            }
+          }
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+
+      float MEImage::DifferenceAreas(MEImage& reference, int difference) const
+      {
+        if (reference.GetWidth() != GetWidth() ||
+          reference.GetHeight() != GetHeight() ||
+          reference.GetLayers() != GetLayers())
+        {
+          printf("Image dimensions or channels are different\n");
+          return -1.0;
+        }
+        float PixelDiff = 0.0;
+        int Pixels = 0;
+        unsigned char* OrigImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* RefImgData = reference.GetImageData();
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+        {
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+          {
+            if (abs(OrigImgData[RowStart + x] - RefImgData[RowStart + x]) > difference)
+              Pixels++;
+          }
+          RowStart += WidthStep;
+        }
+        PixelDiff = (float)Pixels / (ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep) * 100;
+        return PixelDiff;
+      }
+
+      int MEImage::AverageDifference(MEImage& reference) const
+      {
+        if (reference.GetWidth() != GetWidth() ||
+          reference.GetHeight() != GetHeight() ||
+          reference.GetLayers() != GetLayers())
+        {
+          printf("Image dimensions or channels are different\n");
+          return -1;
+        }
+        int Difference = 0;
+        unsigned char* OrigImgData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* RefImgData = reference.GetImageData();
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+        {
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+          {
+            Difference += abs(OrigImgData[RowStart + x] - RefImgData[RowStart + x]);
+          }
+          RowStart += WidthStep;
+        }
+        Difference = Difference / (ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep);
+        return Difference;
+      }
+
+      void MEImage::Minimum(MEImage& image)
+      {
+        if (image.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
+          image.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
+        {
+          printf("Image properties are different\n");
+          return;
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* SecData = image.GetImageData();
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+        {
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+          {
+            ImageData[RowStart + x] = ImageData[RowStart + x] > SecData[RowStart + x] ?
+              SecData[RowStart + x] : ImageData[RowStart + x];
+          }
+          RowStart += WidthStep;
+        }
+      }
+
+      float MEImage::AverageBrightnessLevel() const
+      {
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+        int BrightnessLevel = 0;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+        {
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+          {
+            BrightnessLevel += (int)ImageData[RowStart + x];
+          }
+          RowStart += WidthStep;
+        }
+        return BrightnessLevel / (GetWidth()*GetHeight()*GetLayers());
+      }
+
+      bool MEImage::Equal(const MEImage& reference) const
+      {
+        return Equal(reference, 1);
+      }
+
+      bool MEImage::Equal(const MEImage& reference, int maxabsdiff) const
+      {
+        bool Ret = true;
+
+        if (reference.GetWidth() != ME_CAST_TO_IPLIMAGE(cvImg)->width ||
+          reference.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height ||
+          reference.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels)
+        {
+          printf("Image properties are different\n");
+          return false;
+        }
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* RefData = reference.GetImageData();
+        int WidthStep = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep;
+        int RowStart = 0;
+
+        for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; y >= 0; --y)
+        {
+          for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x)
+          {
+            if (abs(ImageData[RowStart + x] - RefData[RowStart + x]) >= maxabsdiff)
+            {
+              Ret = false;
+              return Ret;
+            }
+          }
+          RowStart += WidthStep;
+        }
+        return Ret;
+      }
+
+      unsigned char MEImage::GrayscalePixel(int x, int y) const
+      {
+        int NewX = x;
+        int NewY = y;
+
+        NewX = NewX < 0 ? 0 : NewX;
+        NewX = NewX > ME_CAST_TO_IPLIMAGE(cvImg)->width - 1 ? ME_CAST_TO_IPLIMAGE(cvImg)->width - 1 : NewX;
+        NewY = NewY < 0 ? 0 : NewY;
+        NewY = NewY > ME_CAST_TO_IPLIMAGE(cvImg)->height - 1 ? ME_CAST_TO_IPLIMAGE(cvImg)->height - 1 : NewY;
+
+        float Sum = 0;
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+
+        for (int l = 0; l < ME_CAST_TO_IPLIMAGE(cvImg)->nChannels; l++)
+        {
+          Sum = Sum + (int)ImageData[NewY*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + NewX*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + l];
+        }
+        Sum = Sum / ME_CAST_TO_IPLIMAGE(cvImg)->nChannels;
+        return (unsigned char)(Sum);
+      }
+
+      int MEImage::NeighbourhoodCounter(int startx, int starty,
+        NeighbourhoodType neighbourhood) const
+      {
+        int IterX = 0;
+        int IterY = 0;
+        int Counter = 0;
+
+        // Determine the iteration numbers
+        switch (neighbourhood)
+        {
+        case n_2x2:
+          IterX = 2;
+          IterY = 2;
+          break;
+
+        case n_3x3:
+          IterX = 3;
+          IterY = 3;
+          break;
+
+        case n_3x2:
+          IterX = 2;
+          IterY = 3;
+          break;
+
+        case n_5x5:
+          IterX = 5;
+          IterY = 5;
+          break;
+
+        case n_7x7:
+          IterX = 7;
+          IterY = 7;
+          break;
+
+        default:
+          IterX = 3;
+          IterY = 3;
+          break;
+        }
+
+        int NewStartX = startx;
+        int NewStartY = starty;
+
+        NewStartX = startx < 0 ? 0 : startx;
+        NewStartX = startx >= ME_CAST_TO_IPLIMAGE(cvImg)->width - IterX ? ME_CAST_TO_IPLIMAGE(cvImg)->width - IterX - 1 : startx;
+        NewStartY = starty < 0 ? 0 : starty;
+        NewStartY = starty >= ME_CAST_TO_IPLIMAGE(cvImg)->height - IterY ? ME_CAST_TO_IPLIMAGE(cvImg)->height - IterY - 1 : starty;
+
+        int Value = 0;
+        unsigned char* ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+
+        for (int x = NewStartX; x < NewStartX + IterX; x++)
+          for (int y = NewStartY; y < NewStartY + IterY; y++)
+          {
+            Value = ((int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels] +
+              (int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + 1] +
+              (int)ImageData[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels + 2]) / 3;
+
+            if (Value == 255)
+            {
+              Counter++;
+            }
+          }
+        return Counter;
+      }
+
+      void MEImage::GradientVector(bool smooth, int x, int y, int mask_size, int& result_x, int& result_y)
+      {
+        int Results[8];
+        int DiagonalMaskSize = (int)((float)mask_size / sqrtf(2));
+
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+        if (smooth)
+        {
+          SmoothAdvanced(s_Gaussian, mask_size * 3 - (mask_size * 3 - 1) % 2);
+        }
+
+        Results[0] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x, y - mask_size);
+        Results[1] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y - DiagonalMaskSize);
+        Results[2] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + mask_size, y);
+        Results[3] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y + DiagonalMaskSize);
+        Results[4] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x, y + mask_size);
+        Results[5] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x - DiagonalMaskSize, y + DiagonalMaskSize);
+        Results[6] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x - mask_size, y);
+        Results[7] = (int)GrayscalePixel(x, y) - (int)GrayscalePixel(x + DiagonalMaskSize, y - DiagonalMaskSize);
+
+        result_x = (DiagonalMaskSize*Results[1] + mask_size*Results[2] +
+          DiagonalMaskSize*Results[3] - DiagonalMaskSize*Results[5] -
+          mask_size*Results[6] + DiagonalMaskSize*Results[7]) / 256;
+        result_y = (-mask_size*Results[0] - DiagonalMaskSize*Results[1] +
+          DiagonalMaskSize*Results[3] + mask_size*Results[4] +
+          DiagonalMaskSize*Results[5] - DiagonalMaskSize*Results[7]) / 256;
+      }
+
+      void MEImage::GradientVisualize(int vector_x, int vector_y)
+      {
+        if (vector_x <= 0)
+        {
+          printf("vectorx: wrong parameter (%d <= 0)\n", vector_x);
+          return;
+        }
+        if (vector_y <= 0)
+        {
+          printf("vectory: wrong parameter (%d <= 0)\n", vector_y);
+          return;
+        }
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels > 1)
+        {
+          ConvertToGrayscale(g_OpenCV);
+        }
+
+        int masksize = (ME_CAST_TO_IPLIMAGE(cvImg)->width < ME_CAST_TO_IPLIMAGE(cvImg)->height) ?
+          ME_CAST_TO_IPLIMAGE(cvImg)->width / (vector_x + 1) :
+          ME_CAST_TO_IPLIMAGE(cvImg)->height / (vector_y + 1);
+
+        SmoothAdvanced(s_Gaussian, masksize * 2 - 1);
+        for (int i = 1; i < vector_x; i++)
+          for (int i1 = 1; i1 < vector_y; i1++)
+          {
+            int Resultx = 0, Resulty = 0;
+            int x = (int)(((float)ME_CAST_TO_IPLIMAGE(cvImg)->width*i / (vector_x)));
+            int y = (int)(((float)ME_CAST_TO_IPLIMAGE(cvImg)->height*i1 / (vector_y)));
+
+            GradientVector(false, x, y, (int)(0.707*masksize), Resultx, Resulty);
+
+            CvPoint Point1;
+            CvPoint Point2;
+
+            Point1.x = x - Resultx / 2;
+            Point1.y = y - Resulty / 2;
+            Point2.x = x + Resultx / 2;
+            Point2.y = y + Resulty / 2;
+            cvLine(ME_CAST_TO_IPLIMAGE(cvImg), Point1, Point2, CV_RGB_LEGACY(255, 255, 255), 1, 8);
+          }
+      }
+
+      bool MEImage::_Copy(const MEImage& other_image)
+      {
+        if (&other_image == this)
+          return true;
+
+        if (ME_CAST_TO_IPLIMAGE(cvImg))
+        {
+          ME_RELEASE_IPLIMAGE(cvImg);
+        }
+        cvImg = cvCloneImage((IplImage*)other_image.GetIplImage());
+        return true;
+      }
+
+      void MEImage::_Init(int width, int height, int layers)
+      {
+        if (width < 1)
+        {
+          printf("Given width for the new image is too small (%d <= 0)\n", width);
+          return;
+        }
+        if (height < 1)
+        {
+          printf("Given height for the new image is (%d <= 0)\n", height);
+          return;
+        }
+        if ((layers != 1) && (layers != 3))
+        {
+          printf("Only one or three (%d != 1 or 3) layer allowed\n", layers);
+          return;
+        }
+
+        if (ME_CAST_TO_IPLIMAGE(cvImg))
+        {
+          ME_RELEASE_IPLIMAGE(cvImg);
+        }
+        cvImg = cvCreateImage(cvSize(width, height), 8, layers);
+      }
+
+      void MEImage::ComputeColorSpace(ColorSpaceConvertType mode)
+      {
+        if (ME_CAST_TO_IPLIMAGE(cvImg)->nChannels != 3)
+        {
+          printf("Image has to have three color channels (%d != 3)\n", ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+          return;
+        }
+        IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8,
+          ME_CAST_TO_IPLIMAGE(cvImg)->nChannels);
+
+        for (int i = 0; i < 3; i++)
+          for (int i1 = 0; i1 < 3; i1++)
+          {
+            if (mode == csc_RGBtoYUV)
+              TransformMatrix[i][i1] = RGBtoYUVMatrix[i][i1];
+            if (mode == csc_RGBtoYIQ)
+              TransformMatrix[i][i1] = RGBtoYIQMatrix[i][i1];
+          }
+        float x = 0.0;
+        float y = 0.0;
+        float z = 0.0;
+        float xmin = 0.0;
+        float xmax = 0.0;
+        float ymin = 0.0;
+        float ymax = 0.0;
+        float zmin = 0.0;
+        float zmax = 0.0;
+
+        if (mode == csc_RGBtoYUV)
+        {
+          xmin = 0.0;
+          xmax = 255.0;
+          ymin = -111.18;
+          ymax = 111.18;
+          zmin = -156.825;
+          zmax = 156.825;
+        }
+        if (mode == csc_RGBtoYIQ)
+        {
+          xmin = 0.0;
+          xmax = 255.0;
+          ymin = -151.98;
+          ymax = 151.98;
+          zmin = -133.365;
+          zmax = 133.365;
+        }
+        unsigned char* SrcData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData;
+        unsigned char* DstData = (unsigned char*)TempImg->imageData;
+
+        for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; i -= 3)
+        {
+          x = (float)SrcData[i] * TransformMatrix[0][0] +
+            (float)SrcData[i + 1] * TransformMatrix[0][1] +
+            (float)SrcData[i + 2] * TransformMatrix[0][2];
+          y = (float)SrcData[i] * TransformMatrix[1][0] +
+            (float)SrcData[i + 1] * TransformMatrix[1][1] +
+            (float)SrcData[i + 2] * TransformMatrix[1][2];
+          z = (float)SrcData[i] * TransformMatrix[2][0] +
+            (float)SrcData[i + 1] * TransformMatrix[2][1] +
+            (float)SrcData[i + 2] * TransformMatrix[2][2];
+
+          x = xmax - xmin != 0.0 ? 255.0 : (x - xmin) / (xmax - xmin)*255.0;
+          y = ymax - ymin != 0.0 ? 255.0 : (y - xmin) / (ymax - ymin)*255.0;
+          z = zmax - zmin != 0.0 ? 255.0 : (z - xmin) / (zmax - zmin)*255.0;
+
+          DstData[i] = (unsigned char)MEBound(0, (int)x, 255);
+          DstData[i + 1] = (unsigned char)MEBound(0, (int)y, 255);
+          DstData[i + 2] = (unsigned char)MEBound(0, (int)z, 255);
+        }
+        ME_RELEASE_IPLIMAGE(cvImg);
+        cvImg = TempImg;
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MEImage.hpp b/src/algorithms/LBP_MRF/MEImage.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d9e079cb7b468e602c31689af4e799d1a85fd90
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MEImage.hpp
@@ -0,0 +1,988 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//#include <opencv2/opencv.hpp>
+//#include <opencv2/imgproc.hpp>
+
+// opencv legacy includes
+#include <opencv2/imgproc/imgproc_c.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      /**
+       * MEImage
+       * @brief Basic image functions
+       */
+      class MEImage
+      {
+      public:
+        /// Types of LBP operator
+        typedef enum {
+          lbp_Min = 0,          /*!< Minimum value */
+          lbp_Normal = lbp_Min, /*!< Normal LBP pattern */
+          lbp_Special,          /*!< Special LBP pattern */
+          lbp_Max = lbp_Special /*!< Maximum value */
+        } LBPType;
+
+        /// Types of image subtraction
+        typedef enum {
+          sub_Min = 0,          /*!< Minimum value */
+          sub_Normal = sub_Min, /*!< Normal */
+          sub_Absolut,          /*!< Absolut */
+          sub_Max = sub_Absolut /*!< Maximum value */
+        } SubtractModeType;
+
+        /// Types of image addition
+        typedef enum {
+          a_Min = 0,         /*!< Minimum value */
+          a_Average = a_Min, /*!< Average */
+          a_Union,           /*!< Union */
+          a_Max = a_Union    /*!< Maximum value */
+        } AdditionType;
+
+        /// Types of image multiplication
+        typedef enum {
+          m_Min = 0,              /*!< Minimum value */
+          m_Normal = m_Min,       /*!< Normal */
+          m_Neighbourhood,        /*!< Neighbourhood */
+          m_Max = m_Neighbourhood /*!< Maximum value */
+        } MultiplicationType;
+
+        /// Types of grayscale conversation
+        typedef enum {
+          g_Min = 0,         /*!< Minimum value */
+          g_Average = g_Min, /*!< Average */
+          g_OpenCV,          /*!< OpenCV */
+          g_Max = g_OpenCV   /*!< Maximum value */
+        } GrayscaleType;
+
+        /// Types of pixel neighbourhoods
+        typedef enum {
+          n_Min = 0,     /*!< Minimum value */
+          n_2x2 = n_Min, /*!< 2x2 */
+          n_3x2,         /*!< 3x2 */
+          n_3x3,         /*!< 3x3 */
+          n_5x5,         /*!< 5x5 */
+          n_7x7,         /*!< 7x7 */
+          n_Max = n_7x7  /*!< Maximum value */
+        } NeighbourhoodType;
+
+        /// Types of special pixels
+        typedef enum {
+          p_Min = 0,         /*!< Minimum value */
+          p_Minimum = p_Min, /*!< Minimum */
+          p_Maximum,         /*!< Maximum */
+          p_Counter,         /*!< Counter */
+          p_Max = p_Counter  /*!< Maximum value */
+        } PixelType;
+
+        /// Types of smooth operation
+        typedef enum {
+          s_Min = 0,       /*!< Minimum value */
+          s_Blur = s_Min,  /*!< Blur */
+          s_Gaussian,      /*!< Gaussian */
+          s_Median,        /*!< Medium */
+          s_Max = s_Median /*!< Maximum value */
+        } SmoothType;
+
+        /// Types of color space conversions
+        typedef enum {
+          csc_Min = 0,                  /*!< Minimum value */
+          csc_RGBtoXYZCIED65 = csc_Min, /*!< RGB to XYZCIED65 */
+          csc_XYZCIED65toRGB,           /*!< XYZCIED65 to RGB */
+          csc_RGBtoHSV,                 /*!< RGB to HSV */
+          csc_HSVtoRGB,                 /*!< HSV to RGB */
+          csc_RGBtoHLS,                 /*!< RGB to HLS */
+          csc_HLStoRGB,                 /*!< HLS to RGB */
+          csc_RGBtoCIELab,              /*!< RGB to CIELab */
+          csc_CIELabtoRGB,              /*!< CIELab to RGB */
+          csc_RGBtoCIELuv,              /*!< RGB to CIELuv */
+          csc_CIELuvtoRGB,              /*!< CIELuv to RGB */
+          csc_RGBtoYUV,                 /*!< RGB to YUV */
+          csc_RGBtoYIQ,                 /*!< RGB to YIQ */
+          csc_RGBtorgI,                 /*!< RGB to rgI */
+          csc_Max = csc_RGBtorgI        /*!< Maximum value */
+        } ColorSpaceConvertType;
+
+        /*!
+        * @brief Class constructor
+        *
+        * @param width Image width
+        * @param height Image height
+        * @param layers Layers
+        *
+        * Class constructor with the possibility to specify the image width,
+        * height and the layers. The default options are 16x16x1.
+        *
+        */
+
+        MEImage(int width = 16, int height = 16, int layers = 1);
+
+        /*!
+        * @brief Class constructor
+        *
+        * @param other Other image
+        *
+        * Class constructor with the possibility to specify the image width,
+        * height and the layers. The default options are 16x16x1.
+        *
+        */
+
+        MEImage(const MEImage& other);
+        /// Destructor of class
+        ~MEImage();
+
+        /*
+        -------------------------------------------------------------------
+                                Basic functions
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Clear image
+        *
+        * This function clears image by filling all image data with zero
+        * value.
+        *
+        */
+
+        void Clear();
+
+        /*!
+        * @brief Get an color layer of image
+        *
+        * @param new_layer new image of layer
+        * @param layernumber number of layer which will be copied
+        *
+        * Copy an image layer (R, G or B) to @a new_layer image. @a new_layer has to
+        * have only one color layer (greyscale). If @a new_layer is not
+        * greyscale or it has got different width or height like source image
+        * than function reallocates it with appropriate features before
+        * copying image data.
+        *
+        */
+
+        void GetLayer(MEImage& new_layer, int layernumber) const;
+
+        /*!
+        * @brief Copy a new color layer to image
+        *
+        * @param new_layer image data of new color layer
+        * @param layernumber number of layer where image data will copy
+        *
+        * Copy a new image layer from @a new_layer image. @a new_layer has to
+        * have only one color layer (greyscale). If @a new_layer is not
+        * greyscale or it has got different width or height like source image
+        * than function halts with an error message.
+        *
+        */
+
+        void SetLayer(MEImage& new_layer, int layernumber);
+
+        /*!
+        * @brief Copy image data to a pointer
+        *
+        * @param data pointer where image data will be copied
+        *
+        * Function in order to acquire image data to an external
+        * (unsigned char*) pointer.
+        *
+        */
+
+        void CopyImageData(unsigned char* data);
+
+        /*!
+        * @brief Get a pointer to the internal IplImage
+        *
+        * @return Pointer to the IplImage
+        *
+        * This function returns the internal IplImage of the class. The
+        * image data can not be modified.
+        *
+        */
+
+        void* GetIplImage() const;
+
+        /*!
+        * @brief Set the internal IplImage
+        *
+        * @param image Pointer to the IplImage
+        *
+        * This function sets the internal IplImage of the class.
+        *
+        */
+
+        void SetIplImage(void* image);
+
+        /*!
+        * @brief Handle operator == for MEImage
+        *
+        * @param image image to check
+        *
+        * @return true if the images are equal otherwise false.
+        *
+        * The operator checks the equality of two images.
+        *
+        */
+
+        bool operator==(const MEImage& image);
+
+        /*!
+        * @brief Handle operator != for MEImage
+        *
+        * @param image image to check
+        *
+        * @return true if the images are not equal otherwise false.
+        *
+        * The operator checks the non-equality of two images.
+        *
+        */
+
+        bool operator!=(const MEImage& image);
+
+        /*!
+        * @brief Handle operator = for MEImage
+        *
+        * @param other_image image to copy operation
+        *
+        * @return Reference to the actual instance.
+        *
+        * Copy image data to @a other_image image. Function calls only
+        * _Copy() directly.
+        *
+        */
+
+        MEImage& operator=(const MEImage& other_image);
+
+        /*!
+        * @brief Get the width of the image
+        *
+        * @return Width of the image
+        *
+        * Get the width of the image.
+        *
+        */
+
+        int GetWidth() const;
+
+        /*!
+        * @brief Get the height of the image
+        *
+        * @return Height of the image
+        *
+        * Get the height of the image.
+        */
+
+        int GetHeight() const;
+
+        /*!
+        * @brief Get the length of a pixel row of the image
+        *
+        * @return Length of a pixel row
+        *
+        * Get the row width of the image.
+        *
+        */
+
+        int GetRowWidth() const;
+
+        /*!
+        * @brief Get the number of color layers of the image
+        *
+        * @return Number of color layer of the image
+        *
+        * Get the number of color layer of the image.
+        *
+        */
+
+        int GetLayers() const;
+
+        /*!
+        * @brief Get the number of the image pixel data
+        *
+        * @return Number of the image pixel data
+        *
+        * Get the number of the image pixel data.
+        *
+        */
+
+        int GetPixelDataNumber() const;
+
+        /*!
+        * @brief Get the image data
+        *
+        * @return Pointer to the image data
+        *
+        * Get a pointer to the image.
+        *
+        */
+
+        unsigned char* GetImageData() const;
+
+        /*!
+        * @brief Set the image data
+        *
+        * @param image_data New image data
+        * @param width New image width
+        * @param height New image height
+        * @param channels New image color channels
+        *
+        * Get a pointer to the image.
+        *
+        */
+
+        void SetData(unsigned char* image_data, int width, int height, int channels);
+
+        /*!
+        * @brief Get ratio of image width and height
+        *
+        * @return float ratio of image dimensions
+        *
+        * Function calculates ratio of image width and height with
+        * following equation: ratio = height / width.
+        */
+
+        float GetRatio() const;
+
+        /*
+        -------------------------------------------------------------------
+                            Basic image manipulation
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Reallocate image data
+        *
+        * @param width New width of the image
+        * @param height New height of the image
+        *
+        * Image data will be reallocated with new dimensions @a width
+        * and @a height. Number of color channels is not changed.
+        *
+        */
+
+        void Realloc(int width, int height);
+
+        /*!
+        * @brief Reallocate image data
+        *
+        * @param width New width of the image
+        * @param height New height of the image
+        * @param layers Number of color channels of the image
+        *
+        * Image data will be reallocated with new dimensions @a width,
+        * @a height and new number of color channels @a layers.
+        *
+        */
+
+        void Realloc(int width, int height, int layers);
+
+        /*!
+        * @brief Resize image
+        *
+        * @param newwidth new width of image
+        * @param newheight new height of image
+        *
+        * Resize image to @a newwidth width and @a newheight
+        * height dimensions.
+        *
+        */
+
+        void Resize(int newwidth, int newheight);
+
+        /*!
+        * @brief Resize image with new width
+        *
+        * @param newwidth new width of image
+        *
+        * Image is resized with only new width information therefore
+        * fit to original ratio.
+        *
+        */
+
+        void ResizeScaleX(int newwidth);
+
+        /*!
+        * @brief Resize image with new height
+        *
+        * @param newheight new height of image
+        *
+        * Image is resized with only new height information therefore
+        * fit to original ratio.
+        *
+        */
+
+        void ResizeScaleY(int newheight);
+
+        /*!
+        * @brief Reverse image in horizontal direction
+        *
+        * Function makes a mirror transformation on image in horizontal
+        * direction.
+        *
+        */
+
+        void MirrorHorizontal();
+
+        /*!
+        * @brief Reverse image in vertical direction
+        *
+        * Function makes a mirror transformation on image in vertical
+        * direction.
+        *
+        */
+
+        void MirrorVertical();
+
+        /*!
+        * @brief Crop image
+        *
+        * @param x1, y1 coordinates of top-left point of rectangle
+        * @param x2, y2 coordinates of bottom-right point of rectangle
+        *
+        * Crop the image in a smaller piece whose dimensions are
+        * specified as a rectangle. Top-left and bottom-right
+        * coordinates of rectangle are (x1, y1) and (x2, y2) wherefrom
+        * comes that the width of the new image is x2-x1 and height is
+        * y2-y1.
+        *
+        */
+
+        void Crop(int x1, int y1, int x2, int y2);
+
+        /*!
+        * @brief Copy all image data from an other picture
+        *
+        * @param x0 x coordinate to paste the new image data
+        * @param y0 y coordinate to paste the new image data
+        * @param source_image source image
+        *
+        * Function copies all image data from @a source_image
+        * to the given coordinate (x0,y0).
+        *
+        */
+
+        void CopyImageInside(int x0, int y0, MEImage& source_image);
+
+        /*
+        -------------------------------------------------------------------
+                          Image processing functions
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Erode function
+        *
+        * @param iterations iterations of erode method
+        *
+        * Method makes an erode filter on an image @a iterations
+        * times with standard 3x3 matrix size.
+        *
+        */
+
+        void Erode(int iterations);
+
+        /*!
+        * @brief Dilate function
+        *
+        * @param iterations iterations of dilate method
+        *
+        * Method makes an dilate filter on an image
+        * @a iterations times with standard 3x3 matrix size.
+        *
+        */
+
+        void Dilate(int iterations);
+
+        /*!
+        * @brief Smooth function
+        *
+        * Method smooths with median filter and standard 3x3 matrix size.
+        * (Median filter works fine and fast.)
+        *
+        */
+
+        void Smooth();
+
+        /*!
+        * @brief Smooth function with defined parameters
+        *
+        * @param filtermode type of smooth method
+        * @param filtersize the size of the convolution matrix
+        *
+        * Method smooths with median filter and the given matrix
+        * size (@a filtersize x @a filtersize). There are more
+        * types of smooth function (@a filtermode):
+        *
+        * - s_Blur: Blur filter.
+        * - s_Gaussian: Gaussian filter.
+        * - s_Median: Median filter.
+        *
+        */
+
+        void SmoothAdvanced(SmoothType filtermode, int filtersize);
+
+        /*!
+        * @brief Canny function
+        *
+        * Canny operator is usable for edge detection. Function makes
+        * this operation with standard 3x3 matrix
+        * size. Canny has two threshold value which are set to zero
+        * in this function by default.
+        *
+        */
+
+        void Canny();
+
+        /*!
+        * @brief Laplace function
+        *
+        * Laplace operator is usable for edge detection like Canny.
+        * This function makes a laplace filter with
+        * standard 3x3 matrix size. After calculating destination image will
+        * be converted from 16 bit back to 8 bit.
+        *
+        */
+
+        void Laplace();
+
+        /*!
+        * @brief Image quantisation
+        *
+        * @param levels level of quantisation
+        *
+        * Quantize an image with @a levels level. It means by 16
+        * level color range 0-255 quantizes to 0-15, by 4 level to 0-63 etc.
+        *
+        */
+
+        void Quantize(int levels);
+
+        /*!
+        * @brief Threshold a picture
+        *
+        * @param threshold_limit limit for threshold
+        *
+        * Threshold an image with @a threshold_limit limit. Value range
+        * of @a threshold_limit is between 0-255. E.g. by value 160 functions
+        * will eliminate all color values under 160 with black color
+        * (color value zero).
+        *
+        */
+
+        void Threshold(int threshold_limit);
+
+        /*!
+        * @brief Adaptive threshold function
+        *
+        * This function does adaptive threshold function.
+        *
+        */
+
+        void AdaptiveThreshold();
+
+        /*!
+        * @brief Threshold a picture by a mask image
+        *
+        * @param mask_image mask image for thresholding
+        *
+        * Threshold an image with a mask image @a mask_image.
+        *
+        */
+
+        void ThresholdByMask(MEImage& mask_image);
+
+        /*!
+        * @brief Convert an image into a new color space
+        *
+        * @param transformation Definition of color transformation
+        *
+        * This function converts an image from a specified color space
+        * to an other.
+        * Current supported conversions (@a transformation):
+        * - csc_RGBtoXYZCIED65: RGB to XYZ (D65 reference light),
+        * - csc_XYZCIED65toRGB: XYZ to RGB (D65 reference light),
+        * - csc_RGBtoHSV: RGB to HSV,
+        * - csc_HSVtoRGB: HSV to RGB,
+        * - csc_RGBtoHLS: RGB to HSV,
+        * - csc_HLStoRGB: HSV to RGB,
+        * - csc_RGBtoCIELab: RGB to CIELab,
+        * - csc_CIELabtoRGB: CIELuv to RGB,
+        * - csc_RGBtoCIELuv: RGB to CIELuv,
+        * - csc_CIELuvtoRGB: CIELuv to RGB,
+        * - csc_RGBtoYUV: RGB to YUV color space,
+        * - csc_RGBtoYIQ: RGB to YIQ color space.
+        *
+        */
+
+        void ColorSpace(ColorSpaceConvertType transformation);
+
+        /*!
+        * @brief Convert an image to grayscale
+        *
+        * @param grayscale_mode mode of grayscale conversation
+        *
+        * The function converts the image to grayscale version
+        * (one color channel after the conversion). There is four
+        * different ways to convert the image to grayscale what we
+        * can define with @a grayscale_mode:
+        *
+        *  - g_Average: It computes the average grayscale
+        * values of the pixels with arithmetical average.
+        *  - g_OpenCV: It computes the average grayscale
+        * values by help of the values of the Y channel.
+        *
+        */
+
+        void ConvertToGrayscale(GrayscaleType grayscale_mode = g_OpenCV);
+
+        /*!
+        * @brief Convert a grayscale image to RGB
+        *
+        * The function converts the grayscale image to RGB version.
+        * (It copies the info from a single color channel to
+        * three color channel.)
+        *
+        */
+
+        void ConvertGrayscaleToRGB();
+
+        /*!
+        * @brief Change the red and blue components of every pixels
+        *
+        * Function changes the red component with the blue of
+        * every pixels. (Simple conversion from RGB->BGR.)
+        *
+        */
+
+        void ConvertBGRToRGB();
+
+        /*!
+        * @brief Compute an LBP filter on the image
+        *
+        * @param mode The LBP operator type
+        *
+        * The function converts the image to binary version over the
+        * threshold value.
+        *
+        */
+
+        void LBP(LBPType mode = lbp_Special);
+
+        /*!
+        * @brief Binarize an image
+        *
+        * @param threshold Threshold value
+        *
+        * The function converts the image to binary version over the
+        * threshold value.
+        *
+        */
+
+        void Binarize(int threshold);
+
+        /*!
+        * @brief Subtract an image from the internal picture
+        *
+        * @param source Source image for subtraction
+        * @param mode Calculation mode of difference feature
+        *
+        * Function generates a difference image between two image:
+        * the internal picture of this class and @a source_image.
+        * The calculation mode is determined by @a mode parameter.
+        * Function supports the following modes:
+        *
+        *  - sub_Normal: Simple subtraction between each
+        * correspondent pixel (per color channels). The result values
+        * are converted to absolute value and normalized to
+        * range 0-255.
+        *
+        */
+
+        void Subtract(MEImage& source, SubtractModeType mode);
+
+        /*!
+        * @brief Multiple an image with the internal picture
+        *
+        * @param source Second source image for multiplication
+        * @param mode Multiplication mode
+        *
+        * Function multiples an image with the internal image of this class and
+        * the result is stored in the internal image. The implemented calculation
+        * modes:
+        *
+        *  - m_Normal: It multiples the corresponding pixel values
+        * of the two images. The original pixel values are divided by 128 and
+        * multiplied together. If the result is at least 1 then the new pixel value
+        * is 255 otherwise 0.
+        *  - m_Neighbourhood: It multiples all pixel values of its
+        * 3x3 neighbourhood separately (see the method at MULTIPLICATION_NORMAL)
+        * and the new pixel value is 255 if at least two pixel is active in the
+        * 3x3 neighbourhood otherwise 0.
+        *
+        */
+
+        void Multiple(MEImage& source, MultiplicationType mode);
+
+        /*!
+        * @brief Addition of an image and the internal picture
+        *
+        * @param source second source image for addition method
+        * @param mode the declaration of the used addition mode
+        *
+        * Function makes an addition operation between an image and the internal
+        * image of this class and the result is stored in the internal image.
+        * Supported modes:
+        *
+        *  - a_Average: It sums the average of the corresponding pixels
+        * of each pictures.
+        *  - a_Union: It sums the union of the corresponding pixels
+        * of each pictures.
+        *
+        */
+
+        void Addition(MEImage& source, AdditionType mode);
+
+        /*!
+        * @brief Eliminate the single pixels from a binary image
+        *
+        * Function eliminates such a pixels which do not have neighbour pixels with
+        * 255 value in a 3x3 neighbourhood. The image should be converted to binary
+        * version.
+        *
+        */
+
+        void EliminateSinglePixels();
+
+        /*!
+        * @brief Calculate an area difference feature between two images
+        *
+        * @param reference Reference image
+        * @param difference Difference
+        *
+        * @return The percentage of image areas representing the conditions
+        *
+        * Function calculates a similarity feature between two pictures.
+        * Counts the number of the pixels whose intensity difference is
+        * higher than @a difference. (Range: 0..100)
+        *
+        */
+
+        float DifferenceAreas(MEImage& reference, int difference) const;
+
+        /*!
+        * @brief Calculate an average difference between two images
+        *
+        * @param reference Reference image
+        *
+        * @return Average difference of the pixels
+        *
+        * Function calculates a similarity feature between
+        * two images. It returns a simple sum of the absolute difference
+        * of each pixel in the two images and averaged by the pixel number.
+        * (Range: 0..255)
+        *
+        */
+
+        int AverageDifference(MEImage& reference) const;
+
+        /*!
+        * @brief Calculate minimum of image data
+        *
+        * @param image Second image
+        *
+        * Function calculates the minimum of current and given image.
+        *
+        */
+
+        void Minimum(MEImage& image);
+
+        /*!
+        * @brief Calculate average brightness level
+        *
+        * @return Brightness level in range 0-255.
+        *
+        * Function calculates the average brightness level of the image.
+        *
+        */
+
+        float AverageBrightnessLevel() const;
+
+        /*!
+        * @brief Check the equalization with a reference image
+        *
+        * @param reference Reference image
+        *
+        * @return true in case of binary equalization, otherwise false.
+        *
+        * Function calculates the binary difference between
+        * the image and the reference image.
+        *
+        */
+
+        bool Equal(const MEImage& reference) const;
+
+        /*!
+        * @brief Check the equalization with a reference image
+        *
+        * @param reference Reference image
+        * @param maxabsdiff Maximal absolute difference
+        *
+        * @return true in case of equalization, otherwise false.
+        *
+        * Function checks the difference between the image and
+        * the reference image. Two pixels are equal in a range of
+        * a maximal absolute difference.
+        *
+        */
+
+        bool Equal(const MEImage& reference, int maxabsdiff) const;
+
+        /*!
+        * @brief Get the grayscale value of a pixel
+        *
+        * @param x X coordinate of the pixel
+        * @param y Y coordinate of the pixel
+        *
+        * @return grayscale value of the pixel
+        *
+        * The method gives the grayscale value of a pixel back. If
+        * the image has 3 color channels (e.g. RGB) then Y value of
+        * YIQ/YUV color space will be calculated otherwise normal
+        * averaged grayscale value.
+        *
+        */
+
+        unsigned char GrayscalePixel(int x, int y) const;
+
+        /*!
+        * @brief Count the number of neighbourhood pixels with maximum intensity
+        *
+        * @param startx X coordinate of the top-left pixel
+        * @param starty Y coordinate of the top-left pixel
+        * @param neighbourhood Specific subset of pixels
+        *
+        * @return number of the pixels with maximum intensity.
+        *
+        * The method counts the number of the pixels with maximum
+        * intensity (255) in a specified subset of pixels.
+        * The grayscale values of the pixels are used in the counter
+        * process. The following neighbourhood forms are allowed with
+        * the @a neighbourhood parameter:
+        *
+        *  - n_2X2: Simple 2x2 matrix.
+        *  - n_3X3: Simple 3x3 matrix.
+        *  - n_3x2: Simple 3x2 matrix.
+        *
+        */
+
+        int NeighbourhoodCounter(int startx, int starty, NeighbourhoodType neighbourhood) const;
+
+        /*!
+        * @brief Calculate the gradient vector in a point
+        *
+        * @param smooth compute smooth filter
+        * @param x X coordinate of the point
+        * @param y Y coordinate of the point
+        * @param mask_size The mask size to calculate the gradient
+        *
+        * @param result_x X component of the calculated vector
+        * @param result_y Y component of the calculated vector
+        *
+        * The method calculates the gradient vector in a given point.
+        * The image is preprocessed with a Gauss filter to smooth the
+        * image content. The filter size of the Gauss filter depends on
+        * mask size of the gradient vector: filter size = mask size*3.
+        * Eight points are assigned to the initial point to compute
+        * a vector sum: (x, y-mask_size), (x+mask_size/√2, y-mask_size/√2),
+        * (x+mask_size, y), (x+mask_size/√2, y+mask_size/√2), (x, y+mask_size),
+        * (x-mask_size/√2, y+mask_size/√2), (x-mask_size, y), (x-mask_size/√2, y-mask_size/√2).
+        * The lengths of all vectors equalize with the mask size.
+        * After that each vector is multiplied with the gradient difference between
+        * its two end points. The results are summarized and normalized by
+        * the mask size.
+        *
+        */
+
+        void GradientVector(bool smooth, int x, int y, int mask_size, int& result_x, int& result_y);
+
+        /*!
+        * @brief Visualize gradient vectors
+        *
+        * @param vector_x Number of points horizontally
+        * @param vector_y Number of points vertically
+        *
+        * This function draws a wire (@a vector_x * @a vector_y) with
+        * gradient vectors.
+        *
+        */
+
+        void GradientVisualize(int vector_x, int vector_y);
+
+      private:
+
+        /*
+        -------------------------------------------------------------------
+                                Internal methods
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Copy image data
+        *
+        * @param other_image Input image with new image data
+        *
+        * @return true if it is successful, otherwise false.
+        *
+        * Copy image data from @a other_image to MEImage image data.
+        *
+        */
+
+        bool _Copy(const MEImage& other_image);
+
+        /*!
+        * @brief Inherent initialization function
+        *
+        * @param width Width of the image
+        * @param height Height of the image
+        * @param layer Number of color channels of the image
+        *
+        * Initialization function of MEImage class which allocates
+        * memory to internal MEImage image and sets its properties.
+        *
+        */
+
+        void _Init(int width, int height, int layer);
+
+        /*!
+        * @brief Compute an image to a different color space
+        *
+        * @param mode Mode of the conversion
+        *
+        * Currently, the internal function allows to use a few
+        * mode to convert an image between color spaces.
+        * Current supported conversions (@a mode):
+        * - RGBtoYUV: RGB to YUV color space,
+        * - RGBtoYIQ: RGB to YIQ color space.
+        *
+        */
+
+        void ComputeColorSpace(ColorSpaceConvertType mode);
+
+      private:
+        /// This matrix stores the matrix of the actual color space transform
+        float TransformMatrix[3][3];
+        /// The OpenCV image which contains the image data
+        void* cvImg;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MotionDetection.cpp b/src/algorithms/LBP_MRF/MotionDetection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..80ff513f40e031c9e554120bf4d0296f2a1f1127
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MotionDetection.cpp
@@ -0,0 +1,1472 @@
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "MotionDetection.hpp"
+
+#include "graph.h"
+#include "MEHistogram.hpp"
+#include "MEImage.hpp"
+
+//#if CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9
+//#define CV_RGB(r, g, b) cvScalar((b), (g), (r), 0)
+//#endif
+#define CV_RGB_LEGACY(r, g, b) cvScalar((b), (g), (r), 0)
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      // Pyramid picture for the tracking
+      IplImage *HUOFPyramid;
+      // Pyramid picture for the tracking
+      IplImage *HUOFPrevPyramid;
+
+      // Struct for histogram update data of a pixel
+      struct MEPixelDataType
+      {
+        float BackgroundRate;
+        int LifeCycle;
+        float *Weights;
+        bool *BackgroundHistogram;
+        float **Histograms;
+        float *PreviousHistogram;
+      };
+
+      MotionDetection::MotionDetection(DetectorType mode) :
+        MDMode(md_NotDefined), MDDataState(ps_Uninitialized), Frames(0), ReadyMask(false),
+        HUColorSpace(MEImage::csc_RGBtoCIELuv), HULBPMode(MEImage::lbp_Special),
+        HUHistogramsPerPixel(3), HUHistogramArea(5), HUHistogramBins(8),
+        HUImageWidth(-1), HUImageHeight(-1), HULBPPixelData(NULL),
+        HUPrThres(0.75), HUBackgrThres(0.95), HUHistLRate(0.01), HUWeightsLRate(0.01),
+        HUSamplePixels(-1), HUDesiredSamplePixels(-1), HUMinCutWeight(8.0),
+        HUOFDataState(ps_Uninitialized), HUOFPointsNumber(-1),
+        HUOFCamMovementX(0), MaxTrackedPoints(0), HUOFFrames(-1),
+        HUOFCamMovement(false)
+      {
+        HUOFPyramid = NULL;
+        HUOFPrevPyramid = NULL;
+        HUOFPoints[0] = NULL;
+        HUOFPoints[1] = NULL;
+        SetMode(mode);
+      }
+
+      MotionDetection::~MotionDetection()
+      {
+        if (MDMode != md_NotDefined)
+        {
+          ReleaseData();
+        }
+      }
+
+      void MotionDetection::SetMode(DetectorType newmode)
+      {
+        if (MDMode != md_NotDefined && MDMode != newmode)
+        {
+          ReleaseData();
+          Frames = 0;
+          HUOFFrames = -1;
+          HUOFCamMovement = false;
+          HUOFCamMovementX = 0;
+          ReadyMask = false;
+        }
+
+        switch (newmode)
+        {
+        case md_LBPHistograms:
+          MDMode = md_LBPHistograms;
+          break;
+
+        case md_DLBPHistograms:
+          MDMode = md_DLBPHistograms;
+          break;
+
+        default:
+          MDMode = md_LBPHistograms;
+          break;
+        }
+      }
+
+      float MotionDetection::GetParameter(ParametersType param) const
+      {
+        float ret = 0.0;
+
+        switch (param)
+        {
+        case mdp_HUProximityThreshold:
+          ret = (float)HUPrThres;
+          break;
+
+        case mdp_HUBackgroundThreshold:
+          ret = (float)HUBackgrThres;
+          break;
+
+        case mdp_HUHistogramLearningRate:
+          ret = (float)HUHistLRate;
+          break;
+
+        case mdp_HUWeightsLearningRate:
+          ret = (float)HUWeightsLRate;
+          break;
+
+        case mdp_HUMinCutWeight:
+          ret = (float)HUMinCutWeight;
+          break;
+
+        case mdp_HUDesiredSamplePixels:
+          ret = (float)HUDesiredSamplePixels;
+          break;
+
+        case mdp_HUHistogramsPerPixel:
+          ret = (float)HUHistogramsPerPixel;
+          break;
+
+        case mdp_HUHistogramArea:
+          ret = (float)HUHistogramArea;
+          break;
+
+        case mdp_HUHistogramBins:
+          ret = (float)HUHistogramBins;
+          break;
+
+        case mdp_HUColorSpace:
+          ret = (float)HUColorSpace;
+          break;
+
+        case mdp_HULBPMode:
+          ret = (float)HULBPMode;
+          break;
+
+        default:
+          break;
+        }
+        return ret;
+      }
+
+      void MotionDetection::SetParameter(ParametersType param, float value)
+      {
+        switch (param)
+        {
+        case mdp_HUProximityThreshold:
+          HUPrThres = (float)value;
+          break;
+
+        case mdp_HUBackgroundThreshold:
+          HUBackgrThres = (float)value;
+          break;
+
+        case mdp_HUHistogramLearningRate:
+          HUHistLRate = (float)value;
+          break;
+
+        case mdp_HUWeightsLearningRate:
+          HUWeightsLRate = (float)value;
+          break;
+
+        case mdp_HUMinCutWeight:
+          HUMinCutWeight = (float)value;
+          break;
+
+        case mdp_HUDesiredSamplePixels:
+          HUDesiredSamplePixels = (int)value;
+          break;
+
+        case mdp_HUHistogramsPerPixel:
+          HUHistogramsPerPixel = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramsPerPixel;
+          break;
+
+        case mdp_HUHistogramArea:
+          HUHistogramArea = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramArea;
+          break;
+
+        case mdp_HUHistogramBins:
+          HUHistogramBins = (MDDataState == ps_Uninitialized) ? (int)value : HUHistogramBins;
+          break;
+
+        case mdp_HUColorSpace:
+          HUColorSpace = (MDDataState == ps_Uninitialized) ? (int)value : HUColorSpace;
+          break;
+
+        case mdp_HULBPMode:
+          HULBPMode = (MDDataState == ps_Uninitialized) ? (int)value : HULBPMode;
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MotionDetection::DetectMotions(MEImage& image)
+      {
+        switch (MDMode)
+        {
+        case md_LBPHistograms:
+        case md_DLBPHistograms:
+          DetectMotionsHU(image);
+          break;
+
+        default:
+          break;
+        }
+      }
+
+      void MotionDetection::GetMotionsMask(MEImage& mask_image)
+      {
+        if (ReadyMask)
+        {
+          mask_image = MaskImage;
+        }
+
+        switch (MDMode)
+        {
+        case md_LBPHistograms:
+        case md_DLBPHistograms:
+          GetMotionsMaskHU(MaskImage);
+          break;
+
+        default:
+          break;
+        }
+
+        ReadyMask = true;
+        mask_image = MaskImage;
+      }
+
+      void MotionDetection::CalculateResults(MEImage& referenceimage, int& tnegatives, int& tpositives,
+        int& ttnegatives, int& ttpositives)
+      {
+        if (MDDataState != ps_Successful)
+        {
+          printf("No data for calculation.\n");
+          return;
+        }
+
+        if (referenceimage.GetLayers() != 1)
+          referenceimage.ConvertToGrayscale(MEImage::g_OpenCV);
+
+        referenceimage.Binarize(1);
+
+        MEImage mask_image;
+
+        GetMotionsMask(mask_image);
+
+        if ((mask_image.GetWidth() != referenceimage.GetWidth()) ||
+          (mask_image.GetHeight() != referenceimage.GetHeight()))
+        {
+          printf("Different resolutions of mask<->reference image.\n");
+          return;
+        }
+
+        unsigned char* RefMaskImgData = referenceimage.GetImageData();
+        unsigned char* MaskImgData = mask_image.GetImageData();
+        int RowStart = 0;
+        int RowWidth = referenceimage.GetRowWidth();
+
+        int TrueNegatives = 0;
+        int TruePositives = 0;
+        int TotalTrueNegatives = 0;
+        int TotalTruePositives = 0;
+
+        int ImageFrame = 0;
+
+        if (MDMode == md_LBPHistograms || md_DLBPHistograms)
+        {
+          ImageFrame = HUHistogramArea / 2;
+        }
+
+        for (int y = referenceimage.GetHeight() - ImageFrame - 1; y >= ImageFrame; --y)
+        {
+          for (int x = referenceimage.GetWidth() - ImageFrame - 1; x >= ImageFrame; --x)
+          {
+            TrueNegatives +=
+              (RefMaskImgData[RowStart + x] == 0) &&
+              (MaskImgData[RowStart + x] == 0);
+            TotalTrueNegatives += (RefMaskImgData[RowStart + x] == 0);
+            TruePositives +=
+              (RefMaskImgData[RowStart + x] == 255) &&
+              (MaskImgData[RowStart + x] == 255);
+            TotalTruePositives += (RefMaskImgData[RowStart + x] == 255);
+          }
+          RowStart += RowWidth;
+        }
+
+        tnegatives = TrueNegatives;
+        ttnegatives = TotalTrueNegatives;
+        tpositives = TruePositives;
+        ttpositives = TotalTruePositives;
+      }
+
+      void MotionDetection::ReleaseData()
+      {
+        if (MDMode == md_LBPHistograms || MDMode == md_DLBPHistograms)
+        {
+          ReleaseHUData();
+        }
+      }
+
+      void MotionDetection::InitHUData(int imagewidth, int imageheight)
+      {
+        if ((HUImageWidth != imagewidth - HUHistogramArea + 1) ||
+          (HUImageHeight != imageheight - HUHistogramArea + 1) ||
+          (MDDataState == ps_Uninitialized))
+        {
+          if (MDDataState != ps_Uninitialized)
+          {
+            ReleaseHUData();
+          }
+
+          MDDataState = ps_Initialized;
+
+          HUImageWidth = imagewidth - HUHistogramArea + 1;
+          HUImageHeight = imageheight - HUHistogramArea + 1;
+
+          HULBPPixelData = new MEPixelDataType**[HUImageWidth / 2];
+
+          for (int i = 0; i < HUImageWidth / 2; ++i)
+          {
+            HULBPPixelData[i] = new MEPixelDataType*[HUImageHeight];
+          }
+
+          for (int i = 0; i < HUImageWidth / 2; ++i)
+            for (int i1 = 0; i1 < HUImageHeight; ++i1)
+            {
+              HULBPPixelData[i][i1] = new MEPixelDataType;
+              HULBPPixelData[i][i1]->Weights = new float[HUHistogramsPerPixel];
+              HULBPPixelData[i][i1]->BackgroundHistogram = new bool[HUHistogramsPerPixel];
+              HULBPPixelData[i][i1]->Histograms = new float*[HUHistogramsPerPixel];
+              for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                HULBPPixelData[i][i1]->Histograms[i2] = new float[HUHistogramBins];
+              HULBPPixelData[i][i1]->PreviousHistogram = new float[HUHistogramBins];
+            }
+
+          // Allocate auxiliary variables
+          HUMaskColumnAddDel = new int*[HUHistogramArea];
+          for (int i = 0; i < HUHistogramArea; ++i)
+            HUMaskColumnAddDel[i] = new int[2];
+
+          HUMaskRowAddDel = new int*[HUHistogramArea];
+          for (int i = 0; i < HUHistogramArea; ++i)
+            HUMaskRowAddDel[i] = new int[2];
+
+          // Generate sample mask
+          SetSampleMaskHU(sm_Circle, HUDesiredSamplePixels);
+
+          // Init HU optical flow data
+          if (MDMode == md_DLBPHistograms)
+            InitHUOFData(imagewidth, imageheight);
+
+          ClearHUData();
+        }
+      }
+
+      void MotionDetection::InitHUOFData(int imagewidth, int imageheight)
+      {
+        if (HUOFDataState != ps_Uninitialized)
+        {
+          ReleaseHUOFData();
+        }
+
+        if (HUOFDataState == ps_Uninitialized)
+        {
+          HUOFPointsNumber = imagewidth*imageheight / 1000;
+          HUOFPyramid = cvCreateImage(cvSize(imagewidth, imageheight), 8, 1);
+          HUOFPrevPyramid = cvCreateImage(cvSize(imagewidth, imageheight), 8, 1);
+          HUOFPoints[0] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[0][0]));
+          HUOFPoints[1] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[1][0]));
+        }
+      }
+
+      void MotionDetection::ReleaseHUData()
+      {
+        if (MDDataState != ps_Uninitialized)
+        {
+          for (int i = 0; i < HUImageWidth / 2; i++)
+            for (int i1 = 0; i1 < HUImageHeight; i1++)
+            {
+              delete[] HULBPPixelData[i][i1]->PreviousHistogram;
+              for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                delete[] HULBPPixelData[i][i1]->Histograms[i2];
+              delete[] HULBPPixelData[i][i1]->Histograms;
+              delete[] HULBPPixelData[i][i1]->BackgroundHistogram;
+              delete[] HULBPPixelData[i][i1]->Weights;
+              delete HULBPPixelData[i][i1];
+            }
+
+          for (int i = 0; i < HUImageWidth / 2; i++)
+          {
+            delete[] HULBPPixelData[i];
+          }
+          delete[] HULBPPixelData;
+
+          if (MDMode == md_DLBPHistograms)
+            ReleaseHUOFData();
+
+          HUImageWidth = -1;
+          HUImageHeight = -1;
+          HULBPPixelData = NULL;
+          MDDataState = ps_Uninitialized;
+
+          // Release auxiliary variables
+          for (int i = 0; i < HUHistogramArea; ++i)
+            delete[] HUMaskColumnAddDel[i];
+          delete[] HUMaskColumnAddDel;
+
+          for (int i = 0; i < HUHistogramArea; ++i)
+            delete[] HUMaskRowAddDel[i];
+          delete[] HUMaskRowAddDel;
+
+          HUMaskColumnAddDel = NULL;
+          HUMaskRowAddDel = NULL;
+        }
+      }
+
+      void MotionDetection::ReleaseHUOFData()
+      {
+        if (MDDataState != ps_Uninitialized)
+        {
+          if (HUOFPyramid)
+          {
+            cvReleaseImage(&HUOFPyramid);
+            HUOFPyramid = NULL;
+          }
+          if (HUOFPrevPyramid)
+          {
+            cvReleaseImage(&HUOFPrevPyramid);
+            HUOFPrevPyramid = NULL;
+          }
+          if (HUOFPoints[0])
+          {
+            cvFree(&HUOFPoints[0]);
+            HUOFPoints[0] = NULL;
+          }
+          if (HUOFPoints[1])
+          {
+            cvFree(&HUOFPoints[1]);
+            HUOFPoints[1] = NULL;
+          }
+          HUOFDataState = ps_Uninitialized;
+        }
+      }
+
+      void MotionDetection::ClearHUData()
+      {
+        if (MDDataState != ps_Uninitialized)
+        {
+          for (int i = (HUImageWidth / 2) - 1; i >= 0; --i)
+            for (int i1 = HUImageHeight - 1; i1 >= 0; --i1)
+            {
+              for (int i2 = HUHistogramsPerPixel - 1; i2 >= 0; --i2)
+              {
+                memset(HULBPPixelData[i][i1]->Histograms[i2], 0,
+                  HUHistogramBins * sizeof(float));
+                HULBPPixelData[i][i1]->Weights[i2] = 1.0 / HUHistogramsPerPixel;
+                HULBPPixelData[i][i1]->BackgroundHistogram[i2] = true;
+              }
+              HULBPPixelData[i][i1]->BackgroundRate = 1.0;
+              HULBPPixelData[i][i1]->LifeCycle = 0;
+            }
+          MDDataState = ps_Initialized;
+        }
+      }
+
+      void MotionDetection::DetectMotionsHU(MEImage& image)
+      {
+        unsigned char *ImgData = NULL;
+        MEImage newimage = image;
+        float DiffAreas = 0;
+
+        // Init the histogram update data structures if needs be
+        if ((MDDataState == ps_Uninitialized) ||
+          (HUImageWidth != newimage.GetWidth() - HUHistogramArea + 1) ||
+          (HUImageHeight != newimage.GetHeight() - HUHistogramArea + 1))
+        {
+          InitHUData(newimage.GetWidth(), newimage.GetHeight());
+        }
+
+        if (newimage.GetLayers() == 1)
+        {
+          newimage.ConvertGrayscaleToRGB();
+        }
+
+        MEImage blueimage = newimage;
+        blueimage.ColorSpace(MEImage::csc_RGBtoCIELuv);
+
+        if (HUColorSpace != -1)
+        {
+          newimage.ColorSpace((MEImage::ColorSpaceConvertType)HUColorSpace);
+        }
+
+        if (Frames == 0)
+        {
+          MEImage BlueLayer;
+          blueimage.GetLayer(BlueLayer, 1);
+          BlueLayer.Resize(32, 24);
+          PreviousBlueLayer = BlueLayer;
+        }
+
+        Frames++;
+
+        // Detect the fast, big changes in the scene
+        MEImage BlueLayer;
+        blueimage.GetLayer(BlueLayer, 1);
+        BlueLayer.Resize(32, 24);
+        DiffAreas = BlueLayer.DifferenceAreas(PreviousBlueLayer, 12);
+
+        if (DiffAreas > 80)
+        {
+          MDDataState = ps_Initialized;
+          if (MDMode == md_DLBPHistograms)
+            HUOFDataState = ps_Initialized;
+          printf("Frame: %d - big changes in the scene (%f)", Frames, DiffAreas);
+          Frames = 1;
+          HUOFFrames = -1;
+        }
+        PreviousBlueLayer = BlueLayer;
+
+        if (Frames == 1)
+        {
+          CurrentImage = image;
+          PreviousImage = CurrentImage;
+        }
+        else
+          if (Frames > 1)
+          {
+            PreviousImage = CurrentImage;
+            CurrentImage = image;
+            // Optical flow correction of the camera movements
+            if (MDMode == md_DLBPHistograms)
+            {
+              OpticalFlowCorrection();
+            }
+          }
+
+        newimage.ConvertToGrayscale(MEImage::g_OpenCV);
+
+        if (HULBPMode != -1)
+        {
+          newimage.LBP((MEImage::LBPType)HULBPMode);
+        }
+
+        // Set some auxiliary variables
+        ImgData = newimage.GetImageData();
+        int DivisionOperator = (int)(log((double)256 / HUHistogramBins) / log((double) 2.)) + 1;
+
+        // Downscale the image
+        for (int i = newimage.GetRowWidth()*newimage.GetHeight() - 1; i >= 0; --i)
+        {
+          ImgData[i] >>= DivisionOperator;
+        }
+
+        UpdateModelHU(newimage, HULBPPixelData);
+
+        // Change the state of the HU data structures
+        if (MDDataState == ps_Initialized)
+        {
+          MDDataState = ps_Successful;
+        }
+        HUOFCamMovement = false;
+        ReadyMask = false;
+      }
+
+      void MotionDetection::UpdateModelHU(MEImage& image, MEPixelDataType*** model)
+      {
+        float *CurrentHistogram = new float[HUHistogramBins];
+        float *CurrentHistogram2 = new float[HUHistogramBins];
+        unsigned char *ImgData = image.GetImageData();
+        int RowWidth = image.GetRowWidth();
+        int RowStart = (HUImageHeight - 1)*RowWidth;
+
+        memset(CurrentHistogram, 0, HUHistogramBins * sizeof(float));
+        // Calculate the first histogram
+        for (int y = HUHistogramArea - 1; y >= 0; --y)
+        {
+          for (int x = HUHistogramArea - 1; x >= 0; --x)
+          {
+            if ((HUMaskRowAddDel[y][1] > x) && (HUMaskRowAddDel[y][0] <= x) &&
+              (HUMaskColumnAddDel[x][1] > y) && (HUMaskColumnAddDel[x][0] <= y))
+            {
+              CurrentHistogram[ImgData[RowStart + HUImageWidth - 1 + x]]++;
+            }
+          }
+          RowStart += RowWidth;
+        }
+
+        // This cycle generates the last row of histograms
+        for (int y = HUImageHeight - 1; y >= 0; --y)
+        {
+          if (HUImageHeight - 1 > y)
+          {
+            // Delete and add a pixel column from the histogram data
+            for (int i = HUHistogramArea - 1; i >= 0; --i)
+            {
+              if (HUMaskColumnAddDel[i][0] != -1)
+                CurrentHistogram[ImgData[RowWidth*(y + HUMaskColumnAddDel[i][0]) + HUImageWidth - 1 + i]]++;
+              if (HUMaskColumnAddDel[i][1] != -1)
+                CurrentHistogram[ImgData[RowWidth*(y + HUMaskColumnAddDel[i][1]) + HUImageWidth - 1 + i]]--;
+            }
+          }
+
+          if (y % 2 == HUImageWidth % 2)
+          {
+            MEPixelDataType* PixelData = model[(HUImageWidth - 1) / 2][y];
+
+            // Allocate and initialize the pixel data if needs be
+            if (!PixelData)
+            {
+              // Memory allocation
+              PixelData = new MEPixelDataType;
+              PixelData->Weights = new float[HUHistogramsPerPixel];
+              PixelData->BackgroundHistogram = new bool[HUHistogramsPerPixel];
+              PixelData->Histograms = new float*[HUHistogramsPerPixel];
+              for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                PixelData->Histograms[i2] = new float[HUHistogramBins];
+              PixelData->PreviousHistogram = new float[HUHistogramBins];
+
+              for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+              {
+                memcpy(PixelData->Histograms[i], CurrentHistogram, HUHistogramBins * sizeof(float));
+                PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
+                PixelData->BackgroundHistogram[i] = true;
+              }
+              PixelData->BackgroundRate = 1.0;
+              PixelData->LifeCycle = 0;
+              memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
+
+              model[(HUImageWidth - 1) / 2][y] = PixelData;
+            }
+            else {
+              bool InitHistograms = (MDDataState == ps_Initialized);
+
+              if (MDDataState != ps_Initialized && HUOFCamMovement)
+              {
+                // Histogram intersection between the previous and the current histogram
+                float Difference = 0.0;
+                for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
+                {
+                  Difference += (float)(CurrentHistogram[i1] < PixelData->PreviousHistogram[i1] ?
+                    CurrentHistogram[i1] : PixelData->PreviousHistogram[i1]);
+                }
+                Difference /= HUSamplePixels;
+
+                if (Difference < HUBackgrThres)
+                  InitHistograms = true;
+              }
+              if (InitHistograms)
+              {
+                // Copy the histogram data to the HU data structures
+                for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+                {
+                  memcpy(PixelData->Histograms[i], CurrentHistogram, HUHistogramBins * sizeof(float));
+                  PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
+                  PixelData->BackgroundHistogram[i] = true;
+                }
+                memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
+                PixelData->BackgroundRate = 1.0;
+                PixelData->LifeCycle = 0;
+              }
+              else {
+                // Update the HU data structures
+                UpdateHUPixelData(PixelData, CurrentHistogram);
+
+                if (MDMode == md_DLBPHistograms)
+                {
+                  memcpy(PixelData->PreviousHistogram, CurrentHistogram, HUHistogramBins * sizeof(float));
+                }
+              }
+            }
+          }
+
+          // Copy the histogram
+          memcpy(CurrentHistogram2, CurrentHistogram, HUHistogramBins * sizeof(float));
+
+          // This cycle generates a column of histograms
+          for (int x = HUImageWidth - 2; x >= 0; --x)
+          {
+            RowStart = RowWidth*y;
+
+            // Delete and add a pixel column from the histogram data
+            for (int i = HUHistogramArea - 1; i >= 0; --i)
+            {
+              if (HUMaskRowAddDel[i][0] != -1)
+                CurrentHistogram2[ImgData[RowStart + x + HUMaskRowAddDel[i][0]]]++;
+              if (HUMaskRowAddDel[i][1] != -1)
+                CurrentHistogram2[ImgData[RowStart + x + HUMaskRowAddDel[i][1]]]--;
+
+              RowStart += RowWidth;
+            }
+            if (x % 2 == 0)
+            {
+              MEPixelDataType* PixelData = model[x / 2][y];
+
+              // Allocate and initialize the pixel data if needs be
+              if (!PixelData)
+              {
+                // Memory allocation
+                PixelData = new MEPixelDataType;
+                PixelData->Weights = new float[HUHistogramsPerPixel];
+                PixelData->BackgroundHistogram = new bool[HUHistogramsPerPixel];
+                PixelData->Histograms = new float*[HUHistogramsPerPixel];
+                for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                  PixelData->Histograms[i2] = new float[HUHistogramBins];
+                PixelData->PreviousHistogram = new float[HUHistogramBins];
+
+                for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+                {
+                  memcpy(PixelData->Histograms[i], CurrentHistogram2, sizeof(CurrentHistogram2));
+                  PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
+                  PixelData->BackgroundHistogram[i] = true;
+                }
+                PixelData->BackgroundRate = 1.0;
+                PixelData->LifeCycle = 0;
+                model[x / 2][y] = PixelData;
+                memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
+              }
+              else {
+                bool InitHistograms = (MDDataState == ps_Initialized);
+
+                if (MDDataState != ps_Initialized && HUOFCamMovement)
+                {
+                  // Histogram intersection between the previous and the current histogram
+                  float Difference = 0.0;
+                  for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
+                  {
+                    Difference += (float)(CurrentHistogram2[i1] < PixelData->PreviousHistogram[i1] ?
+                      CurrentHistogram2[i1] : PixelData->PreviousHistogram[i1]);
+                  }
+                  Difference /= HUSamplePixels;
+
+                  if (Difference < HUBackgrThres)
+                    InitHistograms = true;
+                }
+                if (InitHistograms)
+                {
+                  // Copy the histogram data to the HU data structures
+                  for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+                  {
+                    memcpy(PixelData->Histograms[i], CurrentHistogram2, sizeof(CurrentHistogram2));
+                    PixelData->Weights[i] = 1.0 / HUHistogramsPerPixel;
+                    PixelData->BackgroundHistogram[i] = true;
+                  }
+                  memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
+                  PixelData->BackgroundRate = 1.0;
+                  PixelData->LifeCycle = 0;
+                }
+                else {
+                  // Update the HU data structures
+                  UpdateHUPixelData(PixelData, CurrentHistogram2);
+
+                  if (MDMode == md_DLBPHistograms)
+                  {
+                    memcpy(PixelData->PreviousHistogram, CurrentHistogram2, sizeof(CurrentHistogram2));
+                  }
+                }
+              }
+            }
+
+          }
+        }
+        delete[] CurrentHistogram;
+        delete[] CurrentHistogram2;
+      }
+
+      void MotionDetection::UpdateHUPixelData(MEPixelDataType* PixelData, const float *histogram)
+      {
+        int MaxIndex = 0;
+        float MaxValue = -1;
+        bool Replace = true;
+        float *IntersectionResults = new float[HUHistogramsPerPixel];
+
+        PixelData->LifeCycle++;
+        PixelData->BackgroundRate = 0.0;
+
+        // Compute intersection between the currect and older histograms
+        for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+        {
+          // Histogram intersection
+          float Difference = 0.0;
+          for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
+          {
+            Difference += (float)histogram[i1] < PixelData->Histograms[i][i1] ?
+              (float)histogram[i1] : PixelData->Histograms[i][i1];
+          }
+
+          IntersectionResults[i] = (float)Difference / (float)(HUSamplePixels);
+
+          if (PixelData->BackgroundHistogram[i] &&
+            IntersectionResults[i] > PixelData->BackgroundRate)
+          {
+            PixelData->BackgroundRate = IntersectionResults[i];
+          }
+
+          if (MaxValue < IntersectionResults[i])
+          {
+            MaxValue = IntersectionResults[i];
+            MaxIndex = i;
+          }
+
+          Replace = Replace && (IntersectionResults[i] < HUPrThres);
+        }
+
+        // Replace the histogram with the lowest weight
+        if (Replace)
+        {
+          // Find the histogram with minimal weight
+          int MinIndex = 0;
+          float MinValue = PixelData->Weights[0];
+          for (int i1 = HUHistogramsPerPixel - 1; i1 > 0; --i1)
+          {
+            if (MinValue > PixelData->Weights[i1])
+            {
+              MinValue = PixelData->Weights[i1];
+              MinIndex = i1;
+            }
+          }
+
+          PixelData->Weights[MinIndex] = 0.01;
+          for (int i1 = HUHistogramBins - 1; i1 >= 0; --i1)
+            PixelData->Histograms[MinIndex][i1] = (float)histogram[i1];
+          PixelData->BackgroundHistogram[MinIndex] = 0;
+
+          // Normalize the weights
+          float sum = 0;
+          for (int i1 = HUHistogramsPerPixel - 1; i1 >= 0; --i1)
+            sum += PixelData->Weights[i1];
+
+          for (int i1 = HUHistogramsPerPixel - 1; i1 >= 0; --i1)
+            PixelData->Weights[i1] = PixelData->Weights[i1] / sum;
+
+          return;
+        }
+
+        float LearningRate = HUHistLRate;
+
+        if (PixelData->LifeCycle < 100)
+          LearningRate += (float)(100 - PixelData->LifeCycle) / 100;
+        else
+          if (MDMode == md_DLBPHistograms && HUOFFrames != -1 && HUOFFrames < 40)
+            LearningRate += (HUOFFrames < 80 ? 0.05 : 0);
+
+        // Match was found -> Update the histogram of the best match
+        for (int i = HUHistogramBins - 1; i >= 0; --i)
+        {
+          PixelData->Histograms[MaxIndex][i] *= (1.0 - LearningRate);
+          PixelData->Histograms[MaxIndex][i] += LearningRate*(float)histogram[i];
+        }
+
+        LearningRate = HUWeightsLRate;
+        if (PixelData->LifeCycle < 100)
+          LearningRate += (float)(100 - PixelData->LifeCycle) / 100;
+        else
+          if (MDMode == md_DLBPHistograms && HUOFFrames != -1 && HUOFFrames < 40)
+            LearningRate += (HUOFFrames < 80 ? 0.05 : 0);
+
+        // Update the weights of the histograms
+        for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+        {
+          PixelData->Weights[i] =
+            (LearningRate*(i == MaxIndex) + (1.0 - LearningRate)*PixelData->Weights[i]);
+        }
+
+        // Order and select the background histograms
+        float **Weights = new float*[HUHistogramsPerPixel];
+        for (int i = 0; i < HUHistogramsPerPixel; ++i)
+          Weights[i] = new float[2];
+
+        for (int i = HUHistogramsPerPixel - 1; i >= 0; --i)
+        {
+          Weights[i][0] = (float)i;
+          Weights[i][1] = PixelData->Weights[i];
+        }
+
+        for (int i1 = HUHistogramsPerPixel - 1; i1 >= 2; --i1)
+          for (int i = i1; i >= 1; --i)
+          {
+            if (Weights[i][1] <= Weights[i - 1][1])
+            {
+              float tmp = Weights[i][0];
+              float tmp2 = Weights[i][1];
+
+              Weights[i][0] = Weights[i - 1][0];
+              Weights[i][1] = Weights[i - 1][1];
+
+              Weights[i - 1][0] = tmp;
+              Weights[i - 1][1] = tmp2;
+            }
+          }
+
+        float Sum = 0;
+        int i = 0;
+
+        for (i = HUHistogramsPerPixel - 1; i >= 0; --i)
+        {
+          Sum += Weights[i][1];
+          PixelData->BackgroundHistogram[(int)Weights[i][0]] = true;
+
+          if (Sum > HUBackgrThres)
+            break;
+        }
+        for (int i1 = i - 1; i1 >= 0; --i1)
+        {
+          PixelData->BackgroundHistogram[(int)Weights[i1][0]] = false;
+        }
+        delete[] IntersectionResults;
+        for (int i = 0; i < HUHistogramsPerPixel; ++i)
+          delete[] Weights[i];
+        delete[] Weights;
+      }
+
+      void MotionDetection::OpticalFlowCorrection()
+      {
+        IplImage *PreviousGray = NULL, *CurrentGray = NULL;
+        char* PointsStatus = (char*)cvAlloc(HUOFPointsNumber);
+        int i = 0, i1 = 0;
+
+        if (HUOFFrames != -1)
+          HUOFFrames++;
+
+        // Convert the images into grayscale
+        if (CurrentImage.GetLayers() > 1)
+        {
+          CurrentGray = cvCreateImage(cvGetSize(CurrentImage.GetIplImage()), IPL_DEPTH_8U, 1);
+          cvCvtColor(CurrentImage.GetIplImage(), CurrentGray, CV_BGR2GRAY);
+        }
+        else
+          CurrentGray = (IplImage*)CurrentImage.GetIplImage();
+        if (PreviousImage.GetLayers() > 1)
+        {
+          PreviousGray = cvCreateImage(cvGetSize(CurrentImage.GetIplImage()), IPL_DEPTH_8U, 1);
+          cvCvtColor(PreviousImage.GetIplImage(), PreviousGray, CV_BGR2GRAY);
+        }
+        else
+          PreviousGray = (IplImage*)PreviousImage.GetIplImage();
+
+        if (HUOFDataState != ps_Successful)
+        {
+          printf("Search new corners\n");
+          IplImage* TempEig = cvCreateImage(cvGetSize(CurrentGray), 32, 1);
+          IplImage* Temp = cvCreateImage(cvGetSize(CurrentGray), 32, 1);
+          double MinDistance = (CurrentImage.GetWidth() + CurrentImage.GetHeight()) / 20;
+          HUOFPointsNumber = MaxTrackedPoints = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
+
+          // Search good trackable points
+          cvGoodFeaturesToTrack(PreviousGray, TempEig, Temp,
+            (CvPoint2D32f*)HUOFPoints[0], &HUOFPointsNumber,
+            0.01, MinDistance, NULL, 3);
+          MaxTrackedPoints = HUOFPointsNumber;
+          // Release temporary images
+          cvReleaseImage(&TempEig);
+          cvReleaseImage(&Temp);
+          // Realloc the point status array
+          if (PointsStatus)
+          {
+            cvFree(&PointsStatus);
+            PointsStatus = NULL;
+          }
+
+          if (MaxTrackedPoints < 2)
+          {
+            HUOFDataState = ps_Initialized;
+            HUOFPointsNumber = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
+            return;
+          }
+          else
+            HUOFDataState = ps_Successful;
+          PointsStatus = (char*)cvAlloc(HUOFPointsNumber);
+        }
+
+        cvCalcOpticalFlowPyrLK(PreviousGray, CurrentGray, HUOFPrevPyramid, HUOFPyramid,
+          HUOFPoints[0], HUOFPoints[1], HUOFPointsNumber,
+          cvSize(10, 10), 3, PointsStatus, NULL,
+          cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 5, 1), 0);
+
+        // Count the distances of the tracked points
+        int **Distances = new int*[HUOFPointsNumber];
+        for (int i = 0; i < HUOFPointsNumber; ++i)
+          Distances[i] = new int[3];
+
+        int DistanceMax = 0;
+        for (i = 0; i < HUOFPointsNumber; ++i)
+        {
+          int DiffX = (int)MERound(HUOFPoints[1][i].x - HUOFPoints[0][i].x);
+          int DiffY = (int)MERound(HUOFPoints[1][i].y - HUOFPoints[0][i].y);
+          if ((PointsStatus[i] == 1) && !((DiffX == 0) && (DiffY == 0)))
+          {
+            bool found = false;
+            // Create a list from the differences to count them
+            for (i1 = 0; i1 < DistanceMax; ++i1)
+            {
+              if ((Distances[i1][0] == DiffX) &&
+                (Distances[i1][1] == DiffY))
+              {
+                Distances[i1][2]++;
+                found = true;
+                break;
+              }
+            }
+            if ((!found) && !((DiffX == 0) && (DiffY == 0)))
+            {
+              Distances[DistanceMax][0] = (int)MERound(HUOFPoints[1][i].x - HUOFPoints[0][i].x);
+              Distances[DistanceMax][1] = (int)MERound(HUOFPoints[1][i].y - HUOFPoints[0][i].y);
+              Distances[DistanceMax][2] = 1;
+              DistanceMax++;
+            }
+          }
+        }
+
+        // Sort the results
+        for (int i1 = DistanceMax - 1; i1 >= 2; --i1)
+        {
+          for (int i = i1; i >= 1; --i)
+          {
+            if ((Distances[i][2] > Distances[i - 1][2]) ||
+              ((Distances[i][2] == Distances[i - 1][2]) &&
+              (abs(Distances[i][0]) + abs(Distances[i][1]) <
+                abs(Distances[i - 1][0]) + abs(Distances[i - 1][1]))))
+            {
+              int tmp = Distances[i][0];
+              int tmp2 = Distances[i][1];
+              int tmp3 = Distances[i][2];
+
+              Distances[i][0] = Distances[i - 1][0];
+              Distances[i][1] = Distances[i - 1][1];
+              Distances[i][2] = Distances[i - 1][2];
+
+              Distances[i - 1][0] = tmp;
+              Distances[i - 1][1] = tmp2;
+              Distances[i - 1][2] = tmp3;
+            }
+          }
+        }
+
+        float MoveX = 0.0;
+        float MoveY = 0.0;
+        int SampleNums = 0;
+        float DistanceMeasure = 0.0;
+
+        // Calculate the final camera movement
+        for (i = 0; i < DistanceMax; ++i)
+        {
+          if ((Distances[i][2] <= MaxTrackedPoints / 10))
+            break;
+
+          if (i > 0)
+          {
+            DistanceMeasure += (Distances[i][0] - Distances[i - 1][0])*(Distances[i][0] - Distances[i - 1][0]);
+            DistanceMeasure += (Distances[i][1] - Distances[i - 1][1])*(Distances[i][1] - Distances[i - 1][1]);
+          }
+
+          MoveX += Distances[i][0] * Distances[i][2];
+          MoveY += Distances[i][1] * Distances[i][2];
+          SampleNums += Distances[i][2];
+        }
+
+        if (SampleNums > 0)
+        {
+          MoveX = MERound(MoveX / SampleNums);
+          MoveY = MERound(MoveY / SampleNums);
+        }
+
+        if (!((MoveX == 0) && (MoveY == 0)) &&
+          (SampleNums > MaxTrackedPoints / 2))
+        {
+          HUOFCamMovementX += (int)MoveX;
+          int HUOFCamMovementY = (int)MoveY;
+          int MaxX = (HUImageWidth / 2) - 1;
+          int MaxY = HUImageHeight - 1;
+          /*
+          printf("-----------\n");
+
+          for (i = 0; i < DistanceMax; ++i)
+          printf("%d: %d,%d\n", Distances[i][2], Distances[i][0], Distances[i][1]);
+
+          printf("FINAL: %d,%d,%1.2f\n", (int)MoveX, (int)MoveY, DistanceMeasure);
+          printf("-----------\n");
+          printf("Camera movement: %d,%d,%d (max: %d, current: %d)\n",
+          SampleNums, HUOFCamMovementX, HUOFCamMovementY, MaxTrackedPoints, HUOFPointsNumber);
+          */
+          HUOFFrames = 0;
+          HUOFCamMovement = true;
+
+          if (!(HUOFCamMovementY == 0 && HUOFCamMovementX >= -1 && HUOFCamMovementX <= 1))
+          {
+            MEPixelDataType ***PreviousData = new MEPixelDataType**[MaxX + 1];
+
+            for (int i = 0; i < MaxX + 1; ++i)
+              PreviousData[i] = new MEPixelDataType*[MaxY + 1];
+
+            // Camera movement being happened
+            for (int y = MaxY; y >= 0; --y)
+            {
+              for (int x = MaxX; x >= 0; --x)
+              {
+                PreviousData[x][y] = NULL;
+              }
+            }
+
+            // Move the LBP data to new locations
+            for (int y = MaxY; y >= 0; --y)
+            {
+              for (int x = MaxX; x >= 0; --x)
+              {
+                int NewX = x + (HUOFCamMovementX / 2);
+                int NewY = y + HUOFCamMovementY;
+
+                if (NewX >= 0 && NewX <= MaxX &&
+                  NewY >= 0 && NewY <= MaxY)
+                {
+                  if (HULBPPixelData[NewX][NewY])
+                  {
+                    PreviousData[NewX][NewY] = HULBPPixelData[NewX][NewY];
+                    HULBPPixelData[NewX][NewY] = NULL;
+                    if (PreviousData[x][y])
+                    {
+                      HULBPPixelData[NewX][NewY] = PreviousData[x][y];
+                      PreviousData[x][y] = NULL;
+                    }
+                    else
+                    {
+                      HULBPPixelData[NewX][NewY] = HULBPPixelData[x][y];
+                      HULBPPixelData[x][y] = NULL;
+                    }
+                  }
+                  else
+                  {
+                    if (PreviousData[x][y])
+                    {
+                      HULBPPixelData[NewX][NewY] = PreviousData[x][y];
+                      PreviousData[x][y] = NULL;
+                    }
+                    else
+                    {
+                      HULBPPixelData[NewX][NewY] = HULBPPixelData[x][y];
+                      HULBPPixelData[x][y] = NULL;
+                    }
+                  }
+                }
+                else
+                {
+                  if (HULBPPixelData[x][y])
+                  {
+                    delete[] HULBPPixelData[x][y]->PreviousHistogram;
+                    for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                      delete[] HULBPPixelData[x][y]->Histograms[i2];
+                    delete[] HULBPPixelData[x][y]->Histograms;
+                    delete[] HULBPPixelData[x][y]->BackgroundHistogram;
+                    delete[] HULBPPixelData[x][y]->Weights;
+                    delete HULBPPixelData[x][y];
+                    HULBPPixelData[x][y] = NULL;
+                  }
+                }
+              }
+            }
+
+            // Release unused data
+            for (int y = MaxY; y >= 0; --y)
+            {
+              for (int x = MaxX; x >= 0; --x)
+              {
+                if (PreviousData[x][y])
+                {
+                  delete[] PreviousData[x][y]->PreviousHistogram;
+                  for (int i2 = 0; i2 < HUHistogramsPerPixel; ++i2)
+                    delete[] PreviousData[x][y]->Histograms[i2];
+                  delete[] PreviousData[x][y]->Histograms;
+                  delete[] PreviousData[x][y]->BackgroundHistogram;
+                  delete[] PreviousData[x][y]->Weights;
+                  delete PreviousData[x][y];
+                  PreviousData[x][y] = NULL;
+                }
+              }
+            }
+
+            HUOFCamMovementX = HUOFCamMovementX % 1;
+
+            for (int i = 0; i < MaxX + 1; ++i)
+              delete[] PreviousData[i];
+            delete[] PreviousData;
+          }
+        }
+
+        i1 = 0;
+        // Throw the missed points away
+        for (i = 0; i < HUOFPointsNumber; ++i)
+        {
+          if (PointsStatus[i] == 1)
+          {
+            HUOFPoints[0][i1] = HUOFPoints[1][i];
+            i1++;
+          }
+        }
+        HUOFPointsNumber -= i + 1 - i1;
+
+        if (HUOFPointsNumber < MaxTrackedPoints / 2)
+        {
+          printf("Re-init the optical flow\n");
+          HUOFDataState = ps_Initialized;
+          HUOFPointsNumber = CurrentImage.GetWidth()*CurrentImage.GetHeight() / 1000;
+        }
+        // Free memory
+        if (PreviousGray != PreviousImage.GetIplImage())
+          cvReleaseImage(&PreviousGray);
+        if (CurrentGray != CurrentImage.GetIplImage())
+          cvReleaseImage(&CurrentGray);
+        cvFree(&PointsStatus);
+
+        for (int i = 0; i < HUOFPointsNumber; ++i)
+          delete[] Distances[i];
+        delete[] Distances;
+      }
+
+      void MotionDetection::GetMotionsMaskHU(MEImage& mask_image)
+      {
+        if (MDDataState != ps_Successful)
+        {
+          mask_image.Clear();
+          return;
+        }
+
+        // Reallocate the mask image if needs be
+        if ((HUImageWidth + HUHistogramArea - 1 != mask_image.GetWidth()) ||
+          (HUImageHeight + HUHistogramArea - 1 != mask_image.GetHeight()) ||
+          (mask_image.GetLayers() != 1))
+        {
+          mask_image.Realloc(HUImageWidth + HUHistogramArea - 1,
+            HUImageHeight + HUHistogramArea - 1, 1);
+        }
+        mask_image.Clear();
+        // Generate the mask image
+        unsigned char* MaskImgData = mask_image.GetImageData();
+        int RowStart = (mask_image.GetHeight() - HUHistogramArea / 2)*mask_image.GetRowWidth();
+        int RowWidth = mask_image.GetRowWidth();
+
+        // Generate a graph about the histogram data
+        Graph::node_id **Nodes = new Graph::node_id*[HUImageWidth / 2];
+        for (int i = 0; i < HUImageWidth / 2; ++i)
+          Nodes[i] = new Graph::node_id[HUImageHeight];
+        Graph *LBPGraph = new Graph();
+
+        for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
+        {
+          for (int y = HUImageHeight - 1; y >= 0; --y)
+          {
+            Nodes[x][y] = LBPGraph->add_node();
+          }
+        }
+
+        for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
+        {
+          for (int y = HUImageHeight - 1; y >= 0; --y)
+          {
+            LBPGraph->set_tweights(Nodes[x][y], 1,
+              (short int)(HUMinCutWeight*(1 - HULBPPixelData[x][y]->BackgroundRate)));
+
+            if (x > 0 && y > 0)
+            {
+              LBPGraph->add_edge(Nodes[x][y], Nodes[x - 1][y], 1, 1);
+              LBPGraph->add_edge(Nodes[x][y], Nodes[x][y - 1], 1, 1);
+            }
+          }
+        }
+
+        LBPGraph->maxflow();
+
+        for (int x = (HUImageWidth / 2) - 1; x >= 0; --x)
+        {
+          for (int y = HUImageHeight - 1; y >= 0; --y)
+          {
+            if (LBPGraph->what_segment(Nodes[x][y]) == Graph::SINK)
+              HULBPPixelData[x][y]->BackgroundRate = 0.0;
+            else
+              HULBPPixelData[x][y]->BackgroundRate = 1.0;
+          }
+        }
+
+        delete LBPGraph;
+        LBPGraph = NULL;
+        for (int y = HUImageHeight - 1; y >= 0; --y)
+        {
+          for (int x = HUImageWidth - 1; x >= 0; --x)
+          {
+            if (y % 2 == (x + 1) % 2)
+              MaskImgData[RowStart + x + (HUHistogramArea / 2)] =
+              (HULBPPixelData[x / 2][y]->BackgroundRate == 0.0) ? 255 : 0;
+            else
+            {
+              MaskImgData[RowStart + x + (HUHistogramArea / 2)] =
+                ((int)(x > 1 && HULBPPixelData[(x / 2) - 1][y]->BackgroundRate == 0.0) +
+                (int)(x < mask_image.GetWidth() - HUHistogramArea - 1 &&
+                  HULBPPixelData[(x / 2) + 1][y]->BackgroundRate == 0.0) +
+                  (int)(y > 0 && HULBPPixelData[x / 2][y - 1]->BackgroundRate == 0.0) +
+                  (int)(y < mask_image.GetHeight() - HUHistogramArea &&
+                    HULBPPixelData[x / 2][y + 1]->BackgroundRate == 0.0) > 1)
+                ? 255 : 0;
+            }
+          }
+          RowStart -= RowWidth;
+        }
+
+        cvFloodFill(mask_image.GetIplImage(), cvPoint(0, 0), cvScalar(128, 128, 128, 128),
+          cvScalar(0, 0, 0, 0), cvScalar(0, 0, 0, 0));
+        for (int i = ((IplImage*)mask_image.GetIplImage())->widthStep*((IplImage*)mask_image.GetIplImage())->height - 1; i >= 0; --i)
+        {
+          if (MaskImgData[i] == 128)
+          {
+            MaskImgData[i] = 0;
+          }
+          else
+          {
+            if (MaskImgData[i] == 0)
+            {
+              MaskImgData[i] = 255;
+            }
+          }
+        }
+        // Apply an erode operator
+        mask_image.Erode(1);
+
+        for (int i = 0; i < HUImageWidth / 2; ++i)
+          delete[] Nodes[i];
+        delete[] Nodes;
+      }
+
+      void MotionDetection::SetSampleMaskHU(SampleMaskType mask_type, int desiredarea)
+      {
+        if (HUMaskColumnAddDel == NULL || HUMaskRowAddDel == NULL)
+        {
+          printf("Auxiliary variables are NULL\n");
+          return;
+        }
+
+        // Generate a mask for computing the histograms
+        IplImage *MaskImage = cvCreateImage(cvSize(HUHistogramArea, HUHistogramArea), 8, 1);
+        int DesiredArea = desiredarea <= 0 ? HUHistogramBins * 2 : desiredarea;
+
+        int **CalculationMask = new int*[HUHistogramArea];
+        for (int i = 0; i < HUHistogramArea; ++i)
+          CalculationMask[i] = new int[HUHistogramArea];
+
+        int SquareSide = (int)MERound(sqrt((float)DesiredArea));
+        int CircleRadius = (int)MERound(sqrt((float)DesiredArea / ME_PI_VALUE));
+        int EllipseA = (int)MERound(HUHistogramArea / 2 + 1);
+        int EllipseB = (int)MERound(DesiredArea / (EllipseA*1.2*ME_PI_VALUE));
+
+        cvSetZero(MaskImage);
+
+        switch (mask_type)
+        {
+        case sm_Circle:
+          cvCircle(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
+            CircleRadius, CV_RGB_LEGACY(1, 1, 1), -1);
+          break;
+
+        case sm_Square:
+          cvRectangle(MaskImage,
+            cvPoint(HUHistogramArea / 2 - SquareSide / 2, HUHistogramArea / 2 - SquareSide / 2),
+            cvPoint(HUHistogramArea / 2 + SquareSide / 2, HUHistogramArea / 2 + SquareSide / 2),
+            CV_RGB_LEGACY(1, 1, 1), -1);
+          break;
+
+        case sm_Ellipse:
+          cvEllipse(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
+            cvSize(EllipseA, EllipseB), 45, 0, 360,
+            CV_RGB_LEGACY(1, 1, 1), -1);
+          break;
+
+        case sm_RandomPixels:
+          HUSamplePixels = 0;
+          while (HUSamplePixels != DesiredArea)
+          {
+            int i = rand() % HUHistogramArea;
+            int j = rand() % HUHistogramArea;
+
+            if (MaskImage->imageData[i*MaskImage->widthStep + j] == 0)
+            {
+              MaskImage->imageData[i*MaskImage->widthStep + j] = 1;
+              HUSamplePixels++;
+            }
+          }
+          break;
+
+        default:
+          cvCircle(MaskImage, cvPoint(HUHistogramArea / 2, HUHistogramArea / 2),
+            (int)MERound(sqrt((float)DesiredArea / ME_PI_VALUE)), CV_RGB_LEGACY(1, 1, 1), -1);
+          break;
+        }
+
+        HUSamplePixels = 0;
+        //memset(CalculationMask, 0, sizeof(CalculationMask));
+
+        for (int i = 0; i < HUHistogramArea; ++i)
+        {
+          for (int i1 = 0; i1 < HUHistogramArea; ++i1)
+          {
+            if (MaskImage->imageData[i*MaskImage->widthStep + i1] != 0)
+            {
+              HUSamplePixels++;
+              CalculationMask[i][i1] = 1;
+            }
+            else {
+              CalculationMask[i][i1] = 0;
+            }
+          }
+        }
+
+        // Fill an auxiliary variable for fast computing with data
+        for (int i = 0; i < HUHistogramArea; ++i)
+        {
+          HUMaskColumnAddDel[i][0] = -1;
+          for (int i1 = 0; i1 < HUHistogramArea; ++i1)
+          {
+            if (CalculationMask[i][i1] != 0)
+            {
+              HUMaskColumnAddDel[i][0] = i1;
+              break;
+            }
+          }
+          HUMaskColumnAddDel[i][1] = -1;
+          for (int i1 = HUHistogramArea - 1; i1 >= 0; --i1)
+          {
+            if (CalculationMask[i][i1] != 0)
+            {
+              HUMaskColumnAddDel[i][1] = i1 + 1;
+              break;
+            }
+          }
+        }
+
+        // Fill an auxiliary variable for fast computing with data
+        for (int i = 0; i < HUHistogramArea; ++i)
+        {
+          HUMaskRowAddDel[i][0] = -1;
+          for (int i1 = 0; i1 < HUHistogramArea; ++i1)
+          {
+            if (CalculationMask[i1][i] != 0)
+            {
+              HUMaskRowAddDel[i][0] = i1;
+              break;
+            }
+          }
+          HUMaskRowAddDel[i][1] = -1;
+          for (int i1 = HUHistogramArea - 1; i1 >= 0; --i1)
+          {
+            if (CalculationMask[i1][i] != 0)
+            {
+              HUMaskRowAddDel[i][1] = i1 + 1;
+              break;
+            }
+          }
+        }
+
+        // Freeing memory
+        cvReleaseImage(&MaskImage);
+
+        for (int i = 0; i < HUHistogramArea; ++i)
+          delete[] CalculationMask[i];
+        delete[] CalculationMask;
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/MotionDetection.hpp b/src/algorithms/LBP_MRF/MotionDetection.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a944ef27f301ded232f572251f33296dbad9ea30
--- /dev/null
+++ b/src/algorithms/LBP_MRF/MotionDetection.hpp
@@ -0,0 +1,391 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//#include <opencv2/opencv.hpp>
+//#include <opencv2/imgproc.hpp>
+
+// opencv legacy includes
+#include <opencv2/imgproc/imgproc_c.h>
+#include <opencv2/video/tracking_c.h>
+
+#include "MEDefs.hpp"
+#include "MEImage.hpp"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      class CvBGStatModel;
+      //struct CvPoint2D32f;
+
+      // Struct for histogram update data of a pixel
+      struct MEPixelDataType;
+
+      /**
+       * MotionDetection
+       * @brief Extract moving objects from image sequence
+       */
+      class MotionDetection
+      {
+      public:
+
+        /// Types of motion detection
+        typedef enum
+        {
+          md_Min = 0,               /*!< Minimum value */
+          md_NotDefined = md_Min,   /*!< Not defined */
+          md_DLBPHistograms,        /*!< Dynamic LBP */
+          md_LBPHistograms,         /*!< Normal LBP */
+          md_Max = md_LBPHistograms /*!< Maximum value */
+        } DetectorType;
+
+        /// Types of sample mask
+        typedef enum
+        {
+          sm_Min = 0,              /*!< Minimum value */
+          sm_Circle = sm_Min,      /*!< Circle */
+          sm_Square,               /*!< Square */
+          sm_Ellipse,              /*!< Ellipse */
+          sm_RandomPixels,         /*!< Random pixels */
+          sm_Max = sm_RandomPixels /*!< Maximum value */
+        } SampleMaskType;
+
+        /// Types of motion detection parameters
+        typedef enum
+        {
+          mdp_Min = 0,                         /*!< Minimum value */
+          mdp_HUProximityThreshold = mdp_Min,  /*!< Proximity threshold */
+          mdp_HUBackgroundThreshold,           /*!< Background threshold */
+          mdp_HUHistogramLearningRate,         /*!< Histogram learning rate */
+          mdp_HUWeightsLearningRate,           /*!< Weights learning rate */
+          mdp_HUMinCutWeight,                  /*!< Minimum cut weight */
+          mdp_HUDesiredSamplePixels,           /*!< Desired sample pixels */
+          mdp_HUHistogramsPerPixel,            /*!< Histogram per pixel */
+          mdp_HUHistogramArea,                 /*!< Histogram area */
+          mdp_HUHistogramBins,                 /*!< Histogram bins */
+          mdp_HUColorSpace,                    /*!< Color space */
+          mdp_HULBPMode,                       /*!< LBP mode */
+          mdp_Max = mdp_HULBPMode              /*!< Maximum value */
+        } ParametersType;
+
+        /*!
+        * @brief Class constructor
+        *
+        * @param mode Detection mode
+        *
+        * Class constructor with the possibility to specify the detection mode.
+        * The default is dynamic LBP.
+        *
+        */
+
+        MotionDetection(DetectorType mode = md_DLBPHistograms);
+        /// Destructor of class
+        ~MotionDetection();
+
+        /*
+        -------------------------------------------------------------------
+                                Motion methods
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Set the mode of the motion detection
+        *
+        * @param newmode New mode of detection
+        *
+        * Set the mode of the motion detection.
+        *
+        */
+
+        void SetMode(DetectorType newmode);
+
+        /*!
+        * @brief Get a parameter value of the motion detection
+        *
+        * @param param Parameter of the detection
+        *
+        * @return Queried value
+        *
+        * Get the value of a parameter of the motion detection.
+        *
+        */
+
+        float GetParameter(ParametersType param) const;
+
+        /*!
+        * @brief Set a parameter of the motion detection
+        *
+        * @param param Parameter of the detection
+        * @param value New value
+        *
+        * Set a new value to a parameter of the motion detection.
+        *
+        */
+
+        void SetParameter(ParametersType param, float value);
+
+        /*!
+        * @brief Detect the motions on an image
+        *
+        * @param image Image to process
+        *
+        * The function designed to search motions in image streams
+        * thus it needs to process the image sequence frame by frame.
+        * It processes an image from this sequence and searches moving blobs
+        * on that.
+        *
+        */
+
+        void DetectMotions(MEImage& image);
+
+        /*!
+        * @brief Get mask image with detected motions
+        *
+        * @param mask_image Result mask image
+        *
+        * The function creates a mask image on which the objects are
+        * indicated by white blobs.
+        *
+        */
+
+        void GetMotionsMask(MEImage& mask_image);
+
+        /*!
+        * @brief Calculate results of the motion detection
+        *
+        * @param referenceimage Reference mask image
+        * @param tnegatives True negative pixels
+        * @param tpositives True positive pixels
+        * @param ttnegatives Total true negative pixels
+        * @param ttpositives Total true positive pixels
+        *
+        * The function calculates the results of the motion detection
+        * between the current motion mask and a given reference mask
+        * image.
+        *
+        */
+
+        void CalculateResults(MEImage& referenceimage, int& tnegatives, int& tpositives,
+          int& ttnegatives, int& ttpositives);
+
+      private:
+
+        /*!
+        * @brief Release data structures
+        *
+        * Function releases the data structures.
+        *
+        */
+
+        void ReleaseData();
+
+        /*
+        -------------------------------------------------------------------
+                          Histogram update methods
+        -------------------------------------------------------------------
+        */
+
+        /*!
+        * @brief Init HU data structures
+        *
+        * @param imagewidth Image width for HU to process
+        * @param imageheight Image height for HU to process
+        *
+        * Function allocates/re-allocates the HU data structures and they
+        * are cleared if needs be.
+        *
+        */
+
+        void InitHUData(int imagewidth, int imageheight);
+
+        /*!
+        * @brief Init HU optical flow data structures
+        *
+        * @param imagewidth Image width for HU to process
+        * @param imageheight Image height for HU to process
+        *
+        * Function allocates/re-allocates the HU optical flow
+        * data structures.
+        *
+        */
+
+        void InitHUOFData(int imagewidth, int imageheight);
+
+        /*!
+        * @brief Release HU data structures
+        *
+        * Function releases the HU data structures.
+        *
+        */
+
+        void ReleaseHUData();
+
+        /*!
+        * @brief Release HU optical flow data structures
+        *
+        * Function releases the HU optical flow data structures.
+        *
+        */
+
+        void ReleaseHUOFData();
+
+        /*!
+        * @brief Clear HU data structures
+        *
+        * Function clears the HU data structures.
+        *
+        */
+
+        void ClearHUData();
+
+        /*!
+        * @brief Get mask image with detected motions by histogram update
+        *
+        * @param mask_image Result mask image
+        *
+        * The function creates a mask image on which the objects are
+        * indicated by white blobs.
+        *
+        */
+
+        void GetMotionsMaskHU(MEImage& mask_image);
+
+        /*!
+        * @brief Set the sample mask
+        *
+        * @param mask_type Type of the mask
+        * @param desiredarea The desired area size of the mask
+        *
+        * The function creates a sample mask with a desired form
+        * (square, circle, ellipse, random pixels) and size.
+        *
+        */
+
+        void SetSampleMaskHU(SampleMaskType mask_type, int desiredarea);
+
+        /*!
+        * @brief Detect the motions on an image with histogram update
+        *
+        * @param image Image to process
+        *
+        * The function designed to search motions in image streams
+        * thus it needs to process the image sequence frame by frame.
+        * It processes an image from this sequence and searches moving blobs
+        * on that. It uses histogram update method.
+        *
+        */
+
+        void DetectMotionsHU(MEImage& image);
+
+        /*!
+        * @brief Update a model
+        *
+        * @param image Image to process
+        * @param model Model to update
+        *
+        * The function updates a histogram model of the image.
+        *
+        */
+
+        void UpdateModelHU(MEImage& image, MEPixelDataType*** model);
+
+        /*!
+        * @brief Update the HU data structure for one pixel
+        *
+        * @param pixeldata Pixel data
+        * @param histogram Current histogram
+        *
+        * This method updates the HU data for one pixel.
+        *
+        */
+
+        void UpdateHUPixelData(MEPixelDataType* pixeldata, const float *histogram);
+
+        /*!
+        * @brief Optical flow correction of the camera movements
+        *
+        * The function trackes some points on the scene if a camera movement is
+        * detected, then the LBP pixel data is corrected.
+        *
+        */
+
+        void OpticalFlowCorrection();
+
+      private:
+        // GENERAL VARIABLES
+        /// Motion detection type
+        DetectorType MDMode;
+        /// State of the data structures
+        MEProcessStateType MDDataState;
+        /// Processed number in the image sequence
+        int Frames;
+        /// Store the current image
+        MEImage CurrentImage;
+        /// Store the previous image
+        MEImage PreviousImage;
+        /// Store the current mask image
+        MEImage MaskImage;
+        /// Store the current mask image
+        bool ReadyMask;
+        // HISTOGRAM UPDATE VARIABLES
+        /// Color space (-1 = no conversion)
+        int HUColorSpace;
+        /// LBP calculation mode (-1 = no conversion)
+        int HULBPMode;
+        /// Histograms per pixel
+        int HUHistogramsPerPixel;
+        /// Histogram area
+        int HUHistogramArea;
+        /// Histogram bins
+        int HUHistogramBins;
+        /// Image width for histogram update
+        int HUImageWidth;
+        /// Image height for histogram update
+        int HUImageHeight;
+        /// Data of the LBP histograms
+        MEPixelDataType ***HULBPPixelData;
+        /// Store the previous blue layer
+        MEImage PreviousBlueLayer;
+        /// Histogram proximity threshold
+        float HUPrThres;
+        /// Background selection threshold
+        float HUBackgrThres;
+        /// Histogram learning rate
+        float HUHistLRate;
+        /// Weights learning rate
+        float HUWeightsLRate;
+        /// Pixel number used to calculate the histograms
+        int HUSamplePixels;
+        /// The desired pixel number used to calculate the histograms (-1 = Auto)
+        int HUDesiredSamplePixels;
+        /// Min cut weight
+        float HUMinCutWeight;
+        /// Auxiliary variable for computing the histograms in a column
+        int **HUMaskColumnAddDel;
+        /// Auxiliary variable for computing the histograms in a row
+        int **HUMaskRowAddDel;
+        // OPTICAL FLOW VARIABLES
+        /// State of the optical flow
+        MEProcessStateType HUOFDataState;
+        /// Number of the tracked points with optical flow
+        int HUOFPointsNumber;
+        /// Tracked points
+        CvPoint2D32f* HUOFPoints[2];
+        /// The rest x component of previous camera movement
+        int HUOFCamMovementX;
+        /// Maximum tracked points detected in one cycle
+        int MaxTrackedPoints;
+        /// Processed frame number with optical flow in the image sequence
+        int HUOFFrames;
+        /// Indicator of a new camera movement
+        bool HUOFCamMovement;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/LBP_MRF/block.h b/src/algorithms/LBP_MRF/block.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f5c3d25889725f326d07b297e45acad5bed7a65
--- /dev/null
+++ b/src/algorithms/LBP_MRF/block.h
@@ -0,0 +1,178 @@
+#pragma once
+
+#include <stdlib.h>
+#include <stdio.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      template <class Type> class Block
+      {
+      public:
+        /* Constructor. Arguments are the block size and
+            (optionally) the pointer to the function which
+            will be called if allocation failed; the message
+            passed to this function is "Not enough memory!" */
+        Block(int size, void(*err_function)(char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; }
+
+        /* Destructor. Deallocates all items added so far */
+        ~Block() { while (first) { block *next = first->next; delete first; first = next; } }
+
+        /* Allocates 'num' consecutive items; returns pointer
+            to the first item. 'num' cannot be greater than the
+            block size since items must fit in one block */
+        Type *New(int num = 1)
+        {
+          Type *t;
+
+          if (!last || last->current + num > last->last)
+          {
+            if (last && last->next) last = last->next;
+            else
+            {
+              block *next = (block *) new char[sizeof(block) + (block_size - 1)*sizeof(Type)];
+              if (!next) { fprintf(stderr, "Not enough memory!"); exit(1); }
+              if (last) last->next = next;
+              else first = next;
+              last = next;
+              last->current = &(last->data[0]);
+              last->last = last->current + block_size;
+              last->next = NULL;
+            }
+          }
+
+          t = last->current;
+          last->current += num;
+          return t;
+        }
+
+        /* Returns the first item (or NULL, if no items were added) */
+        Type *ScanFirst()
+        {
+          scan_current_block = first;
+          if (!scan_current_block) return NULL;
+          scan_current_data = &(scan_current_block->data[0]);
+          return scan_current_data++;
+        }
+
+        /* Returns the next item (or NULL, if all items have been read)
+            Can be called only if previous ScanFirst() or ScanNext()
+            call returned not NULL. */
+        Type *ScanNext()
+        {
+          if (scan_current_data >= scan_current_block->current)
+          {
+            scan_current_block = scan_current_block->next;
+            if (!scan_current_block) return NULL;
+            scan_current_data = &(scan_current_block->data[0]);
+          }
+          return scan_current_data++;
+        }
+
+        /* Marks all elements as empty */
+        void Reset()
+        {
+          block *b;
+          if (!first) return;
+          for (b = first;; b = b->next)
+          {
+            b->current = &(b->data[0]);
+            if (b == last) break;
+          }
+          last = first;
+        }
+
+        /***********************************************************************/
+
+      private:
+
+        typedef struct block_st
+        {
+          Type					*current, *last;
+          struct block_st			*next;
+          Type					data[1];
+        } block;
+
+        int		block_size;
+        block	*first;
+        block	*last;
+
+        block	*scan_current_block;
+        Type	*scan_current_data;
+
+        void(*error_function)(char *);
+      };
+
+      /***********************************************************************/
+      /***********************************************************************/
+      /***********************************************************************/
+
+      template <class Type> class DBlock
+      {
+      public:
+        /* Constructor. Arguments are the block size and
+            (optionally) the pointer to the function which
+            will be called if allocation failed; the message
+            passed to this function is "Not enough memory!" */
+        DBlock(int size, void(*err_function)(char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; }
+
+        /* Destructor. Deallocates all items added so far */
+        ~DBlock() { while (first) { block *next = first->next; delete first; first = next; } }
+
+        /* Allocates one item */
+        Type *New()
+        {
+          block_item *item;
+
+          if (!first_free)
+          {
+            block *next = first;
+            first = (block *) new char[sizeof(block) + (block_size - 1)*sizeof(block_item)];
+            if (!first) { fprintf(stderr, "Not enough memory!"); exit(1); }
+            first_free = &(first->data[0]);
+            for (item = first_free; item < first_free + block_size - 1; item++)
+              item->next_free = item + 1;
+            item->next_free = NULL;
+            first->next = next;
+          }
+
+          item = first_free;
+          first_free = item->next_free;
+          return (Type *)item;
+        }
+
+        /* Deletes an item allocated previously */
+        void Delete(Type *t)
+        {
+          ((block_item *)t)->next_free = first_free;
+          first_free = (block_item *)t;
+        }
+
+        /***********************************************************************/
+
+      private:
+
+        typedef union block_item_st
+        {
+          Type			t;
+          block_item_st	*next_free;
+        } block_item;
+
+        typedef struct block_st
+        {
+          struct block_st			*next;
+          block_item				data[1];
+        } block;
+
+        int			block_size;
+        block		*first;
+        block_item	*first_free;
+
+        void(*error_function)(char *);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBP_MRF/graph.cpp b/src/algorithms/LBP_MRF/graph.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..541efb3669ebd8b732fdd26bda47d560c471fcd2
--- /dev/null
+++ b/src/algorithms/LBP_MRF/graph.cpp
@@ -0,0 +1,71 @@
+#include <stdio.h>
+
+#include "graph.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      Graph::Graph(void(*err_function)(char *))
+      {
+        error_function = err_function;
+        node_block = new Block<node>(NODE_BLOCK_SIZE, error_function);
+        arc_block = new Block<arc>(NODE_BLOCK_SIZE, error_function);
+        flow = 0;
+      }
+
+      Graph::~Graph()
+      {
+        delete node_block;
+        delete arc_block;
+      }
+
+      Graph::node_id Graph::add_node()
+      {
+        node *i = node_block->New();
+
+        i->first = NULL;
+        i->tr_cap = 0;
+
+        return (node_id)i;
+      }
+
+      void Graph::add_edge(node_id from, node_id to, captype cap, captype rev_cap)
+      {
+        arc *a, *a_rev;
+
+        a = arc_block->New(2);
+        a_rev = a + 1;
+
+        a->sister = a_rev;
+        a_rev->sister = a;
+        a->next = ((node*)from)->first;
+        ((node*)from)->first = a;
+        a_rev->next = ((node*)to)->first;
+        ((node*)to)->first = a_rev;
+        a->head = (node*)to;
+        a_rev->head = (node*)from;
+        a->r_cap = cap;
+        a_rev->r_cap = rev_cap;
+      }
+
+      void Graph::set_tweights(node_id i, captype cap_source, captype cap_sink)
+      {
+        flow += (cap_source < cap_sink) ? cap_source : cap_sink;
+        ((node*)i)->tr_cap = cap_source - cap_sink;
+      }
+
+      void Graph::add_tweights(node_id i, captype cap_source, captype cap_sink)
+      {
+        //register
+        captype delta = ((node*)i)->tr_cap; // 'register' storage class specifier is deprecated and incompatible with C++17
+        if (delta > 0) cap_source += delta;
+        else           cap_sink -= delta;
+        flow += (cap_source < cap_sink) ? cap_source : cap_sink;
+        ((node*)i)->tr_cap = cap_source - cap_sink;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBP_MRF/graph.h b/src/algorithms/LBP_MRF/graph.h
new file mode 100644
index 0000000000000000000000000000000000000000..257b0a77d35e71952154eaec1be8df0ed3bf883c
--- /dev/null
+++ b/src/algorithms/LBP_MRF/graph.h
@@ -0,0 +1,143 @@
+#pragma once
+
+#include "block.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      /*
+        Nodes, arcs and pointers to nodes are
+        added in blocks for memory and time efficiency.
+        Below are numbers of items in blocks
+        */
+      const int NODE_BLOCK_SIZE = 512;
+      const int ARC_BLOCK_SIZE = 1024;
+      const int NODEPTR_BLOCK_SIZE = 128;
+      
+      class Graph
+      {
+      public:
+        typedef enum
+        {
+          SOURCE = 0,
+          SINK = 1
+        } termtype; /* terminals */
+
+        /* Type of edge weights.
+            Can be changed to char, int, float, double, ... */
+        typedef short captype;
+        /* Type of total flow */
+        typedef int flowtype;
+
+        typedef void * node_id;
+
+        /* interface functions */
+
+        /* Constructor. Optional argument is the pointer to the
+            function which will be called if an error occurs;
+            an error message is passed to this function. If this
+            argument is omitted, exit(1) will be called. */
+        Graph(void(*err_function)(char *) = NULL);
+
+        /* Destructor */
+        ~Graph();
+
+        /* Adds a node to the graph */
+        node_id add_node();
+
+        /* Adds a bidirectional edge between 'from' and 'to'
+            with the weights 'cap' and 'rev_cap' */
+        void add_edge(node_id from, node_id to, captype cap, captype rev_cap);
+
+        /* Sets the weights of the edges 'SOURCE->i' and 'i->SINK'
+            Can be called at most once for each node before any call to 'add_tweights'.
+            Weights can be negative */
+        void set_tweights(node_id i, captype cap_source, captype cap_sink);
+
+        /* Adds new edges 'SOURCE->i' and 'i->SINK' with corresponding weights
+            Can be called multiple times for each node.
+            Weights can be negative */
+        void add_tweights(node_id i, captype cap_source, captype cap_sink);
+
+        /* After the maxflow is computed, this function returns to which
+            segment the node 'i' belongs (Graph::SOURCE or Graph::SINK) */
+        termtype what_segment(node_id i);
+
+        /* Computes the maxflow. Can be called only once. */
+        flowtype maxflow();
+
+        /***********************************************************************/
+        /***********************************************************************/
+        /***********************************************************************/
+
+      private:
+        /* internal variables and functions */
+
+        struct arc_st;
+
+        /* node structure */
+        typedef struct node_st
+        {
+          arc_st			*first;		/* first outcoming arc */
+
+          arc_st			*parent;	/* node's parent */
+          node_st			*next;		/* pointer to the next active node
+                            (or to itself if it is the last node in the list) */
+          int				TS;			/* timestamp showing when DIST was computed */
+          int				DIST;		/* distance to the terminal */
+          short			is_sink;	/* flag showing whether the node is in the source or in the sink tree */
+
+          captype			tr_cap;		/* if tr_cap > 0 then tr_cap is residual capacity of the arc SOURCE->node
+                            otherwise         -tr_cap is residual capacity of the arc node->SINK */
+        } node;
+
+        /* arc structure */
+        typedef struct arc_st
+        {
+          node_st			*head;		/* node the arc points to */
+          arc_st			*next;		/* next arc with the same originating node */
+          arc_st			*sister;	/* reverse arc */
+
+          captype			r_cap;		/* residual capacity */
+        } arc;
+
+        /* 'pointer to node' structure */
+        typedef struct nodeptr_st
+        {
+          node_st			*ptr;
+          nodeptr_st		*next;
+        } nodeptr;
+
+        Block<node>			*node_block;
+        Block<arc>			*arc_block;
+        DBlock<nodeptr>		*nodeptr_block;
+
+        void(*error_function)(char *);	/* this function is called if a error occurs,
+                              with a corresponding error message
+                              (or exit(1) is called if it's NULL) */
+
+        flowtype			flow;		/* total flow */
+
+        /***********************************************************************/
+
+        node				*queue_first[2], *queue_last[2];	/* list of active nodes */
+        nodeptr				*orphan_first, *orphan_last;		/* list of pointers to orphans */
+        int					TIME;								/* monotonically increasing global counter */
+
+        /***********************************************************************/
+
+        /* functions for processing active list */
+        void set_active(node *i);
+        node *next_active();
+
+        void maxflow_init();
+        void augment(arc *middle_arc);
+        void process_source_orphan(node *i);
+        void process_sink_orphan(node *i);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBP_MRF/maxflow.cpp b/src/algorithms/LBP_MRF/maxflow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..660de7ba78293768815fd2df9d8d3c04d7998533
--- /dev/null
+++ b/src/algorithms/LBP_MRF/maxflow.cpp
@@ -0,0 +1,502 @@
+#include <stdio.h>
+
+#include "graph.h"
+
+/*
+special constants for node->parent
+*/
+#define TERMINAL ( (arc *) 1 )		/* to terminal */
+#define ORPHAN   ( (arc *) 2 )		/* orphan */
+
+#define INFINITE_D 1000000000		/* infinite distance to the terminal */
+
+/***********************************************************************/
+
+/*
+Functions for processing active list.
+i->next points to the next node in the list
+(or to i, if i is the last node in the list).
+If i->next is NULL iff i is not in the list.
+
+There are two queues. Active nodes are added
+to the end of the second queue and read from
+the front of the first queue. If the first queue
+is empty, it is replaced by the second queue
+(and the second queue becomes empty).
+*/
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbp_mrf
+    {
+      inline void Graph::set_active(node *i)
+      {
+        if (!i->next)
+        {
+          /* it's not in the list yet */
+          if (queue_last[1]) queue_last[1]->next = i;
+          else               queue_first[1] = i;
+          queue_last[1] = i;
+          i->next = i;
+        }
+      }
+
+      /*
+          Returns the next active node.
+          If it is connected to the sink, it stays in the list,
+          otherwise it is removed from the list
+          */
+      inline Graph::node * Graph::next_active()
+      {
+        node *i;
+
+        while (1)
+        {
+          if (!(i = queue_first[0]))
+          {
+            queue_first[0] = i = queue_first[1];
+            queue_last[0] = queue_last[1];
+            queue_first[1] = NULL;
+            queue_last[1] = NULL;
+            if (!i) return NULL;
+          }
+
+          /* remove it from the active list */
+          if (i->next == i) queue_first[0] = queue_last[0] = NULL;
+          else              queue_first[0] = i->next;
+          i->next = NULL;
+
+          /* a node in the list is active iff it has a parent */
+          if (i->parent) return i;
+        }
+      }
+
+      /***********************************************************************/
+
+      void Graph::maxflow_init()
+      {
+        node *i;
+
+        queue_first[0] = queue_last[0] = NULL;
+        queue_first[1] = queue_last[1] = NULL;
+        orphan_first = NULL;
+
+        for (i = node_block->ScanFirst(); i; i = node_block->ScanNext())
+        {
+          i->next = NULL;
+          i->TS = 0;
+          if (i->tr_cap > 0)
+          {
+            /* i is connected to the source */
+            i->is_sink = 0;
+            i->parent = TERMINAL;
+            set_active(i);
+            i->TS = 0;
+            i->DIST = 1;
+          }
+          else if (i->tr_cap < 0)
+          {
+            /* i is connected to the sink */
+            i->is_sink = 1;
+            i->parent = TERMINAL;
+            set_active(i);
+            i->TS = 0;
+            i->DIST = 1;
+          }
+          else
+          {
+            i->parent = NULL;
+          }
+        }
+        TIME = 0;
+      }
+
+      /***********************************************************************/
+
+      void Graph::augment(arc *middle_arc)
+      {
+        node *i;
+        arc *a;
+        captype bottleneck;
+        nodeptr *np;
+
+
+        /* 1. Finding bottleneck capacity */
+        /* 1a - the source tree */
+        bottleneck = middle_arc->r_cap;
+        for (i = middle_arc->sister->head;; i = a->head)
+        {
+          a = i->parent;
+          if (a == TERMINAL) break;
+          if (bottleneck > a->sister->r_cap) bottleneck = a->sister->r_cap;
+        }
+        if (bottleneck > i->tr_cap) bottleneck = i->tr_cap;
+        /* 1b - the sink tree */
+        for (i = middle_arc->head;; i = a->head)
+        {
+          a = i->parent;
+          if (a == TERMINAL) break;
+          if (bottleneck > a->r_cap) bottleneck = a->r_cap;
+        }
+        if (bottleneck > -i->tr_cap) bottleneck = -i->tr_cap;
+
+
+        /* 2. Augmenting */
+        /* 2a - the source tree */
+        middle_arc->sister->r_cap += bottleneck;
+        middle_arc->r_cap -= bottleneck;
+        for (i = middle_arc->sister->head;; i = a->head)
+        {
+          a = i->parent;
+          if (a == TERMINAL) break;
+          a->r_cap += bottleneck;
+          a->sister->r_cap -= bottleneck;
+          if (!a->sister->r_cap)
+          {
+            /* add i to the adoption list */
+            i->parent = ORPHAN;
+            np = nodeptr_block->New();
+            np->ptr = i;
+            np->next = orphan_first;
+            orphan_first = np;
+          }
+        }
+        i->tr_cap -= bottleneck;
+        if (!i->tr_cap)
+        {
+          /* add i to the adoption list */
+          i->parent = ORPHAN;
+          np = nodeptr_block->New();
+          np->ptr = i;
+          np->next = orphan_first;
+          orphan_first = np;
+        }
+        /* 2b - the sink tree */
+        for (i = middle_arc->head;; i = a->head)
+        {
+          a = i->parent;
+          if (a == TERMINAL) break;
+          a->sister->r_cap += bottleneck;
+          a->r_cap -= bottleneck;
+          if (!a->r_cap)
+          {
+            /* add i to the adoption list */
+            i->parent = ORPHAN;
+            np = nodeptr_block->New();
+            np->ptr = i;
+            np->next = orphan_first;
+            orphan_first = np;
+          }
+        }
+        i->tr_cap += bottleneck;
+        if (!i->tr_cap)
+        {
+          /* add i to the adoption list */
+          i->parent = ORPHAN;
+          np = nodeptr_block->New();
+          np->ptr = i;
+          np->next = orphan_first;
+          orphan_first = np;
+        }
+
+
+        flow += bottleneck;
+      }
+
+      /***********************************************************************/
+
+      void Graph::process_source_orphan(node *i)
+      {
+        node *j;
+        arc *a0, *a0_min = NULL, *a;
+        nodeptr *np;
+        int d, d_min = INFINITE_D;
+
+        /* trying to find a new parent */
+        for (a0 = i->first; a0; a0 = a0->next)
+          if (a0->sister->r_cap)
+          {
+            j = a0->head;
+            if (!j->is_sink && (a = j->parent))
+            {
+              /* checking the origin of j */
+              d = 0;
+              while (1)
+              {
+                if (j->TS == TIME)
+                {
+                  d += j->DIST;
+                  break;
+                }
+                a = j->parent;
+                d++;
+                if (a == TERMINAL)
+                {
+                  j->TS = TIME;
+                  j->DIST = 1;
+                  break;
+                }
+                if (a == ORPHAN) { d = INFINITE_D; break; }
+                j = a->head;
+              }
+              if (d < INFINITE_D) /* j originates from the source - done */
+              {
+                if (d < d_min)
+                {
+                  a0_min = a0;
+                  d_min = d;
+                }
+                /* set marks along the path */
+                for (j = a0->head; j->TS != TIME; j = j->parent->head)
+                {
+                  j->TS = TIME;
+                  j->DIST = d--;
+                }
+              }
+            }
+          }
+
+        if ((i->parent = a0_min))
+        {
+          i->TS = TIME;
+          i->DIST = d_min + 1;
+        }
+        else
+        {
+          /* no parent is found */
+          i->TS = 0;
+
+          /* process neighbors */
+          for (a0 = i->first; a0; a0 = a0->next)
+          {
+            j = a0->head;
+            if (!j->is_sink && (a = j->parent))
+            {
+              if (a0->sister->r_cap) set_active(j);
+              if (a != TERMINAL && a != ORPHAN && a->head == i)
+              {
+                /* add j to the adoption list */
+                j->parent = ORPHAN;
+                np = nodeptr_block->New();
+                np->ptr = j;
+                if (orphan_last) orphan_last->next = np;
+                else             orphan_first = np;
+                orphan_last = np;
+                np->next = NULL;
+              }
+            }
+          }
+        }
+      }
+
+      void Graph::process_sink_orphan(node *i)
+      {
+        node *j;
+        arc *a0, *a0_min = NULL, *a;
+        nodeptr *np;
+        int d, d_min = INFINITE_D;
+
+        /* trying to find a new parent */
+        for (a0 = i->first; a0; a0 = a0->next)
+          if (a0->r_cap)
+          {
+            j = a0->head;
+            if (j->is_sink && (a = j->parent))
+            {
+              /* checking the origin of j */
+              d = 0;
+              while (1)
+              {
+                if (j->TS == TIME)
+                {
+                  d += j->DIST;
+                  break;
+                }
+                a = j->parent;
+                d++;
+                if (a == TERMINAL)
+                {
+                  j->TS = TIME;
+                  j->DIST = 1;
+                  break;
+                }
+                if (a == ORPHAN) { d = INFINITE_D; break; }
+                j = a->head;
+              }
+              if (d < INFINITE_D) /* j originates from the sink - done */
+              {
+                if (d < d_min)
+                {
+                  a0_min = a0;
+                  d_min = d;
+                }
+                /* set marks along the path */
+                for (j = a0->head; j->TS != TIME; j = j->parent->head)
+                {
+                  j->TS = TIME;
+                  j->DIST = d--;
+                }
+              }
+            }
+          }
+
+        if ((i->parent = a0_min))
+        {
+          i->TS = TIME;
+          i->DIST = d_min + 1;
+        }
+        else
+        {
+          /* no parent is found */
+          i->TS = 0;
+
+          /* process neighbors */
+          for (a0 = i->first; a0; a0 = a0->next)
+          {
+            j = a0->head;
+            if (j->is_sink && (a = j->parent))
+            {
+              if (a0->r_cap) set_active(j);
+              if (a != TERMINAL && a != ORPHAN && a->head == i)
+              {
+                /* add j to the adoption list */
+                j->parent = ORPHAN;
+                np = nodeptr_block->New();
+                np->ptr = j;
+                if (orphan_last) orphan_last->next = np;
+                else             orphan_first = np;
+                orphan_last = np;
+                np->next = NULL;
+              }
+            }
+          }
+        }
+      }
+
+      /***********************************************************************/
+
+      Graph::flowtype Graph::maxflow()
+      {
+        node *i, *j, *current_node = NULL;
+        arc *a;
+        nodeptr *np, *np_next;
+
+        maxflow_init();
+        nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);
+
+        while (1)
+        {
+          if ((i = current_node))
+          {
+            i->next = NULL; /* remove active flag */
+            if (!i->parent) i = NULL;
+          }
+          if (!i)
+          {
+            if (!(i = next_active())) break;
+          }
+
+          /* growth */
+          if (!i->is_sink)
+          {
+            /* grow source tree */
+            for (a = i->first; a; a = a->next)
+              if (a->r_cap)
+              {
+                j = a->head;
+                if (!j->parent)
+                {
+                  j->is_sink = 0;
+                  j->parent = a->sister;
+                  j->TS = i->TS;
+                  j->DIST = i->DIST + 1;
+                  set_active(j);
+                }
+                else if (j->is_sink) break;
+                else if (j->TS <= i->TS &&
+                  j->DIST > i->DIST)
+                {
+                  /* heuristic - trying to make the distance from j to the source shorter */
+                  j->parent = a->sister;
+                  j->TS = i->TS;
+                  j->DIST = i->DIST + 1;
+                }
+              }
+          }
+          else
+          {
+            /* grow sink tree */
+            for (a = i->first; a; a = a->next)
+              if (a->sister->r_cap)
+              {
+                j = a->head;
+                if (!j->parent)
+                {
+                  j->is_sink = 1;
+                  j->parent = a->sister;
+                  j->TS = i->TS;
+                  j->DIST = i->DIST + 1;
+                  set_active(j);
+                }
+                else if (!j->is_sink) { a = a->sister; break; }
+                else if (j->TS <= i->TS &&
+                  j->DIST > i->DIST)
+                {
+                  /* heuristic - trying to make the distance from j to the sink shorter */
+                  j->parent = a->sister;
+                  j->TS = i->TS;
+                  j->DIST = i->DIST + 1;
+                }
+              }
+          }
+
+          TIME++;
+
+          if (a)
+          {
+            i->next = i; /* set active flag */
+            current_node = i;
+
+            /* augmentation */
+            augment(a);
+            /* augmentation end */
+
+            /* adoption */
+            while ((np = orphan_first))
+            {
+              np_next = np->next;
+              np->next = NULL;
+
+              while ((np = orphan_first))
+              {
+                orphan_first = np->next;
+                i = np->ptr;
+                nodeptr_block->Delete(np);
+                if (!orphan_first) orphan_last = NULL;
+                if (i->is_sink) process_sink_orphan(i);
+                else            process_source_orphan(i);
+              }
+
+              orphan_first = np_next;
+            }
+            /* adoption end */
+          }
+          else current_node = NULL;
+        }
+
+        delete nodeptr_block;
+
+        return flow;
+      }
+
+      /***********************************************************************/
+
+      Graph::termtype Graph::what_segment(node_id i)
+      {
+        if (((node*)i)->parent && !((node*)i)->is_sink) return SOURCE;
+        return SINK;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorLBSP.cpp b/src/algorithms/LBSP/BackgroundSubtractorLBSP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d8444703ec30563d87a01a5bb7e786328865cc0e
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorLBSP.cpp
@@ -0,0 +1,84 @@
+#include <iostream>
+#include <iomanip>
+#include <exception>
+
+#include <opencv2/imgproc/imgproc.hpp>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#endif
+
+#include "BackgroundSubtractorLBSP.h"
+#include "DistanceUtils.h"
+#include "RandUtils.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+#ifndef SIZE_MAX
+# if __WORDSIZE == 64
+#  define SIZE_MAX		(18446744073709551615UL)
+# else
+#  define SIZE_MAX		(4294967295U)
+# endif
+#endif
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      // local define used to determine the default median blur kernel size
+      const int DEFAULT_MEDIAN_BLUR_KERNEL_SIZE = 9;
+
+      BackgroundSubtractorLBSP::BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nLBSPThresholdOffset)
+        : m_nImgChannels(0)
+        , m_nImgType(0)
+        , m_nLBSPThresholdOffset(nLBSPThresholdOffset)
+        , m_fRelLBSPThreshold(fRelLBSPThreshold)
+        , m_nTotPxCount(0)
+        , m_nTotRelevantPxCount(0)
+        , m_nFrameIndex(SIZE_MAX)
+        , m_nFramesSinceLastReset(0)
+        , m_nModelResetCooldown(0)
+        , m_aPxIdxLUT(nullptr)
+        , m_aPxInfoLUT(nullptr)
+        , m_nDefaultMedianBlurKernelSize(DEFAULT_MEDIAN_BLUR_KERNEL_SIZE)
+        , m_bInitialized(false)
+        , m_bAutoModelResetEnabled(true)
+        , m_bUsingMovingCamera(false)
+        , nDebugCoordX(0), nDebugCoordY(0) {
+        CV_Assert(m_fRelLBSPThreshold >= 0);
+      }
+
+      BackgroundSubtractorLBSP::~BackgroundSubtractorLBSP() {}
+
+      void BackgroundSubtractorLBSP::initialize(const cv::Mat& oInitImg) {
+        this->initialize(oInitImg, cv::Mat());
+      }
+
+      /*cv::AlgorithmInfo* BackgroundSubtractorLBSP::info() const {
+        return nullptr;
+      }*/
+
+      cv::Mat BackgroundSubtractorLBSP::getROICopy() const {
+        return m_oROI.clone();
+      }
+
+      void BackgroundSubtractorLBSP::setROI(cv::Mat& oROI) {
+        LBSP::validateROI(oROI);
+        CV_Assert(cv::countNonZero(oROI) > 0);
+        if (m_bInitialized) {
+          cv::Mat oLatestBackgroundImage;
+          getBackgroundImage(oLatestBackgroundImage);
+          initialize(oLatestBackgroundImage, oROI);
+        }
+        else
+          m_oROI = oROI.clone();
+      }
+
+      void BackgroundSubtractorLBSP::setAutomaticModelReset(bool bVal) {
+        m_bAutoModelResetEnabled = bVal;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorLBSP.h b/src/algorithms/LBSP/BackgroundSubtractorLBSP.h
new file mode 100644
index 0000000000000000000000000000000000000000..3744b8c3358a58c2265644e4bed5a5ec3b0d014b
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorLBSP.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include <opencv2/features2d/features2d.hpp>
+#include <opencv2/video/background_segm.hpp>
+
+#include "LBSP.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*!
+        Local Binary Similarity Pattern (LBSP)-based change detection algorithm (abstract version/base class).
+
+        For more details on the different parameters, see P.-L. St-Charles and G.-A. Bilodeau, "Improving Background
+        Subtraction using Local Binary Similarity Patterns", in WACV 2014, or G.-A. Bilodeau et al, "Change Detection
+        in Feature Space Using Local Binary Similarity Patterns", in CRV 2013.
+
+        This algorithm is currently NOT thread-safe.
+      */
+      class BackgroundSubtractorLBSP : public cv::BackgroundSubtractor {
+      public:
+        //! full constructor
+        BackgroundSubtractorLBSP(float fRelLBSPThreshold, size_t nLBSPThresholdOffset = 0);
+        //! default destructor
+        virtual ~BackgroundSubtractorLBSP();
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg);
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) = 0;
+        //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
+        virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = 0) = 0;
+        //! unused, always returns nullptr
+        //virtual cv::AlgorithmInfo* info() const;
+        //! returns a copy of the ROI used for descriptor extraction
+        virtual cv::Mat getROICopy() const;
+        //! sets the ROI to be used for descriptor extraction (note: this function will reinit the model and return the usable ROI)
+        virtual void setROI(cv::Mat& oROI);
+        //! turns automatic model reset on or off
+        void setAutomaticModelReset(bool);
+
+      protected:
+        struct PxInfoBase {
+          int nImgCoord_Y;
+          int nImgCoord_X;
+          size_t nModelIdx;
+        };
+        //! background model ROI used for LBSP descriptor extraction (specific to the input image size)
+        cv::Mat m_oROI;
+        //! input image size
+        cv::Size m_oImgSize;
+        //! input image channel size
+        size_t m_nImgChannels;
+        //! input image type
+        int m_nImgType;
+        //! LBSP internal threshold offset value, used to reduce texture noise in dark regions
+        const size_t m_nLBSPThresholdOffset;
+        //! LBSP relative internal threshold (kept here since we don't keep an LBSP object)
+        const float m_fRelLBSPThreshold;
+        //! total number of pixels (depends on the input frame size) & total number of relevant pixels
+        size_t m_nTotPxCount, m_nTotRelevantPxCount;
+        //! current frame index, frame count since last model reset & model reset cooldown counters
+        size_t m_nFrameIndex, m_nFramesSinceLastReset, m_nModelResetCooldown;
+        //! pre-allocated internal LBSP threshold values LUT for all possible 8-bit intensities
+        size_t m_anLBSPThreshold_8bitLUT[UCHAR_MAX + 1];
+        //! internal pixel index LUT for all relevant analysis regions (based on the provided ROI)
+        size_t* m_aPxIdxLUT;
+        //! internal pixel info LUT for all possible pixel indexes
+        PxInfoBase* m_aPxInfoLUT;
+        //! default kernel size for median blur post-proc filtering
+        const int m_nDefaultMedianBlurKernelSize;
+        //! specifies whether the algorithm is fully initialized or not
+        bool m_bInitialized;
+        //! specifies whether automatic model resets are enabled or not
+        bool m_bAutoModelResetEnabled;
+        //! specifies whether the camera is considered moving or not
+        bool m_bUsingMovingCamera;
+        //! copy of latest pixel intensities (used when refreshing model)
+        cv::Mat m_oLastColorFrame;
+        //! copy of latest descriptors (used when refreshing model)
+        cv::Mat m_oLastDescFrame;
+        //! the foreground mask generated by the method at [t-1]
+        cv::Mat m_oLastFGMask;
+
+      public:
+        // ######## DEBUG PURPOSES ONLY ##########
+        int nDebugCoordX, nDebugCoordY;
+        std::string sDebugName;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorLBSP_.cpp b/src/algorithms/LBSP/BackgroundSubtractorLBSP_.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a343d53bea68878df053a706cbdb0dc22369a6d
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorLBSP_.cpp
@@ -0,0 +1,78 @@
+#include <iostream>
+#include <iomanip>
+#include <exception>
+
+#include <opencv2/imgproc/imgproc.hpp>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#endif
+
+#include "BackgroundSubtractorLBSP_.h"
+#include "DistanceUtils.h"
+#include "RandUtils.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      // local define used to determine the default median blur kernel size
+      const int DEFAULT_MEDIAN_BLUR_KERNEL_SIZE = 9;
+
+      BackgroundSubtractorLBSP_::BackgroundSubtractorLBSP_(float fRelLBSPThreshold, size_t nLBSPThresholdOffset)
+        : m_nImgChannels(0)
+        , m_nImgType(0)
+        , m_nLBSPThresholdOffset(nLBSPThresholdOffset)
+        , m_fRelLBSPThreshold(fRelLBSPThreshold)
+        , m_nTotPxCount(0)
+        , m_nTotRelevantPxCount(0)
+        , m_nFrameIndex(SIZE_MAX)
+        , m_nFramesSinceLastReset(0)
+        , m_nModelResetCooldown(0)
+        , m_aPxIdxLUT(nullptr)
+        , m_aPxInfoLUT(nullptr)
+        , m_nDefaultMedianBlurKernelSize(DEFAULT_MEDIAN_BLUR_KERNEL_SIZE)
+        , m_bInitialized(false)
+        , m_bAutoModelResetEnabled(true)
+        , m_bUsingMovingCamera(false)
+        , m_nDebugCoordX(0)
+        , m_nDebugCoordY(0)
+        , m_pDebugFS(nullptr) {
+        CV_Assert(m_fRelLBSPThreshold >= 0);
+      }
+
+      BackgroundSubtractorLBSP_::~BackgroundSubtractorLBSP_() {}
+
+      void BackgroundSubtractorLBSP_::initialize(const cv::Mat& oInitImg) {
+        this->initialize(oInitImg, cv::Mat());
+      }
+      /*
+      cv::AlgorithmInfo* BackgroundSubtractorLBSP_::info() const {
+          return nullptr;
+      }
+      */
+      cv::Mat BackgroundSubtractorLBSP_::getROICopy() const {
+        return m_oROI.clone();
+      }
+
+      void BackgroundSubtractorLBSP_::setROI(cv::Mat& oROI) {
+        LBSP_::validateROI(oROI);
+        CV_Assert(cv::countNonZero(oROI) > 0);
+        if (m_bInitialized) {
+          cv::Mat oLatestBackgroundImage;
+          getBackgroundImage(oLatestBackgroundImage);
+          initialize(oLatestBackgroundImage, oROI);
+        }
+        else
+          m_oROI = oROI.clone();
+      }
+
+      void BackgroundSubtractorLBSP_::setAutomaticModelReset(bool bVal) {
+        m_bAutoModelResetEnabled = bVal;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorLBSP_.h b/src/algorithms/LBSP/BackgroundSubtractorLBSP_.h
new file mode 100644
index 0000000000000000000000000000000000000000..79d6df927c4071bdd1e48ed63d62ca2dcf25793e
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorLBSP_.h
@@ -0,0 +1,101 @@
+#pragma once
+
+#include <opencv2/features2d/features2d.hpp>
+#include <opencv2/video/background_segm.hpp>
+
+#include "LBSP_.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*!
+          Local Binary Similarity Pattern (LBSP)-based change detection algorithm (abstract version/base class).
+
+          For more details on the different parameters, see P.-L. St-Charles and G.-A. Bilodeau, "Improving Background
+          Subtraction using Local Binary Similarity Patterns", in WACV 2014, or G.-A. Bilodeau et al, "Change Detection
+          in Feature Space Using Local Binary Similarity Patterns", in CRV 2013.
+
+          This algorithm is currently NOT thread-safe.
+      */
+      class BackgroundSubtractorLBSP_ : public cv::BackgroundSubtractor {
+      public:
+        //! full constructor
+        BackgroundSubtractorLBSP_(float fRelLBSPThreshold, size_t nLBSPThresholdOffset = 0);
+        //! default destructor
+        virtual ~BackgroundSubtractorLBSP_();
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg);
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) = 0;
+        //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
+        virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRate = 0) = 0;
+        //! unused, always returns nullptr
+        //virtual cv::AlgorithmInfo* info() const;
+        //! returns a copy of the ROI used for descriptor extraction
+        virtual cv::Mat getROICopy() const;
+        //! sets the ROI to be used for descriptor extraction (note: this function will reinit the model and return the usable ROI)
+        virtual void setROI(cv::Mat& oROI);
+        //! turns automatic model reset on or off
+        void setAutomaticModelReset(bool);
+
+      protected:
+        struct PxInfoBase {
+          int nImgCoord_Y;
+          int nImgCoord_X;
+          size_t nModelIdx;
+        };
+        //! background model ROI used for LBSP descriptor extraction (specific to the input image size)
+        cv::Mat m_oROI;
+        //! input image size
+        cv::Size m_oImgSize;
+        //! input image channel size
+        size_t m_nImgChannels;
+        //! input image type
+        int m_nImgType;
+        //! LBSP internal threshold offset value, used to reduce texture noise in dark regions
+        const size_t m_nLBSPThresholdOffset;
+        //! LBSP relative internal threshold (kept here since we don't keep an LBSP object)
+        const float m_fRelLBSPThreshold;
+        //! total number of pixels (depends on the input frame size) & total number of relevant pixels
+        size_t m_nTotPxCount, m_nTotRelevantPxCount;
+        //! current frame index, frame count since last model reset & model reset cooldown counters
+        size_t m_nFrameIndex, m_nFramesSinceLastReset, m_nModelResetCooldown;
+        //! pre-allocated internal LBSP threshold values LUT for all possible 8-bit intensities
+        size_t m_anLBSPThreshold_8bitLUT[UCHAR_MAX + 1];
+        //! internal pixel index LUT for all relevant analysis regions (based on the provided ROI)
+        size_t* m_aPxIdxLUT;
+        //! internal pixel info LUT for all possible pixel indexes
+        PxInfoBase* m_aPxInfoLUT;
+        //! default kernel size for median blur post-proc filtering
+        const int m_nDefaultMedianBlurKernelSize;
+        //! specifies whether the algorithm is fully initialized or not
+        bool m_bInitialized;
+        //! specifies whether automatic model resets are enabled or not
+        bool m_bAutoModelResetEnabled;
+        //! specifies whether the camera is considered moving or not
+        bool m_bUsingMovingCamera;
+        //! copy of latest pixel intensities (used when refreshing model)
+        cv::Mat m_oLastColorFrame;
+        //! copy of latest descriptors (used when refreshing model)
+        cv::Mat m_oLastDescFrame;
+        //! the foreground mask generated by the method at [t-1]
+        cv::Mat m_oLastFGMask;
+
+      private:
+        //! copy constructor -- disabled since this class (and its children) use lots of dynamic structs based on raw pointers
+        BackgroundSubtractorLBSP_(const BackgroundSubtractorLBSP_&);
+        //! assignment operator -- disabled since this class (and its children) use lots of dynamic structs based on raw pointers
+        BackgroundSubtractorLBSP_& operator=(const BackgroundSubtractorLBSP_&);
+
+      public:
+        // ######## DEBUG PURPOSES ONLY ##########
+        int m_nDebugCoordX, m_nDebugCoordY;
+        std::string m_sDebugName;
+        cv::FileStorage* m_pDebugFS;
+      };
+    }
+  }
+}
diff --git a/package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp b/src/algorithms/LBSP/BackgroundSubtractorLOBSTER.cpp
similarity index 96%
rename from package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp
rename to src/algorithms/LBSP/BackgroundSubtractorLOBSTER.cpp
index 9648c5c1bf8ebc2dfef307ebc5aafc7d11bd42a1..58c81c5fae0d0c83e78d99e88ebeb88b804afce5 100644
--- a/package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp
+++ b/src/algorithms/LBSP/BackgroundSubtractorLOBSTER.cpp
@@ -1,26 +1,15 @@
-/*
-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.
+#include <iostream>
+#include <iomanip>
 
-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.
+#include <opencv2/imgproc/imgproc.hpp>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#endif
 
-You should have received a copy of the GNU General Public License
-along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
-*/
 #include "BackgroundSubtractorLOBSTER.h"
-#include "DistanceUtils.h"
 #include "RandUtils.h"
-#include <iostream>
-#include <opencv2/imgproc/imgproc.hpp>
-#include <opencv2/highgui/highgui.hpp>
-#include <iomanip>
+
+using namespace bgslibrary::algorithms::lbsp;
 
 BackgroundSubtractorLOBSTER::BackgroundSubtractorLOBSTER(float fRelLBSPThreshold
   , size_t nLBSPThresholdOffset
diff --git a/src/algorithms/LBSP/BackgroundSubtractorLOBSTER.h b/src/algorithms/LBSP/BackgroundSubtractorLOBSTER.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7860a188628fdb3ec7c35a0bd703910ddeed9a5
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorLOBSTER.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "BackgroundSubtractorLBSP.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      //! defines the default value for BackgroundSubtractorLBSP::m_fRelLBSPThreshold
+      const float BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD = 0.365f;
+      //! defines the default value for BackgroundSubtractorLBSP::m_nLBSPThresholdOffset
+      const int BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD = 0;
+      //! defines the default value for BackgroundSubtractorLOBSTER::m_nDescDistThreshold
+      const int BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD = 4;
+      //! defines the default value for BackgroundSubtractorLOBSTER::m_nColorDistThreshold
+      const int BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD = 30;
+      //! defines the default value for BackgroundSubtractorLOBSTER::m_nBGSamples
+      const int BGSLOBSTER_DEFAULT_NB_BG_SAMPLES = 35;
+      //! defines the default value for BackgroundSubtractorLOBSTER::m_nRequiredBGSamples
+      const int BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES = 2;
+      //! defines the default value for the learning rate passed to BackgroundSubtractorLOBSTER::operator()
+      const int BGSLOBSTER_DEFAULT_LEARNING_RATE = 16;
+
+      /*!
+        LOcal Binary Similarity segmenTER (LOBSTER) change detection algorithm.
+
+        Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
+        For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
+
+        For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles and
+        G.-A. Bilodeau, "Improving Background Subtraction using Local Binary Similarity Patterns", in WACV 2014.
+
+        This algorithm is currently NOT thread-safe.
+      */
+      class BackgroundSubtractorLOBSTER : public BackgroundSubtractorLBSP {
+      public:
+        //! full constructor
+        BackgroundSubtractorLOBSTER(float fRelLBSPThreshold = BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
+          size_t nLBSPThresholdOffset = BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD,
+          size_t nDescDistThreshold = BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD,
+          size_t nColorDistThreshold = BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD,
+          size_t nBGSamples = BGSLOBSTER_DEFAULT_NB_BG_SAMPLES,
+          size_t nRequiredBGSamples = BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES);
+        //! default destructor
+        virtual ~BackgroundSubtractorLOBSTER();
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
+        //! refreshes all samples based on the last analyzed frame
+        virtual void refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate = false);
+        //! primary model update function; the learning param is reinterpreted as an integer and should be > 0 (smaller values == faster adaptation)
+        virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = BGSLOBSTER_DEFAULT_LEARNING_RATE);
+        //! returns a copy of the latest reconstructed background image
+        void getBackgroundImage(cv::OutputArray backgroundImage) const;
+        //! returns a copy of the latest reconstructed background descriptors image
+        virtual void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
+
+      protected:
+        //! absolute color distance threshold
+        const size_t m_nColorDistThreshold;
+        //! absolute descriptor distance threshold
+        const size_t m_nDescDistThreshold;
+        //! number of different samples per pixel/block to be taken from input frames to build the background model
+        const size_t m_nBGSamples;
+        //! number of similar samples needed to consider the current pixel/block as 'background'
+        const size_t m_nRequiredBGSamples;
+        //! background model pixel intensity samples
+        std::vector<cv::Mat> m_voBGColorSamples;
+        //! background model descriptors samples
+        std::vector<cv::Mat> m_voBGDescSamples;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorPAWCS.cpp b/src/algorithms/LBSP/BackgroundSubtractorPAWCS.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..19bc1e7039cbe566ab5f618a3bc02a5c419dcc30
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorPAWCS.cpp
@@ -0,0 +1,1347 @@
+#include <iostream>
+#include <iomanip>
+
+#include <opencv2/imgproc/imgproc.hpp>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#endif
+
+#include "BackgroundSubtractorPAWCS.h"
+#include "RandUtils.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*
+       *
+       * Intrinsic configuration parameters are defined here; tuning these for better
+       * performance should not be required in most cases -- although improvements in
+       * very specific scenarios are always possible.
+       *
+       */
+       //! parameter used for dynamic distance threshold adjustments ('R(x)')
+      const float FEEDBACK_R_VAR = 0.01f;
+      //! parameters used to adjust the variation step size of 'v(x)'
+      const float FEEDBACK_V_INCR = 1.000f;
+      const float FEEDBACK_V_DECR = 0.100f;
+      //! parameters used to scale dynamic learning rate adjustments  ('T(x)')
+      const float FEEDBACK_T_DECR = 0.2500f;
+      const float FEEDBACK_T_INCR = 0.5000f;
+      const float FEEDBACK_T_LOWER = 1.0000f;
+      const float FEEDBACK_T_UPPER = 256.00f;
+      //! parameters used to define 'unstable' regions, based on segm noise/bg dynamics and local dist threshold values
+      const float UNSTABLE_REG_RATIO_MIN = 0.100f;
+      const float UNSTABLE_REG_RDIST_MIN = 3.000f;
+      //! parameters used to scale the relative LBSP intensity threshold used for internal comparisons
+      const float LBSPDESC_RATIO_MIN = 0.100f;
+      const float LBSPDESC_RATIO_MAX = 0.500f;
+      //! parameters used to trigger auto model resets in our frame-level component
+      const int FRAMELEVEL_MIN_L1DIST_THRES = 45;
+      const float FRAMELEVEL_MIN_CDIST_THRES = (FRAMELEVEL_MIN_L1DIST_THRES / 10);
+      const int FRAMELEVEL_DOWNSAMPLE_RATIO = 8;
+      //! parameters used to downscale gword maps & scale thresholds to make comparisons easier
+      const int GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO = 2;
+      const int GWORD_DEFAULT_NB_INIT_SAMPL_PASSES = 2;
+      const int GWORD_DESC_THRES_BITS_MATCH_FACTOR = 4;
+
+      // local define used to specify the default frame size (320x240 = QVGA)
+      #define DEFAULT_FRAME_SIZE cv::Size(320,240)
+      // local define used to specify the default lword/gword update rate (16 = like vibe)
+      const int DEFAULT_RESAMPLING_RATE = 16;
+      // local define used to specify the bootstrap window size for faster model stabilization
+      const int DEFAULT_BOOTSTRAP_WIN_SIZE = 500;
+      // local define for the amount of weight offset to apply to words, making sure new words aren't always better than old ones
+      const float DEFAULT_LWORD_WEIGHT_OFFSET = (DEFAULT_BOOTSTRAP_WIN_SIZE * 2);
+      // local define used to set the default local word occurrence increment
+      const int DEFAULT_LWORD_OCC_INCR = 1;
+      // local define for the maximum weight a word can achieve before cutting off occ incr (used to make sure model stays good for long-term uses)
+      const float DEFAULT_LWORD_MAX_WEIGHT = 1.0f;
+      // local define for the initial weight of a new word (used to make sure old words aren't worse off than new seeds)
+      const double DEFAULT_LWORD_INIT_WEIGHT = (1.0f / DEFAULT_LWORD_WEIGHT_OFFSET);
+      // local define used to specify the desc dist threshold offset used for unstable regions
+      #define UNSTAB_DESC_DIST_OFFSET (m_nDescDistThresholdOffset)
+      // local define used to specify the min descriptor bit count for flat regions
+      #define FLAT_REGION_BIT_COUNT (s_nDescMaxDataRange_1ch/8)
+
+      static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX;
+      static const size_t s_nDescMaxDataRange_1ch = LBSP_::DESC_SIZE * 8;
+      static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch * 3;
+      static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch * 3;
+
+      BackgroundSubtractorPAWCS::BackgroundSubtractorPAWCS(float fRelLBSPThreshold
+        , size_t nDescDistThresholdOffset
+        , size_t nMinColorDistThreshold
+        , size_t nMaxNbWords
+        , size_t nSamplesForMovingAvgs)
+        : BackgroundSubtractorLBSP_(fRelLBSPThreshold)
+        , m_nMinColorDistThreshold(nMinColorDistThreshold)
+        , m_nDescDistThresholdOffset(nDescDistThresholdOffset)
+        , m_nMaxLocalWords(nMaxNbWords)
+        , m_nCurrLocalWords(0)
+        , m_nMaxGlobalWords(nMaxNbWords / 2)
+        , m_nCurrGlobalWords(0)
+        , m_nSamplesForMovingAvgs(nSamplesForMovingAvgs)
+        , m_fLastNonFlatRegionRatio(0.0f)
+        , m_nMedianBlurKernelSize(m_nDefaultMedianBlurKernelSize)
+        , m_nDownSampledROIPxCount(0)
+        , m_nLocalWordWeightOffset(DEFAULT_LWORD_WEIGHT_OFFSET)
+        , m_apLocalWordDict(nullptr)
+        , m_aLocalWordList_1ch(nullptr)
+        , m_pLocalWordListIter_1ch(nullptr)
+        , m_aLocalWordList_3ch(nullptr)
+        , m_pLocalWordListIter_3ch(nullptr)
+        , m_apGlobalWordDict(nullptr)
+        , m_aGlobalWordList_1ch(nullptr)
+        , m_pGlobalWordListIter_1ch(nullptr)
+        , m_aGlobalWordList_3ch(nullptr)
+        , m_pGlobalWordListIter_3ch(nullptr)
+        , m_aPxInfoLUT_PAWCS(nullptr) {
+        CV_Assert(m_nMaxLocalWords > 0 && m_nMaxGlobalWords > 0);
+      }
+
+      BackgroundSubtractorPAWCS::~BackgroundSubtractorPAWCS() {
+        CleanupDictionaries();
+      }
+
+      void BackgroundSubtractorPAWCS::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) {
+        // == init
+        CV_Assert(!oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0);
+        CV_Assert(oInitImg.isContinuous());
+        CV_Assert(oInitImg.type() == CV_8UC3 || oInitImg.type() == CV_8UC1);
+        if (oInitImg.type() == CV_8UC3) {
+          std::vector<cv::Mat> voInitImgChannels;
+          cv::split(oInitImg, voInitImgChannels);
+          if (!cv::countNonZero((voInitImgChannels[0] != voInitImgChannels[1]) | (voInitImgChannels[2] != voInitImgChannels[1])))
+            std::cout << std::endl << "\tBackgroundSubtractorPAWCS : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance." << std::endl;
+        }
+        cv::Mat oNewBGROI;
+        if (oROI.empty() && (m_oROI.empty() || oROI.size() != oInitImg.size())) {
+          oNewBGROI.create(oInitImg.size(), CV_8UC1);
+          oNewBGROI = cv::Scalar_<uchar>(UCHAR_MAX);
+        }
+        else if (oROI.empty())
+          oNewBGROI = m_oROI;
+        else {
+          CV_Assert(oROI.size() == oInitImg.size() && oROI.type() == CV_8UC1);
+          CV_Assert(cv::countNonZero((oROI < UCHAR_MAX)&(oROI > 0)) == 0);
+          oNewBGROI = oROI.clone();
+          cv::Mat oTempROI;
+          cv::dilate(oNewBGROI, oTempROI, cv::Mat(), cv::Point(-1, -1), LBSP_::PATCH_SIZE / 2);
+          cv::bitwise_or(oNewBGROI, oTempROI / 2, oNewBGROI);
+        }
+        const size_t nOrigROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
+        CV_Assert(nOrigROIPxCount > 0);
+        LBSP_::validateROI(oNewBGROI);
+        const size_t nFinalROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
+        CV_Assert(nFinalROIPxCount > 0);
+        CleanupDictionaries();
+        m_oROI = oNewBGROI;
+        m_oImgSize = oInitImg.size();
+        m_nImgType = oInitImg.type();
+        m_nImgChannels = oInitImg.channels();
+        m_nTotPxCount = m_oImgSize.area();
+        m_nTotRelevantPxCount = nFinalROIPxCount;
+        m_nFrameIndex = 0;
+        m_nFramesSinceLastReset = 0;
+        m_nModelResetCooldown = 0;
+        m_bUsingMovingCamera = false;
+        m_oDownSampledFrameSize_MotionAnalysis = cv::Size(m_oImgSize.width / FRAMELEVEL_DOWNSAMPLE_RATIO, m_oImgSize.height / FRAMELEVEL_DOWNSAMPLE_RATIO);
+        m_oDownSampledFrameSize_GlobalWordLookup = cv::Size(m_oImgSize.width / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO, m_oImgSize.height / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO);
+        cv::resize(m_oROI, m_oDownSampledROI_MotionAnalysis, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
+        m_fLastNonFlatRegionRatio = 0.0f;
+        m_nCurrLocalWords = m_nMaxLocalWords;
+        if (nOrigROIPxCount >= m_nTotPxCount / 2 && (int)m_nTotPxCount >= DEFAULT_FRAME_SIZE.area()) {
+          const float fRegionSizeScaleFactor = (float)m_nTotPxCount / DEFAULT_FRAME_SIZE.area();
+          const int nRawMedianBlurKernelSize = std::min((int)floor(0.5f + fRegionSizeScaleFactor) + m_nDefaultMedianBlurKernelSize, m_nDefaultMedianBlurKernelSize + 4);
+          m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
+          m_nCurrGlobalWords = m_nMaxGlobalWords;
+          m_oDownSampledROI_MotionAnalysis |= UCHAR_MAX / 2;
+        }
+        else {
+          const float fRegionSizeScaleFactor = (float)nOrigROIPxCount / DEFAULT_FRAME_SIZE.area();
+          const int nRawMedianBlurKernelSize = std::min((int)floor(0.5f + m_nDefaultMedianBlurKernelSize*fRegionSizeScaleFactor * 2) + (m_nDefaultMedianBlurKernelSize - 4), m_nDefaultMedianBlurKernelSize);
+          m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
+          m_nCurrGlobalWords = std::min((size_t)std::pow(m_nMaxGlobalWords*fRegionSizeScaleFactor, 2) + 1, m_nMaxGlobalWords);
+        }
+        if (m_nImgChannels == 1) {
+          m_nCurrLocalWords = std::max(m_nCurrLocalWords / 2, (size_t)1);
+          m_nCurrGlobalWords = std::max(m_nCurrGlobalWords / 2, (size_t)1);
+        }
+        m_nDownSampledROIPxCount = (size_t)cv::countNonZero(m_oDownSampledROI_MotionAnalysis);
+        m_nLocalWordWeightOffset = DEFAULT_LWORD_WEIGHT_OFFSET;
+        m_oIllumUpdtRegionMask.create(m_oImgSize, CV_8UC1);
+        m_oIllumUpdtRegionMask = cv::Scalar_<uchar>(0);
+        m_oUpdateRateFrame.create(m_oImgSize, CV_32FC1);
+        m_oUpdateRateFrame = cv::Scalar(FEEDBACK_T_LOWER);
+        m_oDistThresholdFrame.create(m_oImgSize, CV_32FC1);
+        m_oDistThresholdFrame = cv::Scalar(2.0f);
+        m_oDistThresholdVariationFrame.create(m_oImgSize, CV_32FC1);
+        m_oDistThresholdVariationFrame = cv::Scalar(FEEDBACK_V_INCR * 10);
+        m_oMeanMinDistFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanMinDistFrame_LT = cv::Scalar(0.0f);
+        m_oMeanMinDistFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanMinDistFrame_ST = cv::Scalar(0.0f);
+        m_oMeanDownSampledLastDistFrame_LT.create(m_oDownSampledFrameSize_MotionAnalysis, CV_32FC((int)m_nImgChannels));
+        m_oMeanDownSampledLastDistFrame_LT = cv::Scalar(0.0f);
+        m_oMeanDownSampledLastDistFrame_ST.create(m_oDownSampledFrameSize_MotionAnalysis, CV_32FC((int)m_nImgChannels));
+        m_oMeanDownSampledLastDistFrame_ST = cv::Scalar(0.0f);
+        m_oMeanRawSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanRawSegmResFrame_LT = cv::Scalar(0.0f);
+        m_oMeanRawSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanRawSegmResFrame_ST = cv::Scalar(0.0f);
+        m_oMeanFinalSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanFinalSegmResFrame_LT = cv::Scalar(0.0f);
+        m_oMeanFinalSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanFinalSegmResFrame_ST = cv::Scalar(0.0f);
+        m_oUnstableRegionMask.create(m_oImgSize, CV_8UC1);
+        m_oUnstableRegionMask = cv::Scalar_<uchar>(0);
+        m_oBlinksFrame.create(m_oImgSize, CV_8UC1);
+        m_oBlinksFrame = cv::Scalar_<uchar>(0);
+        m_oDownSampledFrame_MotionAnalysis.create(m_oDownSampledFrameSize_MotionAnalysis, CV_8UC((int)m_nImgChannels));
+        m_oDownSampledFrame_MotionAnalysis = cv::Scalar_<uchar>::all(0);
+        m_oLastColorFrame.create(m_oImgSize, CV_8UC((int)m_nImgChannels));
+        m_oLastColorFrame = cv::Scalar_<uchar>::all(0);
+        m_oLastDescFrame.create(m_oImgSize, CV_16UC((int)m_nImgChannels));
+        m_oLastDescFrame = cv::Scalar_<ushort>::all(0);
+        m_oLastRawFGMask.create(m_oImgSize, CV_8UC1);
+        m_oLastRawFGMask = cv::Scalar_<uchar>(0);
+        m_oLastFGMask.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask = cv::Scalar_<uchar>(0);
+        m_oLastFGMask_dilated.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask_dilated = cv::Scalar_<uchar>(0);
+        m_oLastFGMask_dilated_inverted.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask_dilated_inverted = cv::Scalar_<uchar>(0);
+        m_oFGMask_FloodedHoles.create(m_oImgSize, CV_8UC1);
+        m_oFGMask_FloodedHoles = cv::Scalar_<uchar>(0);
+        m_oFGMask_PreFlood.create(m_oImgSize, CV_8UC1);
+        m_oFGMask_PreFlood = cv::Scalar_<uchar>(0);
+        m_oCurrRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
+        m_oCurrRawFGBlinkMask = cv::Scalar_<uchar>(0);
+        m_oLastRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
+        m_oLastRawFGBlinkMask = cv::Scalar_<uchar>(0);
+        m_oTempGlobalWordWeightDiffFactor.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
+        m_oTempGlobalWordWeightDiffFactor = cv::Scalar(-0.1f);
+        m_oMorphExStructElement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
+        m_aPxIdxLUT = new size_t[m_nTotRelevantPxCount];
+        memset(m_aPxIdxLUT, 0, sizeof(size_t)*m_nTotRelevantPxCount);
+        m_aPxInfoLUT_PAWCS = new PxInfo_PAWCS[m_nTotPxCount];
+        memset(m_aPxInfoLUT_PAWCS, 0, sizeof(PxInfo_PAWCS)*m_nTotPxCount);
+        m_aPxInfoLUT = m_aPxInfoLUT_PAWCS;
+        m_apLocalWordDict = new LocalWordBase*[m_nTotRelevantPxCount*m_nCurrLocalWords];
+        memset(m_apLocalWordDict, 0, sizeof(LocalWordBase*)*m_nTotRelevantPxCount*m_nCurrLocalWords);
+        m_apGlobalWordDict = new GlobalWordBase*[m_nCurrGlobalWords];
+        memset(m_apGlobalWordDict, 0, sizeof(GlobalWordBase*)*m_nCurrGlobalWords);
+        if (m_nImgChannels == 1) {
+          CV_DbgAssert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width && m_oLastColorFrame.step.p[1] == 1);
+          CV_DbgAssert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
+          m_aLocalWordList_1ch = new LocalWord_1ch[m_nTotRelevantPxCount*m_nCurrLocalWords];
+          memset(m_aLocalWordList_1ch, 0, sizeof(LocalWord_1ch)*m_nTotRelevantPxCount*m_nCurrLocalWords);
+          m_pLocalWordListIter_1ch = m_aLocalWordList_1ch;
+          m_aGlobalWordList_1ch = new GlobalWord_1ch[m_nCurrGlobalWords];
+          m_pGlobalWordListIter_1ch = m_aGlobalWordList_1ch;
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 3);
+          for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
+            if (m_oROI.data[nPxIter]) {
+              m_aPxIdxLUT[nModelIter] = nPxIter;
+              m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
+              m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
+              m_aPxInfoLUT_PAWCS[nPxIter].nModelIdx = nModelIter;
+              m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx = (size_t)((m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)*m_oDownSampledFrameSize_GlobalWordLookup.width + (m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)) * 4;
+              m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT = new GlobalWordBase*[m_nCurrGlobalWords];
+              for (size_t nGlobalWordIdxIter = 0; nGlobalWordIdxIter < m_nCurrGlobalWords; ++nGlobalWordIdxIter)
+                m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordIdxIter] = &(m_aGlobalWordList_1ch[nGlobalWordIdxIter]);
+              m_oLastColorFrame.data[nPxIter] = oInitImg.data[nPxIter];
+              const size_t nDescIter = nPxIter * 2;
+              LBSP_::computeGrayscaleDescriptor(oInitImg, oInitImg.data[nPxIter], m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxIter]], *((ushort*)(m_oLastDescFrame.data + nDescIter)));
+              ++nModelIter;
+            }
+          }
+        }
+        else { //m_nImgChannels==3
+          CV_DbgAssert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width * 3 && m_oLastColorFrame.step.p[1] == 3);
+          CV_DbgAssert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
+          m_aLocalWordList_3ch = new LocalWord_3ch[m_nTotRelevantPxCount*m_nCurrLocalWords];
+          memset(m_aLocalWordList_3ch, 0, sizeof(LocalWord_3ch)*m_nTotRelevantPxCount*m_nCurrLocalWords);
+          m_pLocalWordListIter_3ch = m_aLocalWordList_3ch;
+          m_aGlobalWordList_3ch = new GlobalWord_3ch[m_nCurrGlobalWords];
+          m_pGlobalWordListIter_3ch = m_aGlobalWordList_3ch;
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold);
+          for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
+            if (m_oROI.data[nPxIter]) {
+              m_aPxIdxLUT[nModelIter] = nPxIter;
+              m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
+              m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
+              m_aPxInfoLUT_PAWCS[nPxIter].nModelIdx = nModelIter;
+              m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx = (size_t)((m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)*m_oDownSampledFrameSize_GlobalWordLookup.width + (m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X / GWORD_LOOKUP_MAPS_DOWNSAMPLE_RATIO)) * 4;
+              m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT = new GlobalWordBase*[m_nCurrGlobalWords];
+              for (size_t nGlobalWordIdxIter = 0; nGlobalWordIdxIter < m_nCurrGlobalWords; ++nGlobalWordIdxIter)
+                m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordIdxIter] = &(m_aGlobalWordList_3ch[nGlobalWordIdxIter]);
+              const size_t nPxRGBIter = nPxIter * 3;
+              const size_t nDescRGBIter = nPxRGBIter * 2;
+              for (size_t c = 0; c < 3; ++c) {
+                m_oLastColorFrame.data[nPxRGBIter + c] = oInitImg.data[nPxRGBIter + c];
+                LBSP_::computeSingleRGBDescriptor(oInitImg, oInitImg.data[nPxRGBIter + c], m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxRGBIter + c]], ((ushort*)(m_oLastDescFrame.data + nDescRGBIter))[c]);
+              }
+              ++nModelIter;
+            }
+          }
+        }
+        m_bInitialized = true;
+        refreshModel(1, 0);
+      }
+
+      void BackgroundSubtractorPAWCS::refreshModel(size_t nBaseOccCount, float fOccDecrFrac, bool bForceFGUpdate) {
+        // == refresh
+        CV_Assert(m_bInitialized);
+        CV_Assert(fOccDecrFrac >= 0.0f && fOccDecrFrac <= 1.0f);
+        if (m_nImgChannels == 1) {
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
+              const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+              const size_t nFloatIter = nPxIter * 4;
+              uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+              const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+              const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
+              const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
+              // == refresh: local decr
+              if (fOccDecrFrac > 0.0f) {
+                for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                  LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                  if (pCurrLocalWord)
+                    pCurrLocalWord->nOccurrences -= (size_t)(fOccDecrFrac*pCurrLocalWord->nOccurrences);
+                }
+              }
+              const size_t nCurrWordOccIncr = DEFAULT_LWORD_OCC_INCR;
+              const size_t nTotLocalSamplingIterCount = (s_nSamplesInitPatternWidth*s_nSamplesInitPatternHeight) * 2;
+              for (size_t nLocalSamplingIter = 0; nLocalSamplingIter < nTotLocalSamplingIterCount; ++nLocalSamplingIter) {
+                // == refresh: local resampling
+                int nSampleImgCoord_Y, nSampleImgCoord_X;
+                getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+                const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+                if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nSamplePxIdx]) {
+                  const uchar nSampleColor = m_oLastColorFrame.data[nSamplePxIdx];
+                  const size_t nSampleDescIdx = nSamplePxIdx * 2;
+                  const ushort nSampleIntraDesc = *((ushort*)(m_oLastDescFrame.data + nSampleDescIdx));
+                  bool bFoundUninitd = false;
+                  size_t nLocalWordIdx;
+                  for (nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                    LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                    if (pCurrLocalWord
+                      && L1dist(nSampleColor, pCurrLocalWord->oFeature.anColor[0]) <= nCurrColorDistThreshold
+                      && hdist(nSampleIntraDesc, pCurrLocalWord->oFeature.anDesc[0]) <= nCurrDescDistThreshold) {
+                      pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
+                      pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                      break;
+                    }
+                    else if (!pCurrLocalWord)
+                      bFoundUninitd = true;
+                  }
+                  if (nLocalWordIdx == m_nCurrLocalWords) {
+                    nLocalWordIdx = m_nCurrLocalWords - 1;
+                    LocalWord_1ch* pCurrLocalWord = bFoundUninitd ? m_pLocalWordListIter_1ch++ : (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                    pCurrLocalWord->oFeature.anColor[0] = nSampleColor;
+                    pCurrLocalWord->oFeature.anDesc[0] = nSampleIntraDesc;
+                    pCurrLocalWord->nOccurrences = nBaseOccCount;
+                    pCurrLocalWord->nFirstOcc = m_nFrameIndex;
+                    pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                    m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
+                  }
+                  while (nLocalWordIdx > 0 && (!m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1] || GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset) > GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1], m_nFrameIndex, m_nLocalWordWeightOffset))) {
+                    std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+                    --nLocalWordIdx;
+                  }
+                }
+              }
+              CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
+              for (size_t nLocalWordIdx = 1; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                // == refresh: local random resampling
+                LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                if (!pCurrLocalWord) {
+                  const size_t nRandLocalWordIdx = (rand() % nLocalWordIdx);
+                  const LocalWord_1ch* pRefLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nRandLocalWordIdx];
+                  const int nRandColorOffset = (rand() % (nCurrColorDistThreshold + 1)) - (int)nCurrColorDistThreshold / 2;
+                  pCurrLocalWord = m_pLocalWordListIter_1ch++;
+                  pCurrLocalWord->oFeature.anColor[0] = cv::saturate_cast<uchar>((int)pRefLocalWord->oFeature.anColor[0] + nRandColorOffset);
+                  pCurrLocalWord->oFeature.anDesc[0] = pRefLocalWord->oFeature.anDesc[0];
+                  pCurrLocalWord->nOccurrences = std::max((size_t)(pRefLocalWord->nOccurrences*((float)(m_nCurrLocalWords - nLocalWordIdx) / m_nCurrLocalWords)), (size_t)1);
+                  pCurrLocalWord->nFirstOcc = m_nFrameIndex;
+                  pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                  m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
+                }
+              }
+            }
+          }
+          CV_Assert(m_aLocalWordList_1ch == (m_pLocalWordListIter_1ch - m_nTotRelevantPxCount*m_nCurrLocalWords));
+          cv::Mat oGlobalDictPresenceLookupMap(m_oImgSize, CV_8UC1, cv::Scalar_<uchar>(0));
+          size_t nPxIterIncr = std::max(m_nTotPxCount / m_nCurrGlobalWords, (size_t)1);
+          for (size_t nSamplingPasses = 0; nSamplingPasses < GWORD_DEFAULT_NB_INIT_SAMPL_PASSES; ++nSamplingPasses) {
+            for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+              // == refresh: global resampling
+              const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+              if ((nPxIter%nPxIterIncr) == 0) { // <=(m_nCurrGlobalWords) gwords from (m_nCurrGlobalWords) equally spaced pixels
+                if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
+                  const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+                  const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+                  const size_t nFloatIter = nPxIter * 4;
+                  uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+                  const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+                  const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
+                  const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
+                  CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
+                  const LocalWord_1ch* pRefBestLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx];
+                  const float fRefBestLocalWordWeight = GetLocalWordWeight(pRefBestLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                  const uchar nRefBestLocalWordDescBITS = (uchar)popcount(pRefBestLocalWord->oFeature.anDesc[0]);
+                  bool bFoundUninitd = false;
+                  size_t nGlobalWordIdx;
+                  for (nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
+                    GlobalWord_1ch* pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
+                    if (pCurrGlobalWord
+                      && L1dist(pCurrGlobalWord->oFeature.anColor[0], pRefBestLocalWord->oFeature.anColor[0]) <= nCurrColorDistThreshold
+                      && L1dist(nRefBestLocalWordDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
+                      break;
+                    else if (!pCurrGlobalWord)
+                      bFoundUninitd = true;
+                  }
+                  if (nGlobalWordIdx == m_nCurrGlobalWords) {
+                    nGlobalWordIdx = m_nCurrGlobalWords - 1;
+                    GlobalWord_1ch* pCurrGlobalWord = bFoundUninitd ? m_pGlobalWordListIter_1ch++ : (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
+                    pCurrGlobalWord->oFeature.anColor[0] = pRefBestLocalWord->oFeature.anColor[0];
+                    pCurrGlobalWord->oFeature.anDesc[0] = pRefBestLocalWord->oFeature.anDesc[0];
+                    pCurrGlobalWord->nDescBITS = nRefBestLocalWordDescBITS;
+                    pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
+                    pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+                    pCurrGlobalWord->fLatestWeight = 0.0f;
+                    m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
+                  }
+                  float& fCurrGlobalWordLocalWeight = *(float*)(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fCurrGlobalWordLocalWeight < fRefBestLocalWordWeight) {
+                    m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight += fRefBestLocalWordWeight;
+                    fCurrGlobalWordLocalWeight += fRefBestLocalWordWeight;
+                  }
+                  oGlobalDictPresenceLookupMap.data[nPxIter] = UCHAR_MAX;
+                  while (nGlobalWordIdx > 0 && (!m_apGlobalWordDict[nGlobalWordIdx - 1] || m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)) {
+                    std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
+                    --nGlobalWordIdx;
+                  }
+                }
+              }
+            }
+            nPxIterIncr = std::max(nPxIterIncr / 3, (size_t)1);
+          }
+          for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
+            GlobalWord_1ch* pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[nGlobalWordIdx];
+            if (!pCurrGlobalWord) {
+              pCurrGlobalWord = m_pGlobalWordListIter_1ch++;
+              pCurrGlobalWord->oFeature.anColor[0] = 0;
+              pCurrGlobalWord->oFeature.anDesc[0] = 0;
+              pCurrGlobalWord->nDescBITS = 0;
+              pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
+              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+              pCurrGlobalWord->fLatestWeight = 0.0f;
+              m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
+            }
+          }
+          CV_Assert((size_t)(m_pGlobalWordListIter_1ch - m_aGlobalWordList_1ch) == m_nCurrGlobalWords && m_aGlobalWordList_1ch == (m_pGlobalWordListIter_1ch - m_nCurrGlobalWords));
+        }
+        else { //m_nImgChannels==3
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
+              const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+              const size_t nFloatIter = nPxIter * 4;
+              uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+              const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+              const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
+              const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
+              // == refresh: local decr
+              if (fOccDecrFrac > 0.0f) {
+                for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                  LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                  if (pCurrLocalWord)
+                    pCurrLocalWord->nOccurrences -= (size_t)(fOccDecrFrac*pCurrLocalWord->nOccurrences);
+                }
+              }
+              const size_t nCurrWordOccIncr = DEFAULT_LWORD_OCC_INCR;
+              const size_t nTotLocalSamplingIterCount = (s_nSamplesInitPatternWidth*s_nSamplesInitPatternHeight) * 2;
+              for (size_t nLocalSamplingIter = 0; nLocalSamplingIter < nTotLocalSamplingIterCount; ++nLocalSamplingIter) {
+                // == refresh: local resampling
+                int nSampleImgCoord_Y, nSampleImgCoord_X;
+                getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X, m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+                const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+                if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nSamplePxIdx]) {
+                  const size_t nSamplePxRGBIdx = nSamplePxIdx * 3;
+                  const size_t nSampleDescRGBIdx = nSamplePxRGBIdx * 2;
+                  const uchar* const anSampleColor = m_oLastColorFrame.data + nSamplePxRGBIdx;
+                  const ushort* const anSampleIntraDesc = ((ushort*)(m_oLastDescFrame.data + nSampleDescRGBIdx));
+                  bool bFoundUninitd = false;
+                  size_t nLocalWordIdx;
+                  for (nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                    LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                    if (pCurrLocalWord
+                      && cmixdist<3>(anSampleColor, pCurrLocalWord->oFeature.anColor) <= nCurrTotColorDistThreshold
+                      && hdist<3>(anSampleIntraDesc, pCurrLocalWord->oFeature.anDesc) <= nCurrTotDescDistThreshold) {
+                      pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
+                      pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                      break;
+                    }
+                    else if (!pCurrLocalWord)
+                      bFoundUninitd = true;
+                  }
+                  if (nLocalWordIdx == m_nCurrLocalWords) {
+                    nLocalWordIdx = m_nCurrLocalWords - 1;
+                    LocalWord_3ch* pCurrLocalWord = bFoundUninitd ? m_pLocalWordListIter_3ch++ : (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                    for (size_t c = 0; c < 3; ++c) {
+                      pCurrLocalWord->oFeature.anColor[c] = anSampleColor[c];
+                      pCurrLocalWord->oFeature.anDesc[c] = anSampleIntraDesc[c];
+                    }
+                    pCurrLocalWord->nOccurrences = nBaseOccCount;
+                    pCurrLocalWord->nFirstOcc = m_nFrameIndex;
+                    pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                    m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
+                  }
+                  while (nLocalWordIdx > 0 && (!m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1] || GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset) > GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1], m_nFrameIndex, m_nLocalWordWeightOffset))) {
+                    std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+                    --nLocalWordIdx;
+                  }
+                }
+              }
+              CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
+              for (size_t nLocalWordIdx = 1; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+                // == refresh: local random resampling
+                LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+                if (!pCurrLocalWord) {
+                  const size_t nRandLocalWordIdx = (rand() % nLocalWordIdx);
+                  const LocalWord_3ch* pRefLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nRandLocalWordIdx];
+                  const int nRandColorOffset = (rand() % (nCurrTotColorDistThreshold / 3 + 1)) - (int)(nCurrTotColorDistThreshold / 6);
+                  pCurrLocalWord = m_pLocalWordListIter_3ch++;
+                  for (size_t c = 0; c < 3; ++c) {
+                    pCurrLocalWord->oFeature.anColor[c] = cv::saturate_cast<uchar>((int)pRefLocalWord->oFeature.anColor[c] + nRandColorOffset);
+                    pCurrLocalWord->oFeature.anDesc[c] = pRefLocalWord->oFeature.anDesc[c];
+                  }
+                  pCurrLocalWord->nOccurrences = std::max((size_t)(pRefLocalWord->nOccurrences*((float)(m_nCurrLocalWords - nLocalWordIdx) / m_nCurrLocalWords)), (size_t)1);
+                  pCurrLocalWord->nFirstOcc = m_nFrameIndex;
+                  pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                  m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx] = pCurrLocalWord;
+                }
+              }
+            }
+          }
+          CV_Assert(m_aLocalWordList_3ch == (m_pLocalWordListIter_3ch - m_nTotRelevantPxCount*m_nCurrLocalWords));
+          cv::Mat oGlobalDictPresenceLookupMap(m_oImgSize, CV_8UC1, cv::Scalar_<uchar>(0));
+          size_t nPxIterIncr = std::max(m_nTotPxCount / m_nCurrGlobalWords, (size_t)1);
+          for (size_t nSamplingPasses = 0; nSamplingPasses < GWORD_DEFAULT_NB_INIT_SAMPL_PASSES; ++nSamplingPasses) {
+            for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+              // == refresh: global resampling
+              const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+              if ((nPxIter%nPxIterIncr) == 0) { // <=(m_nCurrGlobalWords) gwords from (m_nCurrGlobalWords) equally spaced pixels
+                if (bForceFGUpdate || !m_oLastFGMask_dilated.data[nPxIter]) {
+                  const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+                  const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+                  const size_t nFloatIter = nPxIter * 4;
+                  uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+                  const float fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+                  const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
+                  const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
+                  CV_Assert(m_apLocalWordDict[nLocalDictIdx]);
+                  const LocalWord_3ch* pRefBestLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx];
+                  const float fRefBestLocalWordWeight = GetLocalWordWeight(pRefBestLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                  const uchar nRefBestLocalWordDescBITS = (uchar)popcount<3>(pRefBestLocalWord->oFeature.anDesc);
+                  bool bFoundUninitd = false;
+                  size_t nGlobalWordIdx;
+                  for (nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
+                    GlobalWord_3ch* pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
+                    if (pCurrGlobalWord
+                      && L1dist(nRefBestLocalWordDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
+                      && cmixdist<3>(pRefBestLocalWord->oFeature.anColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
+                      break;
+                    else if (!pCurrGlobalWord)
+                      bFoundUninitd = true;
+                  }
+                  if (nGlobalWordIdx == m_nCurrGlobalWords) {
+                    nGlobalWordIdx = m_nCurrGlobalWords - 1;
+                    GlobalWord_3ch* pCurrGlobalWord = bFoundUninitd ? m_pGlobalWordListIter_3ch++ : (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
+                    for (size_t c = 0; c < 3; ++c) {
+                      pCurrGlobalWord->oFeature.anColor[c] = pRefBestLocalWord->oFeature.anColor[c];
+                      pCurrGlobalWord->oFeature.anDesc[c] = pRefBestLocalWord->oFeature.anDesc[c];
+                    }
+                    pCurrGlobalWord->nDescBITS = nRefBestLocalWordDescBITS;
+                    pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
+                    pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+                    pCurrGlobalWord->fLatestWeight = 0.0f;
+                    m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
+                  }
+                  float& fCurrGlobalWordLocalWeight = *(float*)(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fCurrGlobalWordLocalWeight < fRefBestLocalWordWeight) {
+                    m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight += fRefBestLocalWordWeight;
+                    fCurrGlobalWordLocalWeight += fRefBestLocalWordWeight;
+                  }
+                  oGlobalDictPresenceLookupMap.data[nPxIter] = UCHAR_MAX;
+                  while (nGlobalWordIdx > 0 && (!m_apGlobalWordDict[nGlobalWordIdx - 1] || m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)) {
+                    std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
+                    --nGlobalWordIdx;
+                  }
+                }
+              }
+            }
+            nPxIterIncr = std::max(nPxIterIncr / 3, (size_t)1);
+          }
+          for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
+            GlobalWord_3ch* pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[nGlobalWordIdx];
+            if (!pCurrGlobalWord) {
+              pCurrGlobalWord = m_pGlobalWordListIter_3ch++;
+              for (size_t c = 0; c < 3; ++c) {
+                pCurrGlobalWord->oFeature.anColor[c] = 0;
+                pCurrGlobalWord->oFeature.anDesc[c] = 0;
+              }
+              pCurrGlobalWord->nDescBITS = 0;
+              pCurrGlobalWord->oSpatioOccMap.create(m_oDownSampledFrameSize_GlobalWordLookup, CV_32FC1);
+              pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+              pCurrGlobalWord->fLatestWeight = 0.0f;
+              m_apGlobalWordDict[nGlobalWordIdx] = pCurrGlobalWord;
+            }
+          }
+          CV_Assert((size_t)(m_pGlobalWordListIter_3ch - m_aGlobalWordList_3ch) == m_nCurrGlobalWords && m_aGlobalWordList_3ch == (m_pGlobalWordListIter_3ch - m_nCurrGlobalWords));
+        }
+        for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+          // == refresh: per-px global word sort
+          const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+          const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+          float fLastGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[0]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+          for (size_t nGlobalWordLUTIdx = 1; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+            const float fCurrGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+            if (fCurrGlobalWordLocalWeight > fLastGlobalWordLocalWeight)
+              std::swap(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx], m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx - 1]);
+            else
+              fLastGlobalWordLocalWeight = fCurrGlobalWordLocalWeight;
+          }
+        }
+      }
+
+      void BackgroundSubtractorPAWCS::apply(cv::InputArray _image, cv::OutputArray _fgmask, double learningRateOverride) {
+        // == process
+        CV_Assert(m_bInitialized);
+        cv::Mat oInputImg = _image.getMat();
+        CV_Assert(oInputImg.type() == m_nImgType && oInputImg.size() == m_oImgSize);
+        CV_Assert(oInputImg.isContinuous());
+        _fgmask.create(m_oImgSize, CV_8UC1);
+        cv::Mat oCurrFGMask = _fgmask.getMat();
+        memset(oCurrFGMask.data, 0, oCurrFGMask.cols*oCurrFGMask.rows);
+        const bool bBootstrapping = ++m_nFrameIndex <= DEFAULT_BOOTSTRAP_WIN_SIZE;
+        const size_t nCurrSamplesForMovingAvg_LT = bBootstrapping ? m_nSamplesForMovingAvgs / 2 : m_nSamplesForMovingAvgs;
+        const size_t nCurrSamplesForMovingAvg_ST = nCurrSamplesForMovingAvg_LT / 4;
+        const float fRollAvgFactor_LT = 1.0f / std::min(m_nFrameIndex, nCurrSamplesForMovingAvg_LT);
+        const float fRollAvgFactor_ST = 1.0f / std::min(m_nFrameIndex, nCurrSamplesForMovingAvg_ST);
+        const size_t nCurrGlobalWordUpdateRate = bBootstrapping ? DEFAULT_RESAMPLING_RATE / 2 : DEFAULT_RESAMPLING_RATE;
+        size_t nFlatRegionCount = 0;
+        if (m_nImgChannels == 1) {
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            const size_t nDescIter = nPxIter * 2;
+            const size_t nFloatIter = nPxIter * 4;
+            const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+            const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+            const uchar nCurrColor = oInputImg.data[nPxIter];
+            uchar& nLastColor = m_oLastColorFrame.data[nPxIter];
+            ushort& nLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nDescIter));
+            size_t nMinColorDist = s_nColorMaxDataRange_1ch;
+            size_t nMinDescDist = s_nDescMaxDataRange_1ch;
+            float& fCurrMeanRawSegmRes_LT = *(float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter);
+            float& fCurrMeanRawSegmRes_ST = *(float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter);
+            float& fCurrMeanFinalSegmRes_LT = *(float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter);
+            float& fCurrMeanFinalSegmRes_ST = *(float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter);
+            float& fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+            float& fCurrDistThresholdVariationFactor = *(float*)(m_oDistThresholdVariationFrame.data + nFloatIter);
+            float& fCurrLearningRate = *(float*)(m_oUpdateRateFrame.data + nFloatIter);
+            float& fCurrMeanMinDist_LT = *(float*)(m_oMeanMinDistFrame_LT.data + nFloatIter);
+            float& fCurrMeanMinDist_ST = *(float*)(m_oMeanMinDistFrame_ST.data + nFloatIter);
+            const float fBestLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
+            const float fLocalWordsWeightSumThreshold = fBestLocalWordWeight / (fCurrDistThresholdFactor * 2);
+            uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+            uchar& nCurrRegionIllumUpdtVal = m_oIllumUpdtRegionMask.data[nPxIter];
+            uchar& nCurrRegionSegmVal = oCurrFGMask.data[nPxIter];
+            const bool bCurrRegionIsROIBorder = m_oROI.data[nPxIter] < UCHAR_MAX;
+            const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
+            const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
+            ushort nCurrInterDesc, nCurrIntraDesc;
+            LBSP_::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nCurrIntraDesc);
+            const uchar nCurrIntraDescBITS = (uchar)popcount(nCurrIntraDesc);
+            const bool bCurrRegionIsFlat = nCurrIntraDescBITS < FLAT_REGION_BIT_COUNT;
+            if (bCurrRegionIsFlat)
+              ++nFlatRegionCount;
+            const size_t nCurrWordOccIncr = (DEFAULT_LWORD_OCC_INCR + m_nModelResetCooldown) << int(bCurrRegionIsFlat || bBootstrapping);
+            const size_t nCurrLocalWordUpdateRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : bCurrRegionIsFlat ? (size_t)ceil(fCurrLearningRate + FEEDBACK_T_LOWER) / 2 : (size_t)ceil(fCurrLearningRate);
+            const size_t nCurrColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) / 2;
+            const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET);
+            size_t nLocalWordIdx = 0;
+            float fPotentialLocalWordsWeightSum = 0.0f;
+            float fLastLocalWordWeight = FLT_MAX;
+            while (nLocalWordIdx < m_nCurrLocalWords && fPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
+              LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+              const float fCurrLocalWordWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+              {
+                const size_t nColorDist = L1dist(nCurrColor, pCurrLocalWord->oFeature.anColor[0]);
+                const size_t nIntraDescDist = hdist(nCurrIntraDesc, pCurrLocalWord->oFeature.anDesc[0]);
+                LBSP_::computeGrayscaleDescriptor(oInputImg, pCurrLocalWord->oFeature.anColor[0], nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[0]], nCurrInterDesc);
+                const size_t nInterDescDist = hdist(nCurrInterDesc, pCurrLocalWord->oFeature.anDesc[0]);
+                const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
+                if ((!bCurrRegionIsUnstable || bCurrRegionIsFlat || bCurrRegionIsROIBorder)
+                  && nColorDist <= nCurrColorDistThreshold
+                  && nColorDist >= nCurrColorDistThreshold / 2
+                  && nIntraDescDist <= nCurrDescDistThreshold / 2
+                  && (rand() % (nCurrRegionIllumUpdtVal ? (nCurrLocalWordUpdateRate / 2 + 1) : nCurrLocalWordUpdateRate)) == 0) {
+                  // == illum updt
+                  pCurrLocalWord->oFeature.anColor[0] = nCurrColor;
+                  pCurrLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
+                  m_oIllumUpdtRegionMask.data[nPxIter - 1] = 1 & m_oROI.data[nPxIter - 1];
+                  m_oIllumUpdtRegionMask.data[nPxIter + 1] = 1 & m_oROI.data[nPxIter + 1];
+                  m_oIllumUpdtRegionMask.data[nPxIter] = 2;
+                }
+                if (nDescDist <= nCurrDescDistThreshold && nColorDist <= nCurrColorDistThreshold) {
+                  fPotentialLocalWordsWeightSum += fCurrLocalWordWeight;
+                  pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                  if ((!m_oLastFGMask.data[nPxIter] || m_bUsingMovingCamera) && fCurrLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                    pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
+                  nMinColorDist = std::min(nMinColorDist, nColorDist);
+                  nMinDescDist = std::min(nMinDescDist, nDescDist);
+                }
+              }
+              if (fCurrLocalWordWeight > fLastLocalWordWeight) {
+                std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+              }
+              else
+                fLastLocalWordWeight = fCurrLocalWordWeight;
+              ++nLocalWordIdx;
+            }
+            while (nLocalWordIdx < m_nCurrLocalWords) {
+              const float fCurrLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
+              if (fCurrLocalWordWeight > fLastLocalWordWeight) {
+                std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+              }
+              else
+                fLastLocalWordWeight = fCurrLocalWordWeight;
+              ++nLocalWordIdx;
+            }
+            if (fPotentialLocalWordsWeightSum >= fLocalWordsWeightSumThreshold || bCurrRegionIsROIBorder) {
+              // == background
+              const float fNormalizedMinDist = std::max((float)nMinColorDist / s_nColorMaxDataRange_1ch, (float)nMinDescDist / s_nDescMaxDataRange_1ch);
+              fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT);
+              fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST);
+              if ((rand() % nCurrLocalWordUpdateRate) == 0) {
+                size_t nGlobalWordLUTIdx;
+                GlobalWord_1ch* pCurrGlobalWord = nullptr;
+                for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+                  pCurrGlobalWord = (GlobalWord_1ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
+                  if (L1dist(pCurrGlobalWord->oFeature.anColor[0], nCurrColor) <= nCurrColorDistThreshold
+                    && L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
+                    break;
+                }
+                if (nGlobalWordLUTIdx != m_nCurrGlobalWords || (rand() % (nCurrLocalWordUpdateRate * 2)) == 0) {
+                  if (nGlobalWordLUTIdx == m_nCurrGlobalWords) {
+                    pCurrGlobalWord = (GlobalWord_1ch*)m_apGlobalWordDict[m_nCurrGlobalWords - 1];
+                    pCurrGlobalWord->oFeature.anColor[0] = nCurrColor;
+                    pCurrGlobalWord->oFeature.anDesc[0] = nCurrIntraDesc;
+                    pCurrGlobalWord->nDescBITS = nCurrIntraDescBITS;
+                    pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+                    pCurrGlobalWord->fLatestWeight = 0.0f;
+                  }
+                  float& fCurrGlobalWordLocalWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fCurrGlobalWordLocalWeight < fPotentialLocalWordsWeightSum) {
+                    pCurrGlobalWord->fLatestWeight += fPotentialLocalWordsWeightSum;
+                    fCurrGlobalWordLocalWeight += fPotentialLocalWordsWeightSum;
+                  }
+                }
+              }
+            }
+            else {
+              // == foreground
+              const float fNormalizedMinDist = std::max(std::max((float)nMinColorDist / s_nColorMaxDataRange_1ch, (float)nMinDescDist / s_nDescMaxDataRange_1ch), (fLocalWordsWeightSumThreshold - fPotentialLocalWordsWeightSum) / fLocalWordsWeightSumThreshold);
+              fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
+              fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
+              if (bCurrRegionIsFlat || (rand() % nCurrLocalWordUpdateRate) == 0) {
+                size_t nGlobalWordLUTIdx;
+                GlobalWord_1ch* pCurrGlobalWord;
+                for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+                  pCurrGlobalWord = (GlobalWord_1ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
+                  if (L1dist(pCurrGlobalWord->oFeature.anColor[0], nCurrColor) <= nCurrColorDistThreshold
+                    && L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR)
+                    break;
+                }
+                if (nGlobalWordLUTIdx == m_nCurrGlobalWords)
+                  nCurrRegionSegmVal = UCHAR_MAX;
+                else {
+                  const float fGlobalWordLocalizedWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fPotentialLocalWordsWeightSum + fGlobalWordLocalizedWeight / (bCurrRegionIsFlat ? 2 : 4) < fLocalWordsWeightSumThreshold)
+                    nCurrRegionSegmVal = UCHAR_MAX;
+                }
+              }
+              else
+                nCurrRegionSegmVal = UCHAR_MAX;
+              if (fPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
+                const size_t nNewLocalWordIdx = m_nCurrLocalWords - 1;
+                LocalWord_1ch* pNewLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nNewLocalWordIdx];
+                pNewLocalWord->oFeature.anColor[0] = nCurrColor;
+                pNewLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
+                pNewLocalWord->nOccurrences = nCurrWordOccIncr;
+                pNewLocalWord->nFirstOcc = m_nFrameIndex;
+                pNewLocalWord->nLastOcc = m_nFrameIndex;
+              }
+            }
+            // == neighb updt
+            if ((!nCurrRegionSegmVal && (rand() % nCurrLocalWordUpdateRate) == 0) || bCurrRegionIsROIBorder || m_bUsingMovingCamera) {
+              //if((!nCurrRegionSegmVal && (rand()%(nCurrRegionIllumUpdtVal?(nCurrLocalWordUpdateRate/2+1):nCurrLocalWordUpdateRate))==0) || bCurrRegionIsROIBorder) {
+              int nSampleImgCoord_Y, nSampleImgCoord_X;
+              if (bCurrRegionIsFlat || bCurrRegionIsROIBorder || m_bUsingMovingCamera)
+                getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+              else
+                getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+              const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+              if (m_oROI.data[nSamplePxIdx]) {
+                const size_t nNeighborLocalDictIdx = m_aPxInfoLUT_PAWCS[nSamplePxIdx].nModelIdx*m_nCurrLocalWords;
+                size_t nNeighborLocalWordIdx = 0;
+                float fNeighborPotentialLocalWordsWeightSum = 0.0f;
+                while (nNeighborLocalWordIdx < m_nCurrLocalWords && fNeighborPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
+                  LocalWord_1ch* pNeighborLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
+                  const size_t nNeighborColorDist = L1dist(nCurrColor, pNeighborLocalWord->oFeature.anColor[0]);
+                  const size_t nNeighborIntraDescDist = hdist(nCurrIntraDesc, pNeighborLocalWord->oFeature.anDesc[0]);
+                  const bool bNeighborRegionIsFlat = popcount(pNeighborLocalWord->oFeature.anDesc[0]) < FLAT_REGION_BIT_COUNT;
+                  const size_t nNeighborWordOccIncr = bNeighborRegionIsFlat ? nCurrWordOccIncr * 2 : nCurrWordOccIncr;
+                  if (nNeighborColorDist <= nCurrColorDistThreshold && nNeighborIntraDescDist <= nCurrDescDistThreshold) {
+                    const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                    fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
+                    pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                    if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                      pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
+                  }
+                  else if (!oCurrFGMask.data[nSamplePxIdx] && bCurrRegionIsFlat && (bBootstrapping || (rand() % nCurrLocalWordUpdateRate) == 0)) {
+                    const size_t nSampleDescIdx = nSamplePxIdx * 2;
+                    ushort& nNeighborLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nSampleDescIdx));
+                    const size_t nNeighborLastIntraDescDist = hdist(nCurrIntraDesc, nNeighborLastIntraDesc);
+                    if (nNeighborColorDist <= nCurrColorDistThreshold && nNeighborLastIntraDescDist <= nCurrDescDistThreshold / 2) {
+                      const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                      fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
+                      pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                      if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                        pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
+                      pNeighborLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
+                    }
+                  }
+                  ++nNeighborLocalWordIdx;
+                }
+                if (fNeighborPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
+                  nNeighborLocalWordIdx = m_nCurrLocalWords - 1;
+                  LocalWord_1ch* pNeighborLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
+                  pNeighborLocalWord->oFeature.anColor[0] = nCurrColor;
+                  pNeighborLocalWord->oFeature.anDesc[0] = nCurrIntraDesc;
+                  pNeighborLocalWord->nOccurrences = nCurrWordOccIncr;
+                  pNeighborLocalWord->nFirstOcc = m_nFrameIndex;
+                  pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                }
+              }
+            }
+            if (nCurrRegionIllumUpdtVal)
+              nCurrRegionIllumUpdtVal -= 1;
+            // == feedback adj
+            bCurrRegionIsUnstable = fCurrDistThresholdFactor > UNSTABLE_REG_RDIST_MIN || (fCurrMeanRawSegmRes_LT - fCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (fCurrMeanRawSegmRes_ST - fCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN;
+            if (m_oLastFGMask.data[nPxIter] || (std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && nCurrRegionSegmVal))
+              fCurrLearningRate = std::min(fCurrLearningRate + FEEDBACK_T_INCR / (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST)*fCurrDistThresholdVariationFactor), FEEDBACK_T_UPPER);
+            else
+              fCurrLearningRate = std::max(fCurrLearningRate - FEEDBACK_T_DECR*fCurrDistThresholdVariationFactor / std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST), FEEDBACK_T_LOWER);
+            if (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
+              (fCurrDistThresholdVariationFactor) += bBootstrapping ? FEEDBACK_V_INCR * 2 : FEEDBACK_V_INCR;
+            else
+              fCurrDistThresholdVariationFactor = std::max(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR*((bBootstrapping || bCurrRegionIsFlat) ? 2 : m_oLastFGMask.data[nPxIter] ? 0.5f : 1), FEEDBACK_V_DECR);
+            if (fCurrDistThresholdFactor < std::pow(1.0f + std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) * 2, 2))
+              fCurrDistThresholdFactor += FEEDBACK_R_VAR*(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR);
+            else
+              fCurrDistThresholdFactor = std::max(fCurrDistThresholdFactor - FEEDBACK_R_VAR / fCurrDistThresholdVariationFactor, 1.0f);
+            nLastIntraDesc = nCurrIntraDesc;
+            nLastColor = nCurrColor;
+          }
+        }
+        else { //m_nImgChannels==3
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            const size_t nPxRGBIter = nPxIter * 3;
+            const size_t nDescRGBIter = nPxRGBIter * 2;
+            const size_t nFloatIter = nPxIter * 4;
+            const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+            const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+            const uchar* const anCurrColor = oInputImg.data + nPxRGBIter;
+            uchar* anLastColor = m_oLastColorFrame.data + nPxRGBIter;
+            ushort* anLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nDescRGBIter));
+            size_t nMinTotColorDist = s_nColorMaxDataRange_3ch;
+            size_t nMinTotDescDist = s_nDescMaxDataRange_3ch;
+            float& fCurrMeanRawSegmRes_LT = *(float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter);
+            float& fCurrMeanRawSegmRes_ST = *(float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter);
+            float& fCurrMeanFinalSegmRes_LT = *(float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter);
+            float& fCurrMeanFinalSegmRes_ST = *(float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter);
+            float& fCurrDistThresholdFactor = *(float*)(m_oDistThresholdFrame.data + nFloatIter);
+            float& fCurrDistThresholdVariationFactor = *(float*)(m_oDistThresholdVariationFrame.data + nFloatIter);
+            float& fCurrLearningRate = *(float*)(m_oUpdateRateFrame.data + nFloatIter);
+            float& fCurrMeanMinDist_LT = *(float*)(m_oMeanMinDistFrame_LT.data + nFloatIter);
+            float& fCurrMeanMinDist_ST = *(float*)(m_oMeanMinDistFrame_ST.data + nFloatIter);
+            const float fBestLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
+            const float fLocalWordsWeightSumThreshold = fBestLocalWordWeight / (fCurrDistThresholdFactor * 2);
+            uchar& bCurrRegionIsUnstable = m_oUnstableRegionMask.data[nPxIter];
+            uchar& nCurrRegionIllumUpdtVal = m_oIllumUpdtRegionMask.data[nPxIter];
+            uchar& nCurrRegionSegmVal = oCurrFGMask.data[nPxIter];
+            const bool bCurrRegionIsROIBorder = m_oROI.data[nPxIter] < UCHAR_MAX;
+            const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
+            const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
+            ushort anCurrInterDesc[3], anCurrIntraDesc[3];
+            const size_t anCurrIntraLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]] };
+            LBSP_::computeRGBDescriptor(oInputImg, anCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrIntraLBSPThresholds, anCurrIntraDesc);
+            const uchar nCurrIntraDescBITS = (uchar)popcount<3>(anCurrIntraDesc);
+            const bool bCurrRegionIsFlat = nCurrIntraDescBITS < FLAT_REGION_BIT_COUNT * 2;
+            if (bCurrRegionIsFlat)
+              ++nFlatRegionCount;
+            const size_t nCurrWordOccIncr = (DEFAULT_LWORD_OCC_INCR + m_nModelResetCooldown) << int(bCurrRegionIsFlat || bBootstrapping);
+            const size_t nCurrLocalWordUpdateRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : bCurrRegionIsFlat ? (size_t)ceil(fCurrLearningRate + FEEDBACK_T_LOWER) / 2 : (size_t)ceil(fCurrLearningRate);
+            const size_t nCurrTotColorDistThreshold = (size_t)(sqrt(fCurrDistThresholdFactor)*m_nMinColorDistThreshold) * 3;
+            const size_t nCurrTotDescDistThreshold = (((size_t)1 << ((size_t)floor(fCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (bCurrRegionIsUnstable*UNSTAB_DESC_DIST_OFFSET)) * 3;
+            size_t nLocalWordIdx = 0;
+            float fPotentialLocalWordsWeightSum = 0.0f;
+            float fLastLocalWordWeight = FLT_MAX;
+            while (nLocalWordIdx < m_nCurrLocalWords && fPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
+              LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+              const float fCurrLocalWordWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+              {
+                const size_t nTotColorL1Dist = L1dist<3>(anCurrColor, pCurrLocalWord->oFeature.anColor);
+                const size_t nColorDistortion = cdist<3>(anCurrColor, pCurrLocalWord->oFeature.anColor);
+                const size_t nTotColorMixDist = cmixdist(nTotColorL1Dist, nColorDistortion);
+                const size_t nTotIntraDescDist = hdist<3>(anCurrIntraDesc, pCurrLocalWord->oFeature.anDesc);
+                const size_t anCurrInterLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[0]],m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[1]],m_anLBSPThreshold_8bitLUT[pCurrLocalWord->oFeature.anColor[2]] };
+                LBSP_::computeRGBDescriptor(oInputImg, pCurrLocalWord->oFeature.anColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrInterLBSPThresholds, anCurrInterDesc);
+                const size_t nTotInterDescDist = hdist<3>(anCurrInterDesc, pCurrLocalWord->oFeature.anDesc);
+                const size_t nTotDescDist = (nTotIntraDescDist + nTotInterDescDist) / 2;
+                if ((!bCurrRegionIsUnstable || bCurrRegionIsFlat || bCurrRegionIsROIBorder)
+                  && nTotColorMixDist <= nCurrTotColorDistThreshold
+                  && nTotColorL1Dist >= nCurrTotColorDistThreshold / 2
+                  && nTotIntraDescDist <= nCurrTotDescDistThreshold / 2
+                  && (rand() % (nCurrRegionIllumUpdtVal ? (nCurrLocalWordUpdateRate / 2 + 1) : nCurrLocalWordUpdateRate)) == 0) {
+                  // == illum updt
+                  for (size_t c = 0; c < 3; ++c) {
+                    pCurrLocalWord->oFeature.anColor[c] = anCurrColor[c];
+                    pCurrLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
+                  }
+                  m_oIllumUpdtRegionMask.data[nPxIter - 1] = 1 & m_oROI.data[nPxIter - 1];
+                  m_oIllumUpdtRegionMask.data[nPxIter + 1] = 1 & m_oROI.data[nPxIter + 1];
+                  m_oIllumUpdtRegionMask.data[nPxIter] = 2;
+                }
+                if (nTotDescDist <= nCurrTotDescDistThreshold && nTotColorMixDist <= nCurrTotColorDistThreshold) {
+                  fPotentialLocalWordsWeightSum += fCurrLocalWordWeight;
+                  pCurrLocalWord->nLastOcc = m_nFrameIndex;
+                  if ((!m_oLastFGMask.data[nPxIter] || m_bUsingMovingCamera) && fCurrLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                    pCurrLocalWord->nOccurrences += nCurrWordOccIncr;
+                  nMinTotColorDist = std::min(nMinTotColorDist, nTotColorMixDist);
+                  nMinTotDescDist = std::min(nMinTotDescDist, nTotDescDist);
+                }
+              }
+              if (fCurrLocalWordWeight > fLastLocalWordWeight) {
+                std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+              }
+              else
+                fLastLocalWordWeight = fCurrLocalWordWeight;
+              ++nLocalWordIdx;
+            }
+            while (nLocalWordIdx < m_nCurrLocalWords) {
+              const float fCurrLocalWordWeight = GetLocalWordWeight(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_nFrameIndex, m_nLocalWordWeightOffset);
+              if (fCurrLocalWordWeight > fLastLocalWordWeight) {
+                std::swap(m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx], m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx - 1]);
+              }
+              else
+                fLastLocalWordWeight = fCurrLocalWordWeight;
+              ++nLocalWordIdx;
+            }
+            if (fPotentialLocalWordsWeightSum >= fLocalWordsWeightSumThreshold || bCurrRegionIsROIBorder) {
+              // == background
+              const float fNormalizedMinDist = std::max((float)nMinTotColorDist / s_nColorMaxDataRange_3ch, (float)nMinTotDescDist / s_nDescMaxDataRange_3ch);
+              fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT);
+              fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST);
+              if ((rand() % nCurrLocalWordUpdateRate) == 0) {
+                size_t nGlobalWordLUTIdx;
+                GlobalWord_3ch* pCurrGlobalWord = nullptr;
+                for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+                  pCurrGlobalWord = (GlobalWord_3ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
+                  if (L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
+                    && cmixdist<3>(anCurrColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
+                    break;
+                }
+                if (nGlobalWordLUTIdx != m_nCurrGlobalWords || (rand() % (nCurrLocalWordUpdateRate * 2)) == 0) {
+                  if (nGlobalWordLUTIdx == m_nCurrGlobalWords) {
+                    pCurrGlobalWord = (GlobalWord_3ch*)m_apGlobalWordDict[m_nCurrGlobalWords - 1];
+                    for (size_t c = 0; c < 3; ++c) {
+                      pCurrGlobalWord->oFeature.anColor[c] = anCurrColor[c];
+                      pCurrGlobalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
+                    }
+                    pCurrGlobalWord->nDescBITS = nCurrIntraDescBITS;
+                    pCurrGlobalWord->oSpatioOccMap = cv::Scalar(0.0f);
+                    pCurrGlobalWord->fLatestWeight = 0.0f;
+                  }
+                  float& fCurrGlobalWordLocalWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fCurrGlobalWordLocalWeight < fPotentialLocalWordsWeightSum) {
+                    pCurrGlobalWord->fLatestWeight += fPotentialLocalWordsWeightSum;
+                    fCurrGlobalWordLocalWeight += fPotentialLocalWordsWeightSum;
+                  }
+                }
+              }
+            }
+            else {
+              // == foreground
+              const float fNormalizedMinDist = std::max(std::max((float)nMinTotColorDist / s_nColorMaxDataRange_3ch, (float)nMinTotDescDist / s_nDescMaxDataRange_3ch), (fLocalWordsWeightSumThreshold - fPotentialLocalWordsWeightSum) / fLocalWordsWeightSumThreshold);
+              fCurrMeanMinDist_LT = fCurrMeanMinDist_LT*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              fCurrMeanMinDist_ST = fCurrMeanMinDist_ST*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              fCurrMeanRawSegmRes_LT = fCurrMeanRawSegmRes_LT*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
+              fCurrMeanRawSegmRes_ST = fCurrMeanRawSegmRes_ST*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
+              if (bCurrRegionIsFlat || (rand() % nCurrLocalWordUpdateRate) == 0) {
+                size_t nGlobalWordLUTIdx;
+                GlobalWord_3ch* pCurrGlobalWord;
+                for (nGlobalWordLUTIdx = 0; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+                  pCurrGlobalWord = (GlobalWord_3ch*)m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx];
+                  if (L1dist(nCurrIntraDescBITS, pCurrGlobalWord->nDescBITS) <= nCurrTotDescDistThreshold / GWORD_DESC_THRES_BITS_MATCH_FACTOR
+                    && cmixdist<3>(anCurrColor, pCurrGlobalWord->oFeature.anColor) <= nCurrTotColorDistThreshold)
+                    break;
+                }
+                if (nGlobalWordLUTIdx == m_nCurrGlobalWords)
+                  nCurrRegionSegmVal = UCHAR_MAX;
+                else {
+                  const float fGlobalWordLocalizedWeight = *(float*)(pCurrGlobalWord->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+                  if (fPotentialLocalWordsWeightSum + fGlobalWordLocalizedWeight / (bCurrRegionIsFlat ? 2 : 4) < fLocalWordsWeightSumThreshold)
+                    nCurrRegionSegmVal = UCHAR_MAX;
+                }
+              }
+              else
+                nCurrRegionSegmVal = UCHAR_MAX;
+              if (fPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
+                const size_t nNewLocalWordIdx = m_nCurrLocalWords - 1;
+                LocalWord_3ch* pNewLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nNewLocalWordIdx];
+                for (size_t c = 0; c < 3; ++c) {
+                  pNewLocalWord->oFeature.anColor[c] = anCurrColor[c];
+                  pNewLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
+                }
+                pNewLocalWord->nOccurrences = nCurrWordOccIncr;
+                pNewLocalWord->nFirstOcc = m_nFrameIndex;
+                pNewLocalWord->nLastOcc = m_nFrameIndex;
+              }
+            }
+            // == neighb updt
+            if ((!nCurrRegionSegmVal && (rand() % nCurrLocalWordUpdateRate) == 0) || bCurrRegionIsROIBorder || m_bUsingMovingCamera) {
+              //if((!nCurrRegionSegmVal && (rand()%(nCurrRegionIllumUpdtVal?(nCurrLocalWordUpdateRate/2+1):nCurrLocalWordUpdateRate))==0) || bCurrRegionIsROIBorder) {
+              int nSampleImgCoord_Y, nSampleImgCoord_X;
+              if (bCurrRegionIsFlat || bCurrRegionIsROIBorder || m_bUsingMovingCamera)
+                getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+              else
+                getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP_::PATCH_SIZE / 2, m_oImgSize);
+              const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+              if (m_oROI.data[nSamplePxIdx]) {
+                const size_t nNeighborLocalDictIdx = m_aPxInfoLUT_PAWCS[nSamplePxIdx].nModelIdx*m_nCurrLocalWords;
+                size_t nNeighborLocalWordIdx = 0;
+                float fNeighborPotentialLocalWordsWeightSum = 0.0f;
+                while (nNeighborLocalWordIdx < m_nCurrLocalWords && fNeighborPotentialLocalWordsWeightSum < fLocalWordsWeightSumThreshold) {
+                  LocalWord_3ch* pNeighborLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
+                  const size_t nNeighborTotColorL1Dist = L1dist<3>(anCurrColor, pNeighborLocalWord->oFeature.anColor);
+                  const size_t nNeighborColorDistortion = cdist<3>(anCurrColor, pNeighborLocalWord->oFeature.anColor);
+                  const size_t nNeighborTotColorMixDist = cmixdist(nNeighborTotColorL1Dist, nNeighborColorDistortion);
+                  const size_t nNeighborTotIntraDescDist = hdist<3>(anCurrIntraDesc, pNeighborLocalWord->oFeature.anDesc);
+                  const bool bNeighborRegionIsFlat = popcount<3>(pNeighborLocalWord->oFeature.anDesc) < FLAT_REGION_BIT_COUNT * 2;
+                  const size_t nNeighborWordOccIncr = bNeighborRegionIsFlat ? nCurrWordOccIncr * 2 : nCurrWordOccIncr;
+                  if (nNeighborTotColorMixDist <= nCurrTotColorDistThreshold && nNeighborTotIntraDescDist <= nCurrTotDescDistThreshold) {
+                    const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                    fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
+                    pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                    if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                      pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
+                  }
+                  else if (!oCurrFGMask.data[nSamplePxIdx] && bCurrRegionIsFlat && (bBootstrapping || (rand() % nCurrLocalWordUpdateRate) == 0)) {
+                    const size_t nSamplePxRGBIdx = nSamplePxIdx * 3;
+                    const size_t nSampleDescRGBIdx = nSamplePxRGBIdx * 2;
+                    ushort* anNeighborLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nSampleDescRGBIdx));
+                    const size_t nNeighborTotLastIntraDescDist = hdist<3>(anCurrIntraDesc, anNeighborLastIntraDesc);
+                    if (nNeighborTotColorMixDist <= nCurrTotColorDistThreshold && nNeighborTotLastIntraDescDist <= nCurrTotDescDistThreshold / 2) {
+                      const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                      fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
+                      pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                      if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                        pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
+                      for (size_t c = 0; c < 3; ++c)
+                        pNeighborLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
+                    }
+                    else {
+                      const bool bNeighborLastRegionIsFlat = popcount<3>(anNeighborLastIntraDesc) < FLAT_REGION_BIT_COUNT * 2;
+                      if (bNeighborLastRegionIsFlat && bCurrRegionIsFlat &&
+                        nNeighborTotLastIntraDescDist + nNeighborTotIntraDescDist <= nCurrTotDescDistThreshold &&
+                        nNeighborColorDistortion <= nCurrTotColorDistThreshold / 4) {
+                        const float fNeighborLocalWordWeight = GetLocalWordWeight(pNeighborLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+                        fNeighborPotentialLocalWordsWeightSum += fNeighborLocalWordWeight;
+                        pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                        if (fNeighborLocalWordWeight < DEFAULT_LWORD_MAX_WEIGHT)
+                          pNeighborLocalWord->nOccurrences += nNeighborWordOccIncr;
+                        for (size_t c = 0; c < 3; ++c)
+                          pNeighborLocalWord->oFeature.anColor[c] = anCurrColor[c];
+                      }
+                    }
+                  }
+                  ++nNeighborLocalWordIdx;
+                }
+                if (fNeighborPotentialLocalWordsWeightSum < DEFAULT_LWORD_INIT_WEIGHT) {
+                  nNeighborLocalWordIdx = m_nCurrLocalWords - 1;
+                  LocalWord_3ch* pNeighborLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nNeighborLocalDictIdx + nNeighborLocalWordIdx];
+                  for (size_t c = 0; c < 3; ++c) {
+                    pNeighborLocalWord->oFeature.anColor[c] = anCurrColor[c];
+                    pNeighborLocalWord->oFeature.anDesc[c] = anCurrIntraDesc[c];
+                  }
+                  pNeighborLocalWord->nOccurrences = nCurrWordOccIncr;
+                  pNeighborLocalWord->nFirstOcc = m_nFrameIndex;
+                  pNeighborLocalWord->nLastOcc = m_nFrameIndex;
+                }
+              }
+            }
+            if (nCurrRegionIllumUpdtVal)
+              nCurrRegionIllumUpdtVal -= 1;
+            // == feedback adj
+            bCurrRegionIsUnstable = fCurrDistThresholdFactor > UNSTABLE_REG_RDIST_MIN || (fCurrMeanRawSegmRes_LT - fCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (fCurrMeanRawSegmRes_ST - fCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN;
+            if (m_oLastFGMask.data[nPxIter] || (std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && nCurrRegionSegmVal))
+              fCurrLearningRate = std::min(fCurrLearningRate + FEEDBACK_T_INCR / (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST)*fCurrDistThresholdVariationFactor), FEEDBACK_T_UPPER);
+            else
+              fCurrLearningRate = std::max(fCurrLearningRate - FEEDBACK_T_DECR*fCurrDistThresholdVariationFactor / std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST), FEEDBACK_T_LOWER);
+            if (std::max(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
+              (fCurrDistThresholdVariationFactor) += bBootstrapping ? FEEDBACK_V_INCR * 2 : FEEDBACK_V_INCR;
+            else
+              fCurrDistThresholdVariationFactor = std::max(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR*((bBootstrapping || bCurrRegionIsFlat) ? 2 : m_oLastFGMask.data[nPxIter] ? 0.5f : 1), FEEDBACK_V_DECR);
+            if (fCurrDistThresholdFactor < std::pow(1.0f + std::min(fCurrMeanMinDist_LT, fCurrMeanMinDist_ST) * 2, 2))
+              fCurrDistThresholdFactor += FEEDBACK_R_VAR*(fCurrDistThresholdVariationFactor - FEEDBACK_V_DECR);
+            else
+              fCurrDistThresholdFactor = std::max(fCurrDistThresholdFactor - FEEDBACK_R_VAR / fCurrDistThresholdVariationFactor, 1.0f);
+            for (size_t c = 0; c < 3; ++c) {
+              anLastIntraDesc[c] = anCurrIntraDesc[c];
+              anLastColor[c] = anCurrColor[c];
+            }
+          }
+        }
+        const bool bRecalcGlobalWords = !(m_nFrameIndex % (nCurrGlobalWordUpdateRate << 5));
+        const bool bUpdateGlobalWords = !(m_nFrameIndex % (nCurrGlobalWordUpdateRate));
+        cv::Mat oLastFGMask_dilated_inverted_downscaled;
+        if (bUpdateGlobalWords)
+          cv::resize(m_oLastFGMask_dilated_inverted, oLastFGMask_dilated_inverted_downscaled, m_oDownSampledFrameSize_GlobalWordLookup, 0, 0, cv::INTER_NEAREST);
+        for (size_t nGlobalWordIdx = 0; nGlobalWordIdx < m_nCurrGlobalWords; ++nGlobalWordIdx) {
+          if (bRecalcGlobalWords && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > 0.0f) {
+            m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight = GetGlobalWordWeight(m_apGlobalWordDict[nGlobalWordIdx]);
+            if (m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight < 1.0f) {
+              m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight = 0.0f;
+              m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap = cv::Scalar(0.0f);
+            }
+          }
+          if (bUpdateGlobalWords && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > 0.0f) {
+            cv::accumulateProduct(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, m_oTempGlobalWordWeightDiffFactor, m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, oLastFGMask_dilated_inverted_downscaled);
+            m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight *= 0.9f;
+            cv::blur(m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, m_apGlobalWordDict[nGlobalWordIdx]->oSpatioOccMap, cv::Size(3, 3), cv::Point(-1, -1), cv::BORDER_REPLICATE);
+          }
+          if (nGlobalWordIdx > 0 && m_apGlobalWordDict[nGlobalWordIdx]->fLatestWeight > m_apGlobalWordDict[nGlobalWordIdx - 1]->fLatestWeight)
+            std::swap(m_apGlobalWordDict[nGlobalWordIdx], m_apGlobalWordDict[nGlobalWordIdx - 1]);
+        }
+        if (bUpdateGlobalWords) {
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            const size_t nGlobalWordMapLookupIdx = m_aPxInfoLUT_PAWCS[nPxIter].nGlobalWordMapLookupIdx;
+            float fLastGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[0]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+            for (size_t nGlobalWordLUTIdx = 1; nGlobalWordLUTIdx < m_nCurrGlobalWords; ++nGlobalWordLUTIdx) {
+              const float fCurrGlobalWordLocalWeight = *(float*)(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx]->oSpatioOccMap.data + nGlobalWordMapLookupIdx);
+              if (fCurrGlobalWordLocalWeight > fLastGlobalWordLocalWeight)
+                std::swap(m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx], m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT[nGlobalWordLUTIdx - 1]);
+              else
+                fLastGlobalWordLocalWeight = fCurrGlobalWordLocalWeight;
+            }
+          }
+        }
+        cv::bitwise_xor(oCurrFGMask, m_oLastRawFGMask, m_oCurrRawFGBlinkMask);
+        cv::bitwise_or(m_oCurrRawFGBlinkMask, m_oLastRawFGBlinkMask, m_oBlinksFrame);
+        m_oCurrRawFGBlinkMask.copyTo(m_oLastRawFGBlinkMask);
+        oCurrFGMask.copyTo(m_oLastRawFGMask);
+        cv::morphologyEx(oCurrFGMask, m_oFGMask_PreFlood, cv::MORPH_CLOSE, m_oMorphExStructElement);
+        m_oFGMask_PreFlood.copyTo(m_oFGMask_FloodedHoles);
+        cv::floodFill(m_oFGMask_FloodedHoles, cv::Point(0, 0), UCHAR_MAX);
+        cv::bitwise_not(m_oFGMask_FloodedHoles, m_oFGMask_FloodedHoles);
+        cv::erode(m_oFGMask_PreFlood, m_oFGMask_PreFlood, cv::Mat(), cv::Point(-1, -1), 3);
+        cv::bitwise_or(oCurrFGMask, m_oFGMask_FloodedHoles, oCurrFGMask);
+        cv::bitwise_or(oCurrFGMask, m_oFGMask_PreFlood, oCurrFGMask);
+        cv::medianBlur(oCurrFGMask, m_oLastFGMask, m_nMedianBlurKernelSize);
+        cv::dilate(m_oLastFGMask, m_oLastFGMask_dilated, cv::Mat(), cv::Point(-1, -1), 3);
+        cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
+        cv::bitwise_not(m_oLastFGMask_dilated, m_oLastFGMask_dilated_inverted);
+        cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
+        m_oLastFGMask.copyTo(oCurrFGMask);
+        cv::addWeighted(m_oMeanFinalSegmResFrame_LT, (1.0f - fRollAvgFactor_LT), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_LT, 0, m_oMeanFinalSegmResFrame_LT, CV_32F);
+        cv::addWeighted(m_oMeanFinalSegmResFrame_ST, (1.0f - fRollAvgFactor_ST), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_ST, 0, m_oMeanFinalSegmResFrame_ST, CV_32F);
+        const float fCurrNonFlatRegionRatio = (float)(m_nTotRelevantPxCount - nFlatRegionCount) / m_nTotRelevantPxCount;
+        if (fCurrNonFlatRegionRatio < LBSPDESC_RATIO_MIN && m_fLastNonFlatRegionRatio < LBSPDESC_RATIO_MIN) {
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            if (m_anLBSPThreshold_8bitLUT[t] > cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 4))
+              --m_anLBSPThreshold_8bitLUT[t];
+        }
+        else if (fCurrNonFlatRegionRatio > LBSPDESC_RATIO_MAX && m_fLastNonFlatRegionRatio > LBSPDESC_RATIO_MAX) {
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            if (m_anLBSPThreshold_8bitLUT[t] < cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + UCHAR_MAX*m_fRelLBSPThreshold))
+              ++m_anLBSPThreshold_8bitLUT[t];
+        }
+        m_fLastNonFlatRegionRatio = fCurrNonFlatRegionRatio;
+        cv::resize(oInputImg, m_oDownSampledFrame_MotionAnalysis, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
+        cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_LT, fRollAvgFactor_LT);
+        cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_ST, fRollAvgFactor_ST);
+        const float fCurrMeanL1DistRatio = L1dist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)m_oMeanDownSampledLastDistFrame_ST.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, m_oDownSampledROI_MotionAnalysis.data) / m_nDownSampledROIPxCount;
+        if (!m_bAutoModelResetEnabled && fCurrMeanL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES * 2)
+          m_bAutoModelResetEnabled = true;
+        if (m_bAutoModelResetEnabled || m_bUsingMovingCamera) {
+          if ((m_nFrameIndex%DEFAULT_BOOTSTRAP_WIN_SIZE) == 0) {
+            cv::Mat oCurrBackgroundImg, oDownSampledBackgroundImg;
+            getBackgroundImage(oCurrBackgroundImg);
+            cv::resize(oCurrBackgroundImg, oDownSampledBackgroundImg, m_oDownSampledFrameSize_MotionAnalysis, 0, 0, cv::INTER_AREA);
+            cv::Mat oDownSampledBackgroundImg_32F; oDownSampledBackgroundImg.convertTo(oDownSampledBackgroundImg_32F, CV_32F);
+            const float fCurrModelL1DistRatio = L1dist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)oDownSampledBackgroundImg_32F.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, cv::Mat(m_oDownSampledROI_MotionAnalysis == UCHAR_MAX).data) / m_nDownSampledROIPxCount;
+            const float fCurrModelCDistRatio = cdist((float*)m_oMeanDownSampledLastDistFrame_LT.data, (float*)oDownSampledBackgroundImg_32F.data, m_oMeanDownSampledLastDistFrame_LT.total(), m_nImgChannels, cv::Mat(m_oDownSampledROI_MotionAnalysis == UCHAR_MAX).data) / m_nDownSampledROIPxCount;
+            if (m_bUsingMovingCamera && fCurrModelL1DistRatio < FRAMELEVEL_MIN_L1DIST_THRES / 4 && fCurrModelCDistRatio < FRAMELEVEL_MIN_CDIST_THRES / 4) {
+              m_nLocalWordWeightOffset = DEFAULT_LWORD_WEIGHT_OFFSET;
+              m_bUsingMovingCamera = false;
+              refreshModel(1, 1, true);
+            }
+            else if (bBootstrapping && !m_bUsingMovingCamera && (fCurrModelL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES || fCurrModelCDistRatio >= FRAMELEVEL_MIN_CDIST_THRES)) {
+              m_nLocalWordWeightOffset = 5;
+              m_bUsingMovingCamera = true;
+              refreshModel(1, 1, true);
+            }
+          }
+          if (m_nFramesSinceLastReset > DEFAULT_BOOTSTRAP_WIN_SIZE * 2)
+            m_bAutoModelResetEnabled = false;
+          else if (fCurrMeanL1DistRatio >= FRAMELEVEL_MIN_L1DIST_THRES && m_nModelResetCooldown == 0) {
+            m_nFramesSinceLastReset = 0;
+            refreshModel(m_nLocalWordWeightOffset / 8, 0, true);
+            m_nModelResetCooldown = nCurrSamplesForMovingAvg_ST;
+            m_oUpdateRateFrame = cv::Scalar(1.0f);
+          }
+          else if (!bBootstrapping)
+            ++m_nFramesSinceLastReset;
+        }
+        if (m_nModelResetCooldown > 0)
+          --m_nModelResetCooldown;
+      }
+
+      void BackgroundSubtractorPAWCS::getBackgroundImage(cv::OutputArray backgroundImage) const { // @@@ add option to reconstruct from gwords?
+        CV_Assert(m_bInitialized);
+        cv::Mat oAvgBGImg = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
+        for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+          const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+          const size_t nLocalDictIdx = nModelIter*m_nCurrLocalWords;
+          const int nCurrImgCoord_X = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_X;
+          const int nCurrImgCoord_Y = m_aPxInfoLUT_PAWCS[nPxIter].nImgCoord_Y;
+          if (m_nImgChannels == 1) {
+            float fTotWeight = 0.0f;
+            float fTotColor = 0.0f;
+            for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+              LocalWord_1ch* pCurrLocalWord = (LocalWord_1ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+              float fCurrWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+              fTotColor += (float)pCurrLocalWord->oFeature.anColor[0] * fCurrWeight;
+              fTotWeight += fCurrWeight;
+            }
+            oAvgBGImg.at<float>(nCurrImgCoord_Y, nCurrImgCoord_X) = fTotColor / fTotWeight;
+          }
+          else { //m_nImgChannels==3
+            float fTotWeight = 0.0f;
+            float fTotColor[3] = { 0.0f,0.0f,0.0f };
+            for (size_t nLocalWordIdx = 0; nLocalWordIdx < m_nCurrLocalWords; ++nLocalWordIdx) {
+              LocalWord_3ch* pCurrLocalWord = (LocalWord_3ch*)m_apLocalWordDict[nLocalDictIdx + nLocalWordIdx];
+              float fCurrWeight = GetLocalWordWeight(pCurrLocalWord, m_nFrameIndex, m_nLocalWordWeightOffset);
+              for (size_t c = 0; c < 3; ++c)
+                fTotColor[c] += (float)pCurrLocalWord->oFeature.anColor[c] * fCurrWeight;
+              fTotWeight += fCurrWeight;
+            }
+            oAvgBGImg.at<cv::Vec3f>(nCurrImgCoord_Y, nCurrImgCoord_X) = cv::Vec3f(fTotColor[0] / fTotWeight, fTotColor[1] / fTotWeight, fTotColor[2] / fTotWeight);
+          }
+        }
+        oAvgBGImg.convertTo(backgroundImage, CV_8U);
+      }
+
+      void BackgroundSubtractorPAWCS::getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const {
+        CV_Assert(LBSP_::DESC_SIZE == 2);
+        CV_Assert(m_bInitialized);
+        cv::Mat oAvgBGDesc = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
+        // @@@@@@ TO BE REWRITTEN FOR WORD-BASED RECONSTRUCTION
+        /*for(size_t n=0; n<m_voBGDescSamples.size(); ++n) {
+              for(int y=0; y<m_oImgSize.height; ++y) {
+                  for(int x=0; x<m_oImgSize.width; ++x) {
+                      const size_t nDescIter = m_voBGDescSamples[n].step.p[0]*y + m_voBGDescSamples[n].step.p[1]*x;
+                      const size_t nFloatIter = nDescIter*2;
+                      float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data+nFloatIter);
+                      const ushort* const oBGDescPtr = (ushort*)(m_voBGDescSamples[n].data+nDescIter);
+                      for(size_t c=0; c<m_nImgChannels; ++c)
+                          oAvgBgDescPtr[c] += ((float)oBGDescPtr[c])/m_voBGDescSamples.size();
+                  }
+              }
+          }*/
+        oAvgBGDesc.convertTo(backgroundDescImage, CV_16U);
+      }
+
+      void BackgroundSubtractorPAWCS::CleanupDictionaries() {
+        if (m_aLocalWordList_1ch) {
+          delete[] m_aLocalWordList_1ch;
+          m_aLocalWordList_1ch = nullptr;
+          m_pLocalWordListIter_1ch = nullptr;
+        }
+        else if (m_aLocalWordList_3ch) {
+          delete[] m_aLocalWordList_3ch;
+          m_aLocalWordList_3ch = nullptr;
+          m_pLocalWordListIter_3ch = nullptr;
+        }
+        if (m_apLocalWordDict) {
+          delete[] m_apLocalWordDict;
+          m_apLocalWordDict = nullptr;
+        }
+        if (m_aGlobalWordList_1ch) {
+          delete[] m_aGlobalWordList_1ch;
+          m_aGlobalWordList_1ch = nullptr;
+          m_pGlobalWordListIter_1ch = nullptr;
+        }
+        else if (m_aGlobalWordList_3ch) {
+          delete[] m_aGlobalWordList_3ch;
+          m_aGlobalWordList_3ch = nullptr;
+          m_pGlobalWordListIter_3ch = nullptr;
+        }
+        if (m_apGlobalWordDict) {
+          delete[] m_apGlobalWordDict;
+          m_apGlobalWordDict = nullptr;
+        }
+        if (m_aPxInfoLUT_PAWCS) {
+          for (size_t nPxIter = 0; nPxIter < m_nTotPxCount; ++nPxIter)
+            delete[] m_aPxInfoLUT_PAWCS[nPxIter].apGlobalDictSortLUT;
+          delete[] m_aPxInfoLUT_PAWCS;
+          m_aPxInfoLUT = nullptr;
+          m_aPxInfoLUT_PAWCS = nullptr;
+        }
+        if (m_aPxIdxLUT) {
+          delete[] m_aPxIdxLUT;
+          m_aPxIdxLUT = nullptr;
+        }
+      }
+
+      float BackgroundSubtractorPAWCS::GetLocalWordWeight(const LocalWordBase* w, size_t nCurrFrame, size_t nOffset) {
+        return (float)(w->nOccurrences) / ((w->nLastOcc - w->nFirstOcc) + (nCurrFrame - w->nLastOcc) * 2 + nOffset);
+      }
+
+      float BackgroundSubtractorPAWCS::GetGlobalWordWeight(const GlobalWordBase* w) {
+        return (float)cv::sum(w->oSpatioOccMap).val[0];
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorPAWCS.h b/src/algorithms/LBSP/BackgroundSubtractorPAWCS.h
new file mode 100644
index 0000000000000000000000000000000000000000..e81736d37618108540ae33033b971932c2907fb4
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorPAWCS.h
@@ -0,0 +1,162 @@
+#pragma once
+
+#include "BackgroundSubtractorLBSP_.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      //! defines the default value for BackgroundSubtractorLBSP_::m_fRelLBSPThreshold
+      const float BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD = 0.333f;
+      //! defines the default value for BackgroundSubtractorPAWCS::m_nDescDistThresholdOffset
+      const int BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET = 2;
+      //! defines the default value for BackgroundSubtractorPAWCS::m_nMinColorDistThreshold
+      const int BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD = 20;
+      //! defines the default value for BackgroundSubtractorPAWCS::m_nMaxLocalWords and m_nMaxGlobalWords
+      const int BGSPAWCS_DEFAULT_MAX_NB_WORDS = 50;
+      //! defines the default value for BackgroundSubtractorPAWCS::m_nSamplesForMovingAvgs
+      const int BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS = 100;
+
+      /*!
+          Pixel-based Adaptive Word Consensus Segmenter (PAWCS) change detection algorithm.
+
+          Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
+          For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
+
+          For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles et al.,
+          "A Self-Adjusting Approach to Change Detection Based on Background Word Consensus", in WACV 2015.
+
+          This algorithm is currently NOT thread-safe.
+      */
+      class BackgroundSubtractorPAWCS : public BackgroundSubtractorLBSP_ {
+      public:
+        //! full constructor
+        BackgroundSubtractorPAWCS(float fRelLBSPThreshold = BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
+          size_t nDescDistThresholdOffset = BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET,
+          size_t nMinColorDistThreshold = BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD,
+          size_t nMaxNbWords = BGSPAWCS_DEFAULT_MAX_NB_WORDS,
+          size_t nSamplesForMovingAvgs = BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
+        //! default destructor
+        virtual ~BackgroundSubtractorPAWCS();
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
+        //! refreshes all local (+ global) dictionaries based on the last analyzed frame
+        virtual void refreshModel(size_t nBaseOccCount, float fOccDecrFrac, bool bForceFGUpdate = false);
+        //! primary model update function; the learning param is used to override the internal learning speed (ignored when <= 0)
+        virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = 0);
+        //! returns a copy of the latest reconstructed background image
+        virtual void getBackgroundImage(cv::OutputArray backgroundImage) const;
+        //! returns a copy of the latest reconstructed background descriptors image
+        virtual void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
+
+      protected:
+        template<size_t nChannels>
+        struct ColorLBSPFeature {
+          uchar anColor[nChannels];
+          ushort anDesc[nChannels];
+        };
+        struct LocalWordBase {
+          size_t nFirstOcc;
+          size_t nLastOcc;
+          size_t nOccurrences;
+        };
+        template<typename T>
+        struct LocalWord : LocalWordBase {
+          T oFeature;
+        };
+        struct GlobalWordBase {
+          float fLatestWeight;
+          cv::Mat oSpatioOccMap;
+          uchar nDescBITS;
+        };
+        template<typename T>
+        struct GlobalWord : GlobalWordBase {
+          T oFeature;
+        };
+        typedef LocalWord<ColorLBSPFeature<1>> LocalWord_1ch;
+        typedef LocalWord<ColorLBSPFeature<3>> LocalWord_3ch;
+        typedef GlobalWord<ColorLBSPFeature<1>> GlobalWord_1ch;
+        typedef GlobalWord<ColorLBSPFeature<3>> GlobalWord_3ch;
+        struct PxInfo_PAWCS : PxInfoBase {
+          size_t nGlobalWordMapLookupIdx;
+          GlobalWordBase** apGlobalDictSortLUT;
+        };
+        //! absolute minimal color distance threshold ('R' or 'radius' in the original ViBe paper, used as the default/initial 'R(x)' value here)
+        const size_t m_nMinColorDistThreshold;
+        //! absolute descriptor distance threshold offset
+        const size_t m_nDescDistThresholdOffset;
+        //! max/curr number of local words used to build background submodels (for a single pixel, similar to 'N' in ViBe/PBAS, may vary based on img/channel size)
+        size_t m_nMaxLocalWords, m_nCurrLocalWords;
+        //! max/curr number of global words used to build the global background model (may vary based on img/channel size)
+        size_t m_nMaxGlobalWords, m_nCurrGlobalWords;
+        //! number of samples to use to compute the learning rate of moving averages
+        const size_t m_nSamplesForMovingAvgs;
+        //! last calculated non-flat region ratio
+        float m_fLastNonFlatRegionRatio;
+        //! current kernel size for median blur post-proc filtering
+        int m_nMedianBlurKernelSize;
+        //! specifies the downsampled frame size used for cam motion analysis & gword lookup maps
+        cv::Size m_oDownSampledFrameSize_MotionAnalysis, m_oDownSampledFrameSize_GlobalWordLookup;
+        //! downsampled version of the ROI used for cam motion analysis
+        cv::Mat m_oDownSampledROI_MotionAnalysis;
+        //! total pixel count for the downsampled ROIs
+        size_t m_nDownSampledROIPxCount;
+        //! current local word weight offset
+        size_t m_nLocalWordWeightOffset;
+
+        //! word lists & dictionaries
+        LocalWordBase** m_apLocalWordDict;
+        LocalWord_1ch* m_aLocalWordList_1ch, *m_pLocalWordListIter_1ch;
+        LocalWord_3ch* m_aLocalWordList_3ch, *m_pLocalWordListIter_3ch;
+        GlobalWordBase** m_apGlobalWordDict;
+        GlobalWord_1ch* m_aGlobalWordList_1ch, *m_pGlobalWordListIter_1ch;
+        GlobalWord_3ch* m_aGlobalWordList_3ch, *m_pGlobalWordListIter_3ch;
+        PxInfo_PAWCS* m_aPxInfoLUT_PAWCS;
+
+        //! a lookup map used to keep track of regions where illumination recently changed
+        cv::Mat m_oIllumUpdtRegionMask;
+        //! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe)
+        cv::Mat m_oUpdateRateFrame;
+        //! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds)
+        cv::Mat m_oDistThresholdFrame;
+        //! per-pixel distance threshold variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations)
+        cv::Mat m_oDistThresholdVariationFrame;
+        //! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)')
+        cv::Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST;
+        //! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and force global model resets automatically)
+        cv::Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST;
+        //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
+        cv::Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST;
+        //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
+        cv::Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST;
+        //! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds)
+        cv::Mat m_oUnstableRegionMask;
+        //! per-pixel blink detection map ('Z(x)')
+        cv::Mat m_oBlinksFrame;
+        //! pre-allocated matrix used to downsample the input frame when needed
+        cv::Mat m_oDownSampledFrame_MotionAnalysis;
+        //! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection)
+        cv::Mat m_oLastRawFGMask;
+
+        //! pre-allocated CV_8UC1 matrices used to speed up morph ops
+        cv::Mat m_oFGMask_PreFlood;
+        cv::Mat m_oFGMask_FloodedHoles;
+        cv::Mat m_oLastFGMask_dilated;
+        cv::Mat m_oLastFGMask_dilated_inverted;
+        cv::Mat m_oCurrRawFGBlinkMask;
+        cv::Mat m_oLastRawFGBlinkMask;
+        cv::Mat m_oTempGlobalWordWeightDiffFactor;
+        cv::Mat m_oMorphExStructElement;
+
+        //! internal cleanup function for the dictionary structures
+        void CleanupDictionaries();
+        //! internal weight lookup function for local words
+        static float GetLocalWordWeight(const LocalWordBase* w, size_t nCurrFrame, size_t nOffset);
+        //! internal weight lookup function for global words
+        static float GetGlobalWordWeight(const GlobalWordBase* w);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.cpp b/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31cd8dfdeb0fdbc309f9d0c3b7f2aa76cb3fb18e
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.cpp
@@ -0,0 +1,751 @@
+#include <iostream>
+#include <iomanip>
+
+#include <opencv2/imgproc/imgproc.hpp>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui.hpp>
+#endif
+
+#include "BackgroundSubtractorSuBSENSE.h"
+#include "RandUtils.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*
+       *
+       * Intrinsic parameters for our method are defined here; tuning these for better
+       * performance should not be required in most cases -- although improvements in
+       * very specific scenarios are always possible.
+       *
+       */
+       //! defines the threshold value(s) used to detect long-term ghosting and trigger the fast edge-based absorption heuristic
+      const float GHOSTDET_D_MAX = 0.010f; // defines 'negligible' change here
+      const float GHOSTDET_S_MIN = 0.995f; // defines the required minimum local foreground saturation value
+      //! parameter used to scale dynamic distance threshold adjustments ('R(x)')
+      const float FEEDBACK_R_VAR = 0.01f;
+      //! parameters used to adjust the variation step size of 'v(x)'
+      const float FEEDBACK_V_INCR = 1.000f;
+      const float FEEDBACK_V_DECR = 0.100f;
+      //! parameters used to scale dynamic learning rate adjustments  ('T(x)')
+      const float FEEDBACK_T_DECR = 0.2500f;
+      const float FEEDBACK_T_INCR = 0.5000f;
+      const float FEEDBACK_T_LOWER = 2.0000f;
+      const float FEEDBACK_T_UPPER = 256.00f;
+      //! parameters used to define 'unstable' regions, based on segm noise/bg dynamics and local dist threshold values
+      const float UNSTABLE_REG_RATIO_MIN = 0.100f;
+      const float UNSTABLE_REG_RDIST_MIN = 3.000f;
+      //! parameters used to scale the relative LBSP intensity threshold used for internal comparisons
+      const float LBSPDESC_NONZERO_RATIO_MIN = 0.100f;
+      const float LBSPDESC_NONZERO_RATIO_MAX = 0.500f;
+      //! parameters used to define model reset/learning rate boosts in our frame-level component
+#define FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD  (m_nMinColorDistThreshold/2)
+      const int FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO = 8;
+
+      // local define used to display debug information
+      //const int DISPLAY_SUBSENSE_DEBUG_INFO = 0;
+      // local define used to specify the default frame size (320x240 = QVGA)
+#define DEFAULT_FRAME_SIZE cv::Size(320,240)
+// local define used to specify the color dist threshold offset used for unstable regions
+#define STAB_COLOR_DIST_OFFSET (m_nMinColorDistThreshold/5)
+// local define used to specify the desc dist threshold offset used for unstable regions
+#define UNSTAB_DESC_DIST_OFFSET (m_nDescDistThresholdOffset)
+
+      static const size_t s_nColorMaxDataRange_1ch = UCHAR_MAX;
+      static const size_t s_nDescMaxDataRange_1ch = LBSP::DESC_SIZE * 8;
+      static const size_t s_nColorMaxDataRange_3ch = s_nColorMaxDataRange_1ch * 3;
+      static const size_t s_nDescMaxDataRange_3ch = s_nDescMaxDataRange_1ch * 3;
+
+      BackgroundSubtractorSuBSENSE::BackgroundSubtractorSuBSENSE(float fRelLBSPThreshold
+        , size_t nDescDistThresholdOffset
+        , size_t nMinColorDistThreshold
+        , size_t nBGSamples
+        , size_t nRequiredBGSamples
+        , size_t nSamplesForMovingAvgs)
+        : BackgroundSubtractorLBSP(fRelLBSPThreshold)
+        , m_nMinColorDistThreshold(nMinColorDistThreshold)
+        , m_nDescDistThresholdOffset(nDescDistThresholdOffset)
+        , m_nBGSamples(nBGSamples)
+        , m_nRequiredBGSamples(nRequiredBGSamples)
+        , m_nSamplesForMovingAvgs(nSamplesForMovingAvgs)
+        , m_fLastNonZeroDescRatio(0.0f)
+        , m_bLearningRateScalingEnabled(true)
+        , m_fCurrLearningRateLowerCap(FEEDBACK_T_LOWER)
+        , m_fCurrLearningRateUpperCap(FEEDBACK_T_UPPER)
+        , m_nMedianBlurKernelSize(m_nDefaultMedianBlurKernelSize)
+        , m_bUse3x3Spread(true) {
+        CV_Assert(m_nBGSamples > 0 && m_nRequiredBGSamples <= m_nBGSamples);
+        CV_Assert(m_nMinColorDistThreshold >= STAB_COLOR_DIST_OFFSET);
+      }
+
+      BackgroundSubtractorSuBSENSE::~BackgroundSubtractorSuBSENSE() {
+        if (m_aPxIdxLUT)
+          delete[] m_aPxIdxLUT;
+        if (m_aPxInfoLUT)
+          delete[] m_aPxInfoLUT;
+      }
+
+      void BackgroundSubtractorSuBSENSE::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) {
+        // == init
+        CV_Assert(!oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0);
+        CV_Assert(oInitImg.isContinuous());
+        CV_Assert(oInitImg.type() == CV_8UC3 || oInitImg.type() == CV_8UC1);
+        if (oInitImg.type() == CV_8UC3) {
+          std::vector<cv::Mat> voInitImgChannels;
+          cv::split(oInitImg, voInitImgChannels);
+          if (!cv::countNonZero((voInitImgChannels[0] != voInitImgChannels[1]) | (voInitImgChannels[2] != voInitImgChannels[1])))
+            std::cout << std::endl << "\tBackgroundSubtractorSuBSENSE : Warning, grayscale images should always be passed in CV_8UC1 format for optimal performance." << std::endl;
+        }
+        cv::Mat oNewBGROI;
+        if (oROI.empty() && (m_oROI.empty() || oROI.size() != oInitImg.size())) {
+          oNewBGROI.create(oInitImg.size(), CV_8UC1);
+          oNewBGROI = cv::Scalar_<uchar>(UCHAR_MAX);
+        }
+        else if (oROI.empty())
+          oNewBGROI = m_oROI;
+        else {
+          CV_Assert(oROI.size() == oInitImg.size() && oROI.type() == CV_8UC1);
+          CV_Assert(cv::countNonZero((oROI < UCHAR_MAX)&(oROI > 0)) == 0);
+          oNewBGROI = oROI.clone();
+          cv::Mat oTempROI;
+          cv::dilate(oNewBGROI, oTempROI, cv::Mat(), cv::Point(-1, -1), LBSP::PATCH_SIZE / 2);
+          cv::bitwise_or(oNewBGROI, oTempROI / 2, oNewBGROI);
+        }
+        const size_t nOrigROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
+        CV_Assert(nOrigROIPxCount > 0);
+        LBSP::validateROI(oNewBGROI);
+        const size_t nFinalROIPxCount = (size_t)cv::countNonZero(oNewBGROI);
+        CV_Assert(nFinalROIPxCount > 0);
+        m_oROI = oNewBGROI;
+        m_oImgSize = oInitImg.size();
+        m_nImgType = oInitImg.type();
+        m_nImgChannels = oInitImg.channels();
+        m_nTotPxCount = m_oImgSize.area();
+        m_nTotRelevantPxCount = nFinalROIPxCount;
+        m_nFrameIndex = 0;
+        m_nFramesSinceLastReset = 0;
+        m_nModelResetCooldown = 0;
+        m_fLastNonZeroDescRatio = 0.0f;
+        const int nTotImgPixels = m_oImgSize.height*m_oImgSize.width;
+        if (nOrigROIPxCount >= m_nTotPxCount / 2 && (int)m_nTotPxCount >= DEFAULT_FRAME_SIZE.area()) {
+          m_bLearningRateScalingEnabled = true;
+          m_bAutoModelResetEnabled = true;
+          m_bUse3x3Spread = !(nTotImgPixels > DEFAULT_FRAME_SIZE.area() * 2);
+          const int nRawMedianBlurKernelSize = std::min((int)floor((float)nTotImgPixels / DEFAULT_FRAME_SIZE.area() + 0.5f) + m_nDefaultMedianBlurKernelSize, 14);
+          m_nMedianBlurKernelSize = (nRawMedianBlurKernelSize % 2) ? nRawMedianBlurKernelSize : nRawMedianBlurKernelSize - 1;
+          m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
+          m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
+        }
+        else {
+          m_bLearningRateScalingEnabled = false;
+          m_bAutoModelResetEnabled = false;
+          m_bUse3x3Spread = true;
+          m_nMedianBlurKernelSize = m_nDefaultMedianBlurKernelSize;
+          m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER * 2;
+          m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER * 2;
+        }
+        m_oUpdateRateFrame.create(m_oImgSize, CV_32FC1);
+        m_oUpdateRateFrame = cv::Scalar(m_fCurrLearningRateLowerCap);
+        m_oDistThresholdFrame.create(m_oImgSize, CV_32FC1);
+        m_oDistThresholdFrame = cv::Scalar(1.0f);
+        m_oVariationModulatorFrame.create(m_oImgSize, CV_32FC1);
+        m_oVariationModulatorFrame = cv::Scalar(10.0f); // should always be >= FEEDBACK_V_DECR
+        m_oMeanLastDistFrame.create(m_oImgSize, CV_32FC1);
+        m_oMeanLastDistFrame = cv::Scalar(0.0f);
+        m_oMeanMinDistFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanMinDistFrame_LT = cv::Scalar(0.0f);
+        m_oMeanMinDistFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanMinDistFrame_ST = cv::Scalar(0.0f);
+        m_oDownSampledFrameSize = cv::Size(m_oImgSize.width / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO, m_oImgSize.height / FRAMELEVEL_ANALYSIS_DOWNSAMPLE_RATIO);
+        m_oMeanDownSampledLastDistFrame_LT.create(m_oDownSampledFrameSize, CV_32FC((int)m_nImgChannels));
+        m_oMeanDownSampledLastDistFrame_LT = cv::Scalar(0.0f);
+        m_oMeanDownSampledLastDistFrame_ST.create(m_oDownSampledFrameSize, CV_32FC((int)m_nImgChannels));
+        m_oMeanDownSampledLastDistFrame_ST = cv::Scalar(0.0f);
+        m_oMeanRawSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanRawSegmResFrame_LT = cv::Scalar(0.0f);
+        m_oMeanRawSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanRawSegmResFrame_ST = cv::Scalar(0.0f);
+        m_oMeanFinalSegmResFrame_LT.create(m_oImgSize, CV_32FC1);
+        m_oMeanFinalSegmResFrame_LT = cv::Scalar(0.0f);
+        m_oMeanFinalSegmResFrame_ST.create(m_oImgSize, CV_32FC1);
+        m_oMeanFinalSegmResFrame_ST = cv::Scalar(0.0f);
+        m_oUnstableRegionMask.create(m_oImgSize, CV_8UC1);
+        m_oUnstableRegionMask = cv::Scalar_<uchar>(0);
+        m_oBlinksFrame.create(m_oImgSize, CV_8UC1);
+        m_oBlinksFrame = cv::Scalar_<uchar>(0);
+        m_oDownSampledFrame_MotionAnalysis.create(m_oDownSampledFrameSize, CV_8UC((int)m_nImgChannels));
+        m_oDownSampledFrame_MotionAnalysis = cv::Scalar_<uchar>::all(0);
+        m_oLastColorFrame.create(m_oImgSize, CV_8UC((int)m_nImgChannels));
+        m_oLastColorFrame = cv::Scalar_<uchar>::all(0);
+        m_oLastDescFrame.create(m_oImgSize, CV_16UC((int)m_nImgChannels));
+        m_oLastDescFrame = cv::Scalar_<ushort>::all(0);
+        m_oLastRawFGMask.create(m_oImgSize, CV_8UC1);
+        m_oLastRawFGMask = cv::Scalar_<uchar>(0);
+        m_oLastFGMask.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask = cv::Scalar_<uchar>(0);
+        m_oLastFGMask_dilated.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask_dilated = cv::Scalar_<uchar>(0);
+        m_oLastFGMask_dilated_inverted.create(m_oImgSize, CV_8UC1);
+        m_oLastFGMask_dilated_inverted = cv::Scalar_<uchar>(0);
+        m_oFGMask_FloodedHoles.create(m_oImgSize, CV_8UC1);
+        m_oFGMask_FloodedHoles = cv::Scalar_<uchar>(0);
+        m_oFGMask_PreFlood.create(m_oImgSize, CV_8UC1);
+        m_oFGMask_PreFlood = cv::Scalar_<uchar>(0);
+        m_oCurrRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
+        m_oCurrRawFGBlinkMask = cv::Scalar_<uchar>(0);
+        m_oLastRawFGBlinkMask.create(m_oImgSize, CV_8UC1);
+        m_oLastRawFGBlinkMask = cv::Scalar_<uchar>(0);
+        m_voBGColorSamples.resize(m_nBGSamples);
+        m_voBGDescSamples.resize(m_nBGSamples);
+        for (size_t s = 0; s < m_nBGSamples; ++s) {
+          m_voBGColorSamples[s].create(m_oImgSize, CV_8UC((int)m_nImgChannels));
+          m_voBGColorSamples[s] = cv::Scalar_<uchar>::all(0);
+          m_voBGDescSamples[s].create(m_oImgSize, CV_16UC((int)m_nImgChannels));
+          m_voBGDescSamples[s] = cv::Scalar_<ushort>::all(0);
+        }
+        if (m_aPxIdxLUT)
+          delete[] m_aPxIdxLUT;
+        if (m_aPxInfoLUT)
+          delete[] m_aPxInfoLUT;
+        m_aPxIdxLUT = new size_t[m_nTotRelevantPxCount];
+        m_aPxInfoLUT = new PxInfoBase[m_nTotPxCount];
+        if (m_nImgChannels == 1) {
+          CV_Assert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width && m_oLastColorFrame.step.p[1] == 1);
+          CV_Assert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>((m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold) / 3);
+          for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
+            if (m_oROI.data[nPxIter]) {
+              m_aPxIdxLUT[nModelIter] = nPxIter;
+              m_aPxInfoLUT[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
+              m_aPxInfoLUT[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
+              m_aPxInfoLUT[nPxIter].nModelIdx = nModelIter;
+              m_oLastColorFrame.data[nPxIter] = oInitImg.data[nPxIter];
+              const size_t nDescIter = nPxIter * 2;
+              LBSP::computeGrayscaleDescriptor(oInitImg, oInitImg.data[nPxIter], m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxIter]], *((ushort*)(m_oLastDescFrame.data + nDescIter)));
+              ++nModelIter;
+            }
+          }
+        }
+        else { //m_nImgChannels==3
+          CV_Assert(m_oLastColorFrame.step.p[0] == (size_t)m_oImgSize.width * 3 && m_oLastColorFrame.step.p[1] == 3);
+          CV_Assert(m_oLastDescFrame.step.p[0] == m_oLastColorFrame.step.p[0] * 2 && m_oLastDescFrame.step.p[1] == m_oLastColorFrame.step.p[1] * 2);
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            m_anLBSPThreshold_8bitLUT[t] = cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + t*m_fRelLBSPThreshold);
+          for (size_t nPxIter = 0, nModelIter = 0; nPxIter < m_nTotPxCount; ++nPxIter) {
+            if (m_oROI.data[nPxIter]) {
+              m_aPxIdxLUT[nModelIter] = nPxIter;
+              m_aPxInfoLUT[nPxIter].nImgCoord_Y = (int)nPxIter / m_oImgSize.width;
+              m_aPxInfoLUT[nPxIter].nImgCoord_X = (int)nPxIter%m_oImgSize.width;
+              m_aPxInfoLUT[nPxIter].nModelIdx = nModelIter;
+              const size_t nPxRGBIter = nPxIter * 3;
+              const size_t nDescRGBIter = nPxRGBIter * 2;
+              for (size_t c = 0; c < 3; ++c) {
+                m_oLastColorFrame.data[nPxRGBIter + c] = oInitImg.data[nPxRGBIter + c];
+                LBSP::computeSingleRGBDescriptor(oInitImg, oInitImg.data[nPxRGBIter + c], m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[oInitImg.data[nPxRGBIter + c]], ((ushort*)(m_oLastDescFrame.data + nDescRGBIter))[c]);
+              }
+              ++nModelIter;
+            }
+          }
+        }
+        m_bInitialized = true;
+        refreshModel(1.0f);
+      }
+
+      void BackgroundSubtractorSuBSENSE::refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate) {
+        // == refresh
+        CV_Assert(m_bInitialized);
+        CV_Assert(fSamplesRefreshFrac > 0.0f && fSamplesRefreshFrac <= 1.0f);
+        const size_t nModelsToRefresh = fSamplesRefreshFrac < 1.0f ? (size_t)(fSamplesRefreshFrac*m_nBGSamples) : m_nBGSamples;
+        const size_t nRefreshStartPos = fSamplesRefreshFrac < 1.0f ? rand() % m_nBGSamples : 0;
+        if (m_nImgChannels == 1) {
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            if (bForceFGUpdate || !m_oLastFGMask.data[nPxIter]) {
+              for (size_t nCurrModelIdx = nRefreshStartPos; nCurrModelIdx < nRefreshStartPos + nModelsToRefresh; ++nCurrModelIdx) {
+                int nSampleImgCoord_Y, nSampleImgCoord_X;
+                getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+                const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+                if (bForceFGUpdate || !m_oLastFGMask.data[nSamplePxIdx]) {
+                  const size_t nCurrRealModelIdx = nCurrModelIdx%m_nBGSamples;
+                  m_voBGColorSamples[nCurrRealModelIdx].data[nPxIter] = m_oLastColorFrame.data[nSamplePxIdx];
+                  *((ushort*)(m_voBGDescSamples[nCurrRealModelIdx].data + nPxIter * 2)) = *((ushort*)(m_oLastDescFrame.data + nSamplePxIdx * 2));
+                }
+              }
+            }
+          }
+        }
+        else { //m_nImgChannels==3
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            if (bForceFGUpdate || !m_oLastFGMask.data[nPxIter]) {
+              for (size_t nCurrModelIdx = nRefreshStartPos; nCurrModelIdx < nRefreshStartPos + nModelsToRefresh; ++nCurrModelIdx) {
+                int nSampleImgCoord_Y, nSampleImgCoord_X;
+                getRandSamplePosition(nSampleImgCoord_X, nSampleImgCoord_Y, m_aPxInfoLUT[nPxIter].nImgCoord_X, m_aPxInfoLUT[nPxIter].nImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+                const size_t nSamplePxIdx = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+                if (bForceFGUpdate || !m_oLastFGMask.data[nSamplePxIdx]) {
+                  const size_t nCurrRealModelIdx = nCurrModelIdx%m_nBGSamples;
+                  for (size_t c = 0; c < 3; ++c) {
+                    m_voBGColorSamples[nCurrRealModelIdx].data[nPxIter * 3 + c] = m_oLastColorFrame.data[nSamplePxIdx * 3 + c];
+                    *((ushort*)(m_voBGDescSamples[nCurrRealModelIdx].data + (nPxIter * 3 + c) * 2)) = *((ushort*)(m_oLastDescFrame.data + (nSamplePxIdx * 3 + c) * 2));
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      void BackgroundSubtractorSuBSENSE::apply(cv::InputArray _image, cv::OutputArray _fgmask, double learningRateOverride) {
+        // == process
+        CV_Assert(m_bInitialized);
+        cv::Mat oInputImg = _image.getMat();
+        CV_Assert(oInputImg.type() == m_nImgType && oInputImg.size() == m_oImgSize);
+        CV_Assert(oInputImg.isContinuous());
+        _fgmask.create(m_oImgSize, CV_8UC1);
+        cv::Mat oCurrFGMask = _fgmask.getMat();
+        memset(oCurrFGMask.data, 0, oCurrFGMask.cols*oCurrFGMask.rows);
+        size_t nNonZeroDescCount = 0;
+        const float fRollAvgFactor_LT = 1.0f / std::min(++m_nFrameIndex, m_nSamplesForMovingAvgs);
+        const float fRollAvgFactor_ST = 1.0f / std::min(m_nFrameIndex, m_nSamplesForMovingAvgs / 4);
+        if (m_nImgChannels == 1) {
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            const size_t nDescIter = nPxIter * 2;
+            const size_t nFloatIter = nPxIter * 4;
+            const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
+            const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
+            const uchar nCurrColor = oInputImg.data[nPxIter];
+            size_t nMinDescDist = s_nDescMaxDataRange_1ch;
+            size_t nMinSumDist = s_nColorMaxDataRange_1ch;
+            float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data + nFloatIter);
+            float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data + nFloatIter);
+            float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data + nFloatIter));
+            float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data + nFloatIter));
+            float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data + nFloatIter));
+            float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data + nFloatIter));
+            float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter));
+            float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter));
+            float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter));
+            float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter));
+            ushort& nLastIntraDesc = *((ushort*)(m_oLastDescFrame.data + nDescIter));
+            uchar& nLastColor = m_oLastColorFrame.data[nPxIter];
+            const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold) - ((!m_oUnstableRegionMask.data[nPxIter])*STAB_COLOR_DIST_OFFSET)) / 2;
+            const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(*pfCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (m_oUnstableRegionMask.data[nPxIter] * UNSTAB_DESC_DIST_OFFSET);
+            ushort nCurrInterDesc, nCurrIntraDesc;
+            LBSP::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nCurrIntraDesc);
+            m_oUnstableRegionMask.data[nPxIter] = ((*pfCurrDistThresholdFactor) > UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN) ? 1 : 0;
+            size_t nGoodSamplesCount = 0, nSampleIdx = 0;
+            while (nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples) {
+              const uchar& nBGColor = m_voBGColorSamples[nSampleIdx].data[nPxIter];
+              {
+                const size_t nColorDist = L1dist(nCurrColor, nBGColor);
+                if (nColorDist > nCurrColorDistThreshold)
+                  goto failedcheck1ch;
+                const ushort& nBGIntraDesc = *((ushort*)(m_voBGDescSamples[nSampleIdx].data + nDescIter));
+                const size_t nIntraDescDist = hdist(nCurrIntraDesc, nBGIntraDesc);
+                LBSP::computeGrayscaleDescriptor(oInputImg, nBGColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nBGColor], nCurrInterDesc);
+                const size_t nInterDescDist = hdist(nCurrInterDesc, nBGIntraDesc);
+                const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
+                if (nDescDist > nCurrDescDistThreshold)
+                  goto failedcheck1ch;
+                const size_t nSumDist = std::min((nDescDist / 4)*(s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch) + nColorDist, s_nColorMaxDataRange_1ch);
+                if (nSumDist > nCurrColorDistThreshold)
+                  goto failedcheck1ch;
+                if (nMinDescDist > nDescDist)
+                  nMinDescDist = nDescDist;
+                if (nMinSumDist > nSumDist)
+                  nMinSumDist = nSumDist;
+                nGoodSamplesCount++;
+              }
+            failedcheck1ch:
+              nSampleIdx++;
+            }
+            const float fNormalizedLastDist = ((float)L1dist(nLastColor, nCurrColor) / s_nColorMaxDataRange_1ch + (float)hdist(nLastIntraDesc, nCurrIntraDesc) / s_nDescMaxDataRange_1ch) / 2;
+            *pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f - fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST;
+            if (nGoodSamplesCount < m_nRequiredBGSamples) {
+              // == foreground
+              const float fNormalizedMinDist = std::min(1.0f, ((float)nMinSumDist / s_nColorMaxDataRange_1ch + (float)nMinDescDist / s_nDescMaxDataRange_1ch) / 2 + (float)(m_nRequiredBGSamples - nGoodSamplesCount) / m_nRequiredBGSamples);
+              *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
+              *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
+              oCurrFGMask.data[nPxIter] = UCHAR_MAX;
+              if (m_nModelResetCooldown && (rand() % (size_t)FEEDBACK_T_LOWER) == 0) {
+                const size_t s_rand = rand() % m_nBGSamples;
+                *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIter)) = nCurrIntraDesc;
+                m_voBGColorSamples[s_rand].data[nPxIter] = nCurrColor;
+              }
+            }
+            else {
+              // == background
+              const float fNormalizedMinDist = ((float)nMinSumDist / s_nColorMaxDataRange_1ch + (float)nMinDescDist / s_nDescMaxDataRange_1ch) / 2;
+              *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT);
+              *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST);
+              const size_t nLearningRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : (size_t)ceil(*pfCurrLearningRate);
+              if ((rand() % nLearningRate) == 0) {
+                const size_t s_rand = rand() % m_nBGSamples;
+                *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIter)) = nCurrIntraDesc;
+                m_voBGColorSamples[s_rand].data[nPxIter] = nCurrColor;
+              }
+              int nSampleImgCoord_Y, nSampleImgCoord_X;
+              const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[nPxIter];
+              if (bCurrUsing3x3Spread)
+                getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+              else
+                getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+              const size_t n_rand = rand();
+              const size_t idx_rand_uchar = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+              const size_t idx_rand_flt32 = idx_rand_uchar * 4;
+              const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data + idx_rand_flt32));
+              const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32));
+              if ((n_rand % (bCurrUsing3x3Spread ? nLearningRate : (nLearningRate / 2 + 1))) == 0
+                || (fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX && (n_rand % ((size_t)m_fCurrLearningRateLowerCap)) == 0)) {
+                const size_t idx_rand_ushrt = idx_rand_uchar * 2;
+                const size_t s_rand = rand() % m_nBGSamples;
+                *((ushort*)(m_voBGDescSamples[s_rand].data + idx_rand_ushrt)) = nCurrIntraDesc;
+                m_voBGColorSamples[s_rand].data[idx_rand_uchar] = nCurrColor;
+              }
+            }
+            if (m_oLastFGMask.data[nPxIter] || (std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[nPxIter])) {
+              if ((*pfCurrLearningRate) < m_fCurrLearningRateUpperCap)
+                *pfCurrLearningRate += FEEDBACK_T_INCR / (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor));
+            }
+            else if ((*pfCurrLearningRate) > m_fCurrLearningRateLowerCap)
+              *pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor) / std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST);
+            if ((*pfCurrLearningRate) < m_fCurrLearningRateLowerCap)
+              *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
+            else if ((*pfCurrLearningRate) > m_fCurrLearningRateUpperCap)
+              *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
+            if (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
+              (*pfCurrVariationFactor) += FEEDBACK_V_INCR;
+            else if ((*pfCurrVariationFactor) > FEEDBACK_V_DECR) {
+              (*pfCurrVariationFactor) -= m_oLastFGMask.data[nPxIter] ? FEEDBACK_V_DECR / 4 : m_oUnstableRegionMask.data[nPxIter] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
+              if ((*pfCurrVariationFactor) < FEEDBACK_V_DECR)
+                (*pfCurrVariationFactor) = FEEDBACK_V_DECR;
+            }
+            if ((*pfCurrDistThresholdFactor) < std::pow(1.0f + std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) * 2, 2))
+              (*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor - FEEDBACK_V_DECR);
+            else {
+              (*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR / (*pfCurrVariationFactor);
+              if ((*pfCurrDistThresholdFactor) < 1.0f)
+                (*pfCurrDistThresholdFactor) = 1.0f;
+            }
+            if (popcount(nCurrIntraDesc) >= 2)
+              ++nNonZeroDescCount;
+            nLastIntraDesc = nCurrIntraDesc;
+            nLastColor = nCurrColor;
+          }
+        }
+        else { //m_nImgChannels==3
+          for (size_t nModelIter = 0; nModelIter < m_nTotRelevantPxCount; ++nModelIter) {
+            const size_t nPxIter = m_aPxIdxLUT[nModelIter];
+            const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
+            const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
+            const size_t nPxIterRGB = nPxIter * 3;
+            const size_t nDescIterRGB = nPxIterRGB * 2;
+            const size_t nFloatIter = nPxIter * 4;
+            const uchar* const anCurrColor = oInputImg.data + nPxIterRGB;
+            size_t nMinTotDescDist = s_nDescMaxDataRange_3ch;
+            size_t nMinTotSumDist = s_nColorMaxDataRange_3ch;
+            float* pfCurrDistThresholdFactor = (float*)(m_oDistThresholdFrame.data + nFloatIter);
+            float* pfCurrVariationFactor = (float*)(m_oVariationModulatorFrame.data + nFloatIter);
+            float* pfCurrLearningRate = ((float*)(m_oUpdateRateFrame.data + nFloatIter));
+            float* pfCurrMeanLastDist = ((float*)(m_oMeanLastDistFrame.data + nFloatIter));
+            float* pfCurrMeanMinDist_LT = ((float*)(m_oMeanMinDistFrame_LT.data + nFloatIter));
+            float* pfCurrMeanMinDist_ST = ((float*)(m_oMeanMinDistFrame_ST.data + nFloatIter));
+            float* pfCurrMeanRawSegmRes_LT = ((float*)(m_oMeanRawSegmResFrame_LT.data + nFloatIter));
+            float* pfCurrMeanRawSegmRes_ST = ((float*)(m_oMeanRawSegmResFrame_ST.data + nFloatIter));
+            float* pfCurrMeanFinalSegmRes_LT = ((float*)(m_oMeanFinalSegmResFrame_LT.data + nFloatIter));
+            float* pfCurrMeanFinalSegmRes_ST = ((float*)(m_oMeanFinalSegmResFrame_ST.data + nFloatIter));
+            ushort* anLastIntraDesc = ((ushort*)(m_oLastDescFrame.data + nDescIterRGB));
+            uchar* anLastColor = m_oLastColorFrame.data + nPxIterRGB;
+            const size_t nCurrColorDistThreshold = (size_t)(((*pfCurrDistThresholdFactor)*m_nMinColorDistThreshold) - ((!m_oUnstableRegionMask.data[nPxIter])*STAB_COLOR_DIST_OFFSET));
+            const size_t nCurrDescDistThreshold = ((size_t)1 << ((size_t)floor(*pfCurrDistThresholdFactor + 0.5f))) + m_nDescDistThresholdOffset + (m_oUnstableRegionMask.data[nPxIter] * UNSTAB_DESC_DIST_OFFSET);
+            const size_t nCurrTotColorDistThreshold = nCurrColorDistThreshold * 3;
+            const size_t nCurrTotDescDistThreshold = nCurrDescDistThreshold * 3;
+            const size_t nCurrSCColorDistThreshold = nCurrTotColorDistThreshold / 2;
+            ushort anCurrInterDesc[3], anCurrIntraDesc[3];
+            const size_t anCurrIntraLBSPThresholds[3] = { m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]] };
+            LBSP::computeRGBDescriptor(oInputImg, anCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, anCurrIntraLBSPThresholds, anCurrIntraDesc);
+            m_oUnstableRegionMask.data[nPxIter] = ((*pfCurrDistThresholdFactor) > UNSTABLE_REG_RDIST_MIN || (*pfCurrMeanRawSegmRes_LT - *pfCurrMeanFinalSegmRes_LT) > UNSTABLE_REG_RATIO_MIN || (*pfCurrMeanRawSegmRes_ST - *pfCurrMeanFinalSegmRes_ST) > UNSTABLE_REG_RATIO_MIN) ? 1 : 0;
+            size_t nGoodSamplesCount = 0, nSampleIdx = 0;
+            while (nGoodSamplesCount < m_nRequiredBGSamples && nSampleIdx < m_nBGSamples) {
+              const ushort* const anBGIntraDesc = (ushort*)(m_voBGDescSamples[nSampleIdx].data + nDescIterRGB);
+              const uchar* const anBGColor = m_voBGColorSamples[nSampleIdx].data + nPxIterRGB;
+              size_t nTotDescDist = 0;
+              size_t nTotSumDist = 0;
+              for (size_t c = 0; c < 3; ++c) {
+                const size_t nColorDist = L1dist(anCurrColor[c], anBGColor[c]);
+                if (nColorDist > nCurrSCColorDistThreshold)
+                  goto failedcheck3ch;
+                const size_t nIntraDescDist = hdist(anCurrIntraDesc[c], anBGIntraDesc[c]);
+                LBSP::computeSingleRGBDescriptor(oInputImg, anBGColor[c], nCurrImgCoord_X, nCurrImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[anBGColor[c]], anCurrInterDesc[c]);
+                const size_t nInterDescDist = hdist(anCurrInterDesc[c], anBGIntraDesc[c]);
+                const size_t nDescDist = (nIntraDescDist + nInterDescDist) / 2;
+                const size_t nSumDist = std::min((nDescDist / 2)*(s_nColorMaxDataRange_1ch / s_nDescMaxDataRange_1ch) + nColorDist, s_nColorMaxDataRange_1ch);
+                if (nSumDist > nCurrSCColorDistThreshold)
+                  goto failedcheck3ch;
+                nTotDescDist += nDescDist;
+                nTotSumDist += nSumDist;
+              }
+              if (nTotDescDist > nCurrTotDescDistThreshold || nTotSumDist > nCurrTotColorDistThreshold)
+                goto failedcheck3ch;
+              if (nMinTotDescDist > nTotDescDist)
+                nMinTotDescDist = nTotDescDist;
+              if (nMinTotSumDist > nTotSumDist)
+                nMinTotSumDist = nTotSumDist;
+              nGoodSamplesCount++;
+            failedcheck3ch:
+              nSampleIdx++;
+            }
+            const float fNormalizedLastDist = ((float)L1dist<3>(anLastColor, anCurrColor) / s_nColorMaxDataRange_3ch + (float)hdist<3>(anLastIntraDesc, anCurrIntraDesc) / s_nDescMaxDataRange_3ch) / 2;
+            *pfCurrMeanLastDist = (*pfCurrMeanLastDist)*(1.0f - fRollAvgFactor_ST) + fNormalizedLastDist*fRollAvgFactor_ST;
+            if (nGoodSamplesCount < m_nRequiredBGSamples) {
+              // == foreground
+              const float fNormalizedMinDist = std::min(1.0f, ((float)nMinTotSumDist / s_nColorMaxDataRange_3ch + (float)nMinTotDescDist / s_nDescMaxDataRange_3ch) / 2 + (float)(m_nRequiredBGSamples - nGoodSamplesCount) / m_nRequiredBGSamples);
+              *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT) + fRollAvgFactor_LT;
+              *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST) + fRollAvgFactor_ST;
+              oCurrFGMask.data[nPxIter] = UCHAR_MAX;
+              if (m_nModelResetCooldown && (rand() % (size_t)FEEDBACK_T_LOWER) == 0) {
+                const size_t s_rand = rand() % m_nBGSamples;
+                for (size_t c = 0; c < 3; ++c) {
+                  *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIterRGB + 2 * c)) = anCurrIntraDesc[c];
+                  *(m_voBGColorSamples[s_rand].data + nPxIterRGB + c) = anCurrColor[c];
+                }
+              }
+            }
+            else {
+              // == background
+              const float fNormalizedMinDist = ((float)nMinTotSumDist / s_nColorMaxDataRange_3ch + (float)nMinTotDescDist / s_nDescMaxDataRange_3ch) / 2;
+              *pfCurrMeanMinDist_LT = (*pfCurrMeanMinDist_LT)*(1.0f - fRollAvgFactor_LT) + fNormalizedMinDist*fRollAvgFactor_LT;
+              *pfCurrMeanMinDist_ST = (*pfCurrMeanMinDist_ST)*(1.0f - fRollAvgFactor_ST) + fNormalizedMinDist*fRollAvgFactor_ST;
+              *pfCurrMeanRawSegmRes_LT = (*pfCurrMeanRawSegmRes_LT)*(1.0f - fRollAvgFactor_LT);
+              *pfCurrMeanRawSegmRes_ST = (*pfCurrMeanRawSegmRes_ST)*(1.0f - fRollAvgFactor_ST);
+              const size_t nLearningRate = learningRateOverride > 0 ? (size_t)ceil(learningRateOverride) : (size_t)ceil(*pfCurrLearningRate);
+              if ((rand() % nLearningRate) == 0) {
+                const size_t s_rand = rand() % m_nBGSamples;
+                for (size_t c = 0; c < 3; ++c) {
+                  *((ushort*)(m_voBGDescSamples[s_rand].data + nDescIterRGB + 2 * c)) = anCurrIntraDesc[c];
+                  *(m_voBGColorSamples[s_rand].data + nPxIterRGB + c) = anCurrColor[c];
+                }
+              }
+              int nSampleImgCoord_Y, nSampleImgCoord_X;
+              const bool bCurrUsing3x3Spread = m_bUse3x3Spread && !m_oUnstableRegionMask.data[nPxIter];
+              if (bCurrUsing3x3Spread)
+                getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+              else
+                getRandNeighborPosition_5x5(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize);
+              const size_t n_rand = rand();
+              const size_t idx_rand_uchar = m_oImgSize.width*nSampleImgCoord_Y + nSampleImgCoord_X;
+              const size_t idx_rand_flt32 = idx_rand_uchar * 4;
+              const float fRandMeanLastDist = *((float*)(m_oMeanLastDistFrame.data + idx_rand_flt32));
+              const float fRandMeanRawSegmRes = *((float*)(m_oMeanRawSegmResFrame_ST.data + idx_rand_flt32));
+              if ((n_rand % (bCurrUsing3x3Spread ? nLearningRate : (nLearningRate / 2 + 1))) == 0
+                || (fRandMeanRawSegmRes > GHOSTDET_S_MIN && fRandMeanLastDist < GHOSTDET_D_MAX && (n_rand % ((size_t)m_fCurrLearningRateLowerCap)) == 0)) {
+                const size_t idx_rand_uchar_rgb = idx_rand_uchar * 3;
+                const size_t idx_rand_ushrt_rgb = idx_rand_uchar_rgb * 2;
+                const size_t s_rand = rand() % m_nBGSamples;
+                for (size_t c = 0; c < 3; ++c) {
+                  *((ushort*)(m_voBGDescSamples[s_rand].data + idx_rand_ushrt_rgb + 2 * c)) = anCurrIntraDesc[c];
+                  *(m_voBGColorSamples[s_rand].data + idx_rand_uchar_rgb + c) = anCurrColor[c];
+                }
+              }
+            }
+            if (m_oLastFGMask.data[nPxIter] || (std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) < UNSTABLE_REG_RATIO_MIN && oCurrFGMask.data[nPxIter])) {
+              if ((*pfCurrLearningRate) < m_fCurrLearningRateUpperCap)
+                *pfCurrLearningRate += FEEDBACK_T_INCR / (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST)*(*pfCurrVariationFactor));
+            }
+            else if ((*pfCurrLearningRate) > m_fCurrLearningRateLowerCap)
+              *pfCurrLearningRate -= FEEDBACK_T_DECR*(*pfCurrVariationFactor) / std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST);
+            if ((*pfCurrLearningRate) < m_fCurrLearningRateLowerCap)
+              *pfCurrLearningRate = m_fCurrLearningRateLowerCap;
+            else if ((*pfCurrLearningRate) > m_fCurrLearningRateUpperCap)
+              *pfCurrLearningRate = m_fCurrLearningRateUpperCap;
+            if (std::max(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) > UNSTABLE_REG_RATIO_MIN && m_oBlinksFrame.data[nPxIter])
+              (*pfCurrVariationFactor) += FEEDBACK_V_INCR;
+            else if ((*pfCurrVariationFactor) > FEEDBACK_V_DECR) {
+              (*pfCurrVariationFactor) -= m_oLastFGMask.data[nPxIter] ? FEEDBACK_V_DECR / 4 : m_oUnstableRegionMask.data[nPxIter] ? FEEDBACK_V_DECR / 2 : FEEDBACK_V_DECR;
+              if ((*pfCurrVariationFactor) < FEEDBACK_V_DECR)
+                (*pfCurrVariationFactor) = FEEDBACK_V_DECR;
+            }
+            if ((*pfCurrDistThresholdFactor) < std::pow(1.0f + std::min(*pfCurrMeanMinDist_LT, *pfCurrMeanMinDist_ST) * 2, 2))
+              (*pfCurrDistThresholdFactor) += FEEDBACK_R_VAR*(*pfCurrVariationFactor - FEEDBACK_V_DECR);
+            else {
+              (*pfCurrDistThresholdFactor) -= FEEDBACK_R_VAR / (*pfCurrVariationFactor);
+              if ((*pfCurrDistThresholdFactor) < 1.0f)
+                (*pfCurrDistThresholdFactor) = 1.0f;
+            }
+            if (popcount<3>(anCurrIntraDesc) >= 4)
+              ++nNonZeroDescCount;
+            for (size_t c = 0; c < 3; ++c) {
+              anLastIntraDesc[c] = anCurrIntraDesc[c];
+              anLastColor[c] = anCurrColor[c];
+            }
+          }
+        }
+#if DISPLAY_SUBSENSE_DEBUG_INFO
+        std::cout << std::endl;
+        cv::Point dbgpt(nDebugCoordX, nDebugCoordY);
+        cv::Mat oMeanMinDistFrameNormalized; m_oMeanMinDistFrame_ST.copyTo(oMeanMinDistFrameNormalized);
+        cv::circle(oMeanMinDistFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oMeanMinDistFrameNormalized, oMeanMinDistFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("d_min(x)", oMeanMinDistFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "  d_min(" << dbgpt << ") = " << m_oMeanMinDistFrame_ST.at<float>(dbgpt) << std::endl;
+        cv::Mat oMeanLastDistFrameNormalized; m_oMeanLastDistFrame.copyTo(oMeanLastDistFrameNormalized);
+        cv::circle(oMeanLastDistFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oMeanLastDistFrameNormalized, oMeanLastDistFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("d_last(x)", oMeanLastDistFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << " d_last(" << dbgpt << ") = " << m_oMeanLastDistFrame.at<float>(dbgpt) << std::endl;
+        cv::Mat oMeanRawSegmResFrameNormalized; m_oMeanRawSegmResFrame_ST.copyTo(oMeanRawSegmResFrameNormalized);
+        cv::circle(oMeanRawSegmResFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oMeanRawSegmResFrameNormalized, oMeanRawSegmResFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("s_avg(x)", oMeanRawSegmResFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "  s_avg(" << dbgpt << ") = " << m_oMeanRawSegmResFrame_ST.at<float>(dbgpt) << std::endl;
+        cv::Mat oMeanFinalSegmResFrameNormalized; m_oMeanFinalSegmResFrame_ST.copyTo(oMeanFinalSegmResFrameNormalized);
+        cv::circle(oMeanFinalSegmResFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oMeanFinalSegmResFrameNormalized, oMeanFinalSegmResFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("z_avg(x)", oMeanFinalSegmResFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "  z_avg(" << dbgpt << ") = " << m_oMeanFinalSegmResFrame_ST.at<float>(dbgpt) << std::endl;
+        cv::Mat oDistThresholdFrameNormalized; m_oDistThresholdFrame.convertTo(oDistThresholdFrameNormalized, CV_32FC1, 0.25f, -0.25f);
+        cv::circle(oDistThresholdFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oDistThresholdFrameNormalized, oDistThresholdFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("r(x)", oDistThresholdFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "      r(" << dbgpt << ") = " << m_oDistThresholdFrame.at<float>(dbgpt) << std::endl;
+        cv::Mat oVariationModulatorFrameNormalized; cv::normalize(m_oVariationModulatorFrame, oVariationModulatorFrameNormalized, 0, 255, cv::NORM_MINMAX, CV_8UC1);
+        cv::circle(oVariationModulatorFrameNormalized, dbgpt, 5, cv::Scalar(255));
+        cv::resize(oVariationModulatorFrameNormalized, oVariationModulatorFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("v(x)", oVariationModulatorFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "      v(" << dbgpt << ") = " << m_oVariationModulatorFrame.at<float>(dbgpt) << std::endl;
+        cv::Mat oUpdateRateFrameNormalized; m_oUpdateRateFrame.convertTo(oUpdateRateFrameNormalized, CV_32FC1, 1.0f / FEEDBACK_T_UPPER, -FEEDBACK_T_LOWER / FEEDBACK_T_UPPER);
+        cv::circle(oUpdateRateFrameNormalized, dbgpt, 5, cv::Scalar(1.0f));
+        cv::resize(oUpdateRateFrameNormalized, oUpdateRateFrameNormalized, DEFAULT_FRAME_SIZE);
+        cv::imshow("t(x)", oUpdateRateFrameNormalized);
+        std::cout << std::fixed << std::setprecision(5) << "      t(" << dbgpt << ") = " << m_oUpdateRateFrame.at<float>(dbgpt) << std::endl;
+#endif //DISPLAY_SUBSENSE_DEBUG_INFO
+        cv::bitwise_xor(oCurrFGMask, m_oLastRawFGMask, m_oCurrRawFGBlinkMask);
+        cv::bitwise_or(m_oCurrRawFGBlinkMask, m_oLastRawFGBlinkMask, m_oBlinksFrame);
+        m_oCurrRawFGBlinkMask.copyTo(m_oLastRawFGBlinkMask);
+        oCurrFGMask.copyTo(m_oLastRawFGMask);
+        cv::morphologyEx(oCurrFGMask, m_oFGMask_PreFlood, cv::MORPH_CLOSE, cv::Mat());
+        m_oFGMask_PreFlood.copyTo(m_oFGMask_FloodedHoles);
+        cv::floodFill(m_oFGMask_FloodedHoles, cv::Point(0, 0), UCHAR_MAX);
+        cv::bitwise_not(m_oFGMask_FloodedHoles, m_oFGMask_FloodedHoles);
+        cv::erode(m_oFGMask_PreFlood, m_oFGMask_PreFlood, cv::Mat(), cv::Point(-1, -1), 3);
+        cv::bitwise_or(oCurrFGMask, m_oFGMask_FloodedHoles, oCurrFGMask);
+        cv::bitwise_or(oCurrFGMask, m_oFGMask_PreFlood, oCurrFGMask);
+        cv::medianBlur(oCurrFGMask, m_oLastFGMask, m_nMedianBlurKernelSize);
+        cv::dilate(m_oLastFGMask, m_oLastFGMask_dilated, cv::Mat(), cv::Point(-1, -1), 3);
+        cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
+        cv::bitwise_not(m_oLastFGMask_dilated, m_oLastFGMask_dilated_inverted);
+        cv::bitwise_and(m_oBlinksFrame, m_oLastFGMask_dilated_inverted, m_oBlinksFrame);
+        m_oLastFGMask.copyTo(oCurrFGMask);
+        cv::addWeighted(m_oMeanFinalSegmResFrame_LT, (1.0f - fRollAvgFactor_LT), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_LT, 0, m_oMeanFinalSegmResFrame_LT, CV_32F);
+        cv::addWeighted(m_oMeanFinalSegmResFrame_ST, (1.0f - fRollAvgFactor_ST), m_oLastFGMask, (1.0 / UCHAR_MAX)*fRollAvgFactor_ST, 0, m_oMeanFinalSegmResFrame_ST, CV_32F);
+        const float fCurrNonZeroDescRatio = (float)nNonZeroDescCount / m_nTotRelevantPxCount;
+        if (fCurrNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN && m_fLastNonZeroDescRatio < LBSPDESC_NONZERO_RATIO_MIN) {
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            if (m_anLBSPThreshold_8bitLUT[t] > cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + ceil(t*m_fRelLBSPThreshold / 4)))
+              --m_anLBSPThreshold_8bitLUT[t];
+        }
+        else if (fCurrNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX && m_fLastNonZeroDescRatio > LBSPDESC_NONZERO_RATIO_MAX) {
+          for (size_t t = 0; t <= UCHAR_MAX; ++t)
+            if (m_anLBSPThreshold_8bitLUT[t] < cv::saturate_cast<uchar>(m_nLBSPThresholdOffset + UCHAR_MAX*m_fRelLBSPThreshold))
+              ++m_anLBSPThreshold_8bitLUT[t];
+        }
+        m_fLastNonZeroDescRatio = fCurrNonZeroDescRatio;
+        if (m_bLearningRateScalingEnabled) {
+          cv::resize(oInputImg, m_oDownSampledFrame_MotionAnalysis, m_oDownSampledFrameSize, 0, 0, cv::INTER_AREA);
+          cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_LT, fRollAvgFactor_LT);
+          cv::accumulateWeighted(m_oDownSampledFrame_MotionAnalysis, m_oMeanDownSampledLastDistFrame_ST, fRollAvgFactor_ST);
+          size_t nTotColorDiff = 0;
+          for (int i = 0; i < m_oMeanDownSampledLastDistFrame_ST.rows; ++i) {
+            const size_t idx1 = m_oMeanDownSampledLastDistFrame_ST.step.p[0] * i;
+            for (int j = 0; j < m_oMeanDownSampledLastDistFrame_ST.cols; ++j) {
+              const size_t idx2 = idx1 + m_oMeanDownSampledLastDistFrame_ST.step.p[1] * j;
+              nTotColorDiff += (m_nImgChannels == 1) ?
+                (size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2))) / 2
+                :  //(m_nImgChannels==3)
+                std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2))),
+                  std::max((size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 4)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 4))),
+                  (size_t)fabs((*(float*)(m_oMeanDownSampledLastDistFrame_ST.data + idx2 + 8)) - (*(float*)(m_oMeanDownSampledLastDistFrame_LT.data + idx2 + 8)))));
+            }
+          }
+          const float fCurrColorDiffRatio = (float)nTotColorDiff / (m_oMeanDownSampledLastDistFrame_ST.rows*m_oMeanDownSampledLastDistFrame_ST.cols);
+          if (m_bAutoModelResetEnabled) {
+            if (m_nFramesSinceLastReset > 1000)
+              m_bAutoModelResetEnabled = false;
+            else if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD && m_nModelResetCooldown == 0) {
+              m_nFramesSinceLastReset = 0;
+              refreshModel(0.1f); // reset 10% of the bg model
+              m_nModelResetCooldown = m_nSamplesForMovingAvgs / 4;
+              m_oUpdateRateFrame = cv::Scalar(1.0f);
+            }
+            else
+              ++m_nFramesSinceLastReset;
+          }
+          else if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD * 2) {
+            m_nFramesSinceLastReset = 0;
+            m_bAutoModelResetEnabled = true;
+          }
+          if (fCurrColorDiffRatio >= FRAMELEVEL_MIN_COLOR_DIFF_THRESHOLD / 2) {
+            m_fCurrLearningRateLowerCap = (float)std::max((int)FEEDBACK_T_LOWER >> (int)(fCurrColorDiffRatio / 2), 1);
+            m_fCurrLearningRateUpperCap = (float)std::max((int)FEEDBACK_T_UPPER >> (int)(fCurrColorDiffRatio / 2), 1);
+          }
+          else {
+            m_fCurrLearningRateLowerCap = FEEDBACK_T_LOWER;
+            m_fCurrLearningRateUpperCap = FEEDBACK_T_UPPER;
+          }
+          if (m_nModelResetCooldown > 0)
+            --m_nModelResetCooldown;
+        }
+      }
+
+      void BackgroundSubtractorSuBSENSE::getBackgroundImage(cv::OutputArray backgroundImage) const {
+        CV_Assert(m_bInitialized);
+        cv::Mat oAvgBGImg = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
+        for (size_t s = 0; s < m_nBGSamples; ++s) {
+          for (int y = 0; y < m_oImgSize.height; ++y) {
+            for (int x = 0; x < m_oImgSize.width; ++x) {
+              const size_t idx_nimg = m_voBGColorSamples[s].step.p[0] * y + m_voBGColorSamples[s].step.p[1] * x;
+              const size_t nFloatIter = idx_nimg * 4;
+              float* oAvgBgImgPtr = (float*)(oAvgBGImg.data + nFloatIter);
+              const uchar* const oBGImgPtr = m_voBGColorSamples[s].data + idx_nimg;
+              for (size_t c = 0; c < m_nImgChannels; ++c)
+                oAvgBgImgPtr[c] += ((float)oBGImgPtr[c]) / m_nBGSamples;
+            }
+          }
+        }
+        oAvgBGImg.convertTo(backgroundImage, CV_8U);
+      }
+
+      void BackgroundSubtractorSuBSENSE::getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const {
+        CV_Assert(LBSP::DESC_SIZE == 2);
+        CV_Assert(m_bInitialized);
+        cv::Mat oAvgBGDesc = cv::Mat::zeros(m_oImgSize, CV_32FC((int)m_nImgChannels));
+        for (size_t n = 0; n < m_voBGDescSamples.size(); ++n) {
+          for (int y = 0; y < m_oImgSize.height; ++y) {
+            for (int x = 0; x < m_oImgSize.width; ++x) {
+              const size_t idx_ndesc = m_voBGDescSamples[n].step.p[0] * y + m_voBGDescSamples[n].step.p[1] * x;
+              const size_t nFloatIter = idx_ndesc * 2;
+              float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data + nFloatIter);
+              const ushort* const oBGDescPtr = (ushort*)(m_voBGDescSamples[n].data + idx_ndesc);
+              for (size_t c = 0; c < m_nImgChannels; ++c)
+                oAvgBgDescPtr[c] += ((float)oBGDescPtr[c]) / m_voBGDescSamples.size();
+            }
+          }
+        }
+        oAvgBGDesc.convertTo(backgroundDescImage, CV_16U);
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.h b/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ec95e1e0825a24102ebbf34e2dff12470604b2b
--- /dev/null
+++ b/src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include "BackgroundSubtractorLBSP.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      //! defines the default value for BackgroundSubtractorLBSP::m_fRelLBSPThreshold
+      const float BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD = 0.333f;
+      //! defines the default value for BackgroundSubtractorSuBSENSE::m_nDescDistThresholdOffset
+      const int BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET = 3;
+      //! defines the default value for BackgroundSubtractorSuBSENSE::m_nMinColorDistThreshold
+      const int BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD = 30;
+      //! defines the default value for BackgroundSubtractorSuBSENSE::m_nBGSamples
+      const int BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES = 50;
+      //! defines the default value for BackgroundSubtractorSuBSENSE::m_nRequiredBGSamples
+      const int BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES = 2;
+      //! defines the default value for BackgroundSubtractorSuBSENSE::m_nSamplesForMovingAvgs
+      const int BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS = 100;
+
+      /*!
+        Self-Balanced Sensitivity segmenTER (SuBSENSE) change detection algorithm.
+
+        Note: both grayscale and RGB/BGR images may be used with this extractor (parameters are adjusted automatically).
+        For optimal grayscale results, use CV_8UC1 frames instead of CV_8UC3.
+
+        For more details on the different parameters or on the algorithm itself, see P.-L. St-Charles et al.,
+        "Flexible Background Subtraction With Self-Balanced Local Sensitivity", in CVPRW 2014.
+
+        This algorithm is currently NOT thread-safe.
+      */
+      class BackgroundSubtractorSuBSENSE : public BackgroundSubtractorLBSP {
+      public:
+        //! full constructor
+        BackgroundSubtractorSuBSENSE(float fRelLBSPThreshold = BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD,
+          size_t nDescDistThresholdOffset = BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET,
+          size_t nMinColorDistThreshold = BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD,
+          size_t nBGSamples = BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES,
+          size_t nRequiredBGSamples = BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES,
+          size_t nSamplesForMovingAvgs = BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS);
+        //! default destructor
+        virtual ~BackgroundSubtractorSuBSENSE();
+        //! (re)initiaization method; needs to be called before starting background subtraction
+        virtual void initialize(const cv::Mat& oInitImg, const cv::Mat& oROI);
+        //! refreshes all samples based on the last analyzed frame
+        virtual void refreshModel(float fSamplesRefreshFrac, bool bForceFGUpdate = false);
+        //! primary model update function; the learning param is used to override the internal learning thresholds (ignored when <= 0)
+        virtual void apply(cv::InputArray image, cv::OutputArray fgmask, double learningRateOverride = 0);
+        //! returns a copy of the latest reconstructed background image
+        void getBackgroundImage(cv::OutputArray backgroundImage) const;
+        //! returns a copy of the latest reconstructed background descriptors image
+        void getBackgroundDescriptorsImage(cv::OutputArray backgroundDescImage) const;
+
+      protected:
+        //! absolute minimal color distance threshold ('R' or 'radius' in the original ViBe paper, used as the default/initial 'R(x)' value here)
+        const size_t m_nMinColorDistThreshold;
+        //! absolute descriptor distance threshold offset
+        const size_t m_nDescDistThresholdOffset;
+        //! number of different samples per pixel/block to be taken from input frames to build the background model (same as 'N' in ViBe/PBAS)
+        const size_t m_nBGSamples;
+        //! number of similar samples needed to consider the current pixel/block as 'background' (same as '#_min' in ViBe/PBAS)
+        const size_t m_nRequiredBGSamples;
+        //! number of samples to use to compute the learning rate of moving averages
+        const size_t m_nSamplesForMovingAvgs;
+        //! last calculated non-zero desc ratio
+        float m_fLastNonZeroDescRatio;
+        //! specifies whether Tmin/Tmax scaling is enabled or not
+        bool m_bLearningRateScalingEnabled;
+        //! current learning rate caps
+        float m_fCurrLearningRateLowerCap, m_fCurrLearningRateUpperCap;
+        //! current kernel size for median blur post-proc filtering
+        int m_nMedianBlurKernelSize;
+        //! specifies the px update spread range
+        bool m_bUse3x3Spread;
+        //! specifies the downsampled frame size used for cam motion analysis
+        cv::Size m_oDownSampledFrameSize;
+
+        //! background model pixel color intensity samples (equivalent to 'B(x)' in PBAS)
+        std::vector<cv::Mat> m_voBGColorSamples;
+        //! background model descriptors samples
+        std::vector<cv::Mat> m_voBGDescSamples;
+
+        //! per-pixel update rates ('T(x)' in PBAS, which contains pixel-level 'sigmas', as referred to in ViBe)
+        cv::Mat m_oUpdateRateFrame;
+        //! per-pixel distance thresholds (equivalent to 'R(x)' in PBAS, but used as a relative value to determine both intensity and descriptor variation thresholds)
+        cv::Mat m_oDistThresholdFrame;
+        //! per-pixel distance variation modulators ('v(x)', relative value used to modulate 'R(x)' and 'T(x)' variations)
+        cv::Mat m_oVariationModulatorFrame;
+        //! per-pixel mean distances between consecutive frames ('D_last(x)', used to detect ghosts and high variation regions in the sequence)
+        cv::Mat m_oMeanLastDistFrame;
+        //! per-pixel mean minimal distances from the model ('D_min(x)' in PBAS, used to control variation magnitude and direction of 'T(x)' and 'R(x)')
+        cv::Mat m_oMeanMinDistFrame_LT, m_oMeanMinDistFrame_ST;
+        //! per-pixel mean downsampled distances between consecutive frames (used to analyze camera movement and control max learning rates globally)
+        cv::Mat m_oMeanDownSampledLastDistFrame_LT, m_oMeanDownSampledLastDistFrame_ST;
+        //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
+        cv::Mat m_oMeanRawSegmResFrame_LT, m_oMeanRawSegmResFrame_ST;
+        //! per-pixel mean raw segmentation results (used to detect unstable segmentation regions)
+        cv::Mat m_oMeanFinalSegmResFrame_LT, m_oMeanFinalSegmResFrame_ST;
+        //! a lookup map used to keep track of unstable regions (based on segm. noise & local dist. thresholds)
+        cv::Mat m_oUnstableRegionMask;
+        //! per-pixel blink detection map ('Z(x)')
+        cv::Mat m_oBlinksFrame;
+        //! pre-allocated matrix used to downsample the input frame when needed
+        cv::Mat m_oDownSampledFrame_MotionAnalysis;
+        //! the foreground mask generated by the method at [t-1] (without post-proc, used for blinking px detection)
+        cv::Mat m_oLastRawFGMask;
+
+        //! pre-allocated CV_8UC1 matrices used to speed up morph ops
+        cv::Mat m_oFGMask_PreFlood;
+        cv::Mat m_oFGMask_FloodedHoles;
+        cv::Mat m_oLastFGMask_dilated;
+        cv::Mat m_oLastFGMask_dilated_inverted;
+        cv::Mat m_oCurrRawFGBlinkMask;
+        cv::Mat m_oLastRawFGBlinkMask;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/DistanceUtils.h b/src/algorithms/LBSP/DistanceUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..59a0fe1b96cd248b7811ab7a2857227fed6a2e9a
--- /dev/null
+++ b/src/algorithms/LBSP/DistanceUtils.h
@@ -0,0 +1,326 @@
+#pragma once
+
+// opencv legacy includes
+#include <opencv2/core/types_c.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      //! computes the L1 distance between two integer values
+      template<typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type L1dist(T a, T b) {
+        return (size_t)abs((int)a-b);
+      }
+
+      //! computes the L1 distance between two float values
+      template<typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type L1dist(T a, T b) {
+        return fabs((float)a-(float)b);
+      }
+
+      //! computes the L1 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline auto L1dist(const T* a, const T* b) -> decltype(L1dist(*a,*b)) {
+        decltype(L1dist(*a,*b)) oResult = 0;
+        for(size_t c=0; c<nChannels; ++c)
+          oResult += L1dist(a[c],b[c]);
+        return oResult;
+      }
+
+      //! computes the L1 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline auto L1dist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(L1dist<nChannels>(a,b)) {
+        decltype(L1dist<nChannels>(a,b)) oResult = 0;
+        size_t nTotElements = nElements*nChannels;
+        if(m) {
+          for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
+            if(m[i])
+              oResult += L1dist<nChannels>(a+n,b+n);
+        }
+        else {
+          for(size_t n=0; n<nTotElements; n+=nChannels)
+            oResult += L1dist<nChannels>(a+n,b+n);
+        }
+        return oResult;
+      }
+
+      //! computes the L1 distance between two generic arrays
+      template<typename T> static inline auto L1dist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(L1dist<3>(a,b,nElements,m)) {
+        CV_Assert(nChannels>0 && nChannels<=4);
+        switch(nChannels) {
+        case 1: return L1dist<1>(a,b,nElements,m);
+        case 2: return L1dist<2>(a,b,nElements,m);
+        case 3: return L1dist<3>(a,b,nElements,m);
+        case 4: return L1dist<4>(a,b,nElements,m);
+        default: return 0;
+        }
+      }
+
+      //! computes the L1 distance between two opencv vectors
+      template<size_t nChannels, typename T> static inline auto L1dist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(L1dist<nChannels,T>((T*)(0),(T*)(0))) {
+        T a_array[nChannels], b_array[nChannels];
+        for(size_t c=0; c<nChannels; ++c) {
+          a_array[c] = a[(int)c];
+          b_array[c] = b[(int)c];
+        }
+        return L1dist<nChannels>(a_array,b_array);
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////////////////////////
+
+      //! computes the squared L2 distance between two generic variables
+      template<typename T> static inline auto L2sqrdist(T a, T b) -> decltype(L1dist(a,b)) {
+        auto oResult = L1dist(a,b);
+        return oResult*oResult;
+      }
+
+      //! computes the squared L2 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline auto L2sqrdist(const T* a, const T* b) -> decltype(L2sqrdist(*a,*b)) {
+        decltype(L2sqrdist(*a,*b)) oResult = 0;
+        for(size_t c=0; c<nChannels; ++c)
+          oResult += L2sqrdist(a[c],b[c]);
+        return oResult;
+      }
+
+      //! computes the squared L2 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline auto L2sqrdist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(L2sqrdist<nChannels>(a,b)) {
+        decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
+        size_t nTotElements = nElements*nChannels;
+        if(m) {
+          for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
+            if(m[i])
+              oResult += L2sqrdist<nChannels>(a+n,b+n);
+        }
+        else {
+          for(size_t n=0; n<nTotElements; n+=nChannels)
+            oResult += L2sqrdist<nChannels>(a+n,b+n);
+        }
+        return oResult;
+      }
+
+      //! computes the squared L2 distance between two generic arrays
+      template<typename T> static inline auto L2sqrdist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(L2sqrdist<3>(a,b,nElements,m)) {
+        CV_Assert(nChannels>0 && nChannels<=4);
+        switch(nChannels) {
+        case 1: return L2sqrdist<1>(a,b,nElements,m);
+        case 2: return L2sqrdist<2>(a,b,nElements,m);
+        case 3: return L2sqrdist<3>(a,b,nElements,m);
+        case 4: return L2sqrdist<4>(a,b,nElements,m);
+        default: return 0;
+        }
+      }
+
+      //! computes the squared L2 distance between two opencv vectors
+      template<size_t nChannels, typename T> static inline auto L2sqrdist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(L2sqrdist<nChannels,T>((T*)(0),(T*)(0))) {
+        T a_array[nChannels], b_array[nChannels];
+        for(size_t c=0; c<nChannels; ++c) {
+          a_array[c] = a[(int)c];
+          b_array[c] = b[(int)c];
+        }
+        return L2sqrdist<nChannels>(a_array,b_array);
+      }
+
+      //! computes the L2 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline float L2dist(const T* a, const T* b) {
+        decltype(L2sqrdist(*a,*b)) oResult = 0;
+        for(size_t c=0; c<nChannels; ++c)
+          oResult += L2sqrdist(a[c],b[c]);
+        return sqrt((float)oResult);
+      }
+
+      //! computes the L2 distance between two generic arrays
+      template<size_t nChannels, typename T> static inline float L2dist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) {
+        decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
+        size_t nTotElements = nElements*nChannels;
+        if(m) {
+          for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
+            if(m[i])
+              oResult += L2sqrdist<nChannels>(a+n,b+n);
+        }
+        else {
+          for(size_t n=0; n<nTotElements; n+=nChannels)
+            oResult += L2sqrdist<nChannels>(a+n,b+n);
+        }
+        return sqrt((float)oResult);
+      }
+
+      //! computes the squared L2 distance between two generic arrays
+      template<typename T> static inline float L2dist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) {
+        CV_Assert(nChannels>0 && nChannels<=4);
+        switch(nChannels) {
+        case 1: return L2dist<1>(a,b,nElements,m);
+        case 2: return L2dist<2>(a,b,nElements,m);
+        case 3: return L2dist<3>(a,b,nElements,m);
+        case 4: return L2dist<4>(a,b,nElements,m);
+        default: return 0;
+        }
+      }
+
+      //! computes the L2 distance between two opencv vectors
+      template<size_t nChannels, typename T> static inline float L2dist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) {
+        T a_array[nChannels], b_array[nChannels];
+        for(size_t c=0; c<nChannels; ++c) {
+          a_array[c] = a[(int)c];
+          b_array[c] = b[(int)c];
+        }
+        return L2dist<nChannels>(a_array,b_array);
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////////////////////////
+
+      //! computes the color distortion between two integer arrays
+      template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type cdist(const T* curr, const T* bg) {
+        static_assert(nChannels>1,"cdist: requires more than one channel");
+        size_t curr_sqr = 0;
+        bool bSkip = true;
+        for(size_t c=0; c<nChannels; ++c) {
+          curr_sqr += curr[c]*curr[c];
+          bSkip = bSkip&(bg[c]<=0);
+        }
+        if(bSkip)
+          return (size_t)sqrt((float)curr_sqr);
+        size_t bg_sqr = 0;
+        size_t mix = 0;
+        for(size_t c=0; c<nChannels; ++c) {
+          bg_sqr += bg[c]*bg[c];
+          mix += curr[c]*bg[c];
+        }
+        return (size_t)sqrt(curr_sqr-((float)(mix*mix)/bg_sqr));
+      }
+
+      //! computes the color distortion between two float arrays
+      template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type cdist(const T* curr, const T* bg) {
+        static_assert(nChannels>1,"cdist: requires more than one channel");
+        float curr_sqr = 0;
+        bool bSkip = true;
+        for(size_t c=0; c<nChannels; ++c) {
+          curr_sqr += (float)curr[c]*curr[c];
+          bSkip = bSkip&(bg[c]<=0);
+        }
+        if(bSkip)
+          return sqrt(curr_sqr);
+        float bg_sqr = 0;
+        float mix = 0;
+        for(size_t c=0; c<nChannels; ++c) {
+          bg_sqr += (float)bg[c]*bg[c];
+          mix += (float)curr[c]*bg[c];
+        }
+        return sqrt(curr_sqr-((mix*mix)/bg_sqr));
+      }
+
+      //! computes the color distortion between two generic arrays
+      template<size_t nChannels, typename T> static inline auto cdist(const T* a, const T* b, size_t nElements, const uchar* m=NULL) -> decltype(cdist<nChannels>(a,b)) {
+        decltype(cdist<nChannels>(a,b)) oResult = 0;
+        size_t nTotElements = nElements*nChannels;
+        if(m) {
+          for(size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
+            if(m[i])
+              oResult += cdist<nChannels>(a+n,b+n);
+        }
+        else {
+          for(size_t n=0; n<nTotElements; n+=nChannels)
+            oResult += cdist<nChannels>(a+n,b+n);
+        }
+        return oResult;
+      }
+
+      //! computes the color distortion between two generic arrays
+      template<typename T> static inline auto cdist(const T* a, const T* b, size_t nElements, size_t nChannels, const uchar* m=NULL) -> decltype(cdist<3>(a,b,nElements,m)) {
+        CV_Assert(nChannels>1 && nChannels<=4);
+        switch(nChannels) {
+        case 2: return cdist<2>(a,b,nElements,m);
+        case 3: return cdist<3>(a,b,nElements,m);
+        case 4: return cdist<4>(a,b,nElements,m);
+        default: return 0;
+        }
+      }
+
+      //! computes the color distortion between two opencv vectors
+      template<size_t nChannels, typename T> static inline auto cdist_(const cv::Vec<T,nChannels>& a, const cv::Vec<T,nChannels>& b) -> decltype(cdist<nChannels,T>((T*)(0),(T*)(0))) {
+        T a_array[nChannels], b_array[nChannels];
+        for(size_t c=0; c<nChannels; ++c) {
+          a_array[c] = a[(int)c];
+          b_array[c] = b[(int)c];
+        }
+        return cdist<nChannels>(a_array,b_array);
+      }
+
+      //! computes a color distortion-distance mix using two generic distances
+      template<typename T> static inline T cmixdist(T oL1Distance, T oCDistortion) {
+        return (oL1Distance/2+oCDistortion*4);
+      }
+
+      //! computes a color distoirtion-distance mix using two generic arrays
+      template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_integral<T>::value,size_t>::type cmixdist(const T* curr, const T* bg) {
+        return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
+      }
+
+      template<size_t nChannels, typename T> static inline typename std::enable_if<std::is_floating_point<T>::value,float>::type cmixdist(const T* curr, const T* bg) {
+        return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////////////////////////
+
+      //! popcount LUT for 8-bit vectors
+      static const uchar popcount_LUT8[256] = {
+        0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+      };
+
+      //! computes the population count of an N-byte vector using an 8-bit popcount LUT
+      template<typename T> static inline size_t popcount(T x) {
+        size_t nBytes = sizeof(T);
+        size_t nResult = 0;
+        for(size_t l=0; l<nBytes; ++l)
+          nResult += popcount_LUT8[(uchar)(x>>l*8)];
+        return nResult;
+      }
+
+      //! computes the hamming distance between two N-byte vectors using an 8-bit popcount LUT
+      template<typename T> static inline size_t hdist(T a, T b) {
+        return popcount(a^b);
+      }
+
+      //! computes the gradient magnitude distance between two N-byte vectors using an 8-bit popcount LUT
+      template<typename T> static inline size_t gdist(T a, T b) {
+        return L1dist(popcount(a),popcount(b));
+      }
+
+      //! computes the population count of a (nChannels*N)-byte vector using an 8-bit popcount LUT
+      template<size_t nChannels, typename T> static inline size_t popcount(const T* x) {
+        size_t nBytes = sizeof(T);
+        size_t nResult = 0;
+        for(size_t c=0; c<nChannels; ++c)
+          for(size_t l=0; l<nBytes; ++l)
+            nResult += popcount_LUT8[(uchar)(*(x+c)>>l*8)];
+        return nResult;
+      }
+
+      //! computes the hamming distance between two (nChannels*N)-byte vectors using an 8-bit popcount LUT
+      template<size_t nChannels, typename T> static inline size_t hdist(const T* a, const T* b) {
+        T xor_array[nChannels];
+        for(size_t c=0; c<nChannels; ++c)
+          xor_array[c] = a[c]^b[c];
+        return popcount<nChannels>(xor_array);
+      }
+
+      //! computes the gradient magnitude distance between two (nChannels*N)-byte vectors using an 8-bit popcount LUT
+      template<size_t nChannels, typename T> static inline size_t gdist(const T* a, const T* b) {
+        return L1dist(popcount<nChannels>(a),popcount<nChannels>(b));
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/LBSP.cpp b/src/algorithms/LBSP/LBSP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b965112cde62d8e1990e8f8adad914eedbfc3fff
--- /dev/null
+++ b/src/algorithms/LBSP/LBSP.cpp
@@ -0,0 +1,329 @@
+#include "LBSP.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      LBSP::LBSP(size_t nThreshold)
+        : m_bOnlyUsingAbsThreshold(true)
+        , m_fRelThreshold(0) // unused
+        , m_nThreshold(nThreshold)
+        , m_oRefImage() {}
+
+      LBSP::LBSP(float fRelThreshold, size_t nThresholdOffset)
+        : m_bOnlyUsingAbsThreshold(false)
+        , m_fRelThreshold(fRelThreshold)
+        , m_nThreshold(nThresholdOffset)
+        , m_oRefImage() {
+        CV_Assert(m_fRelThreshold >= 0);
+      }
+
+      LBSP::~LBSP() {}
+
+      void LBSP::read(const cv::FileNode& /*fn*/) {
+        // ... = fn["..."];
+      }
+
+      void LBSP::write(cv::FileStorage& /*fs*/) const {
+        //fs << "..." << ...;
+      }
+
+      void LBSP::setReference(const cv::Mat& img) {
+        CV_DbgAssert(img.empty() || img.type() == CV_8UC1 || img.type() == CV_8UC3);
+        m_oRefImage = img;
+      }
+
+      int LBSP::descriptorSize() const {
+        return DESC_SIZE;
+      }
+
+      int LBSP::descriptorType() const {
+        return CV_16U;
+      }
+
+      bool LBSP::isUsingRelThreshold() const {
+        return !m_bOnlyUsingAbsThreshold;
+      }
+
+      float LBSP::getRelThreshold() const {
+        return m_fRelThreshold;
+      }
+
+      size_t LBSP::getAbsThreshold() const {
+        return m_nThreshold;
+      }
+
+      static inline void lbsp_computeImpl(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        size_t _t) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create((int)nKeyPoints, 1, CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>((int)k);
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create((int)nKeyPoints, 1, CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
+#include "LBSP_16bits_dbcross_3ch1t.i"
+          }
+        }
+      }
+
+      static inline void lbsp_computeImpl(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        float fThreshold,
+        size_t nThresholdOffset) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(fThreshold >= 0);
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create((int)nKeyPoints, 1, CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>((int)k);
+            const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create((int)nKeyPoints, 1, CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
+            const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
+#include "LBSP_16bits_dbcross_3ch3t.i"
+          }
+        }
+      }
+
+      static inline void lbsp_computeImpl2(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        size_t _t) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create(oInputImg.size(), CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>(_y, _x);
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create(oInputImg.size(), CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
+#include "LBSP_16bits_dbcross_3ch1t.i"
+          }
+        }
+      }
+
+      static inline void lbsp_computeImpl2(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        float fThreshold,
+        size_t nThresholdOffset) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(fThreshold >= 0);
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create(oInputImg.size(), CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>(_y, _x);
+            const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create(oInputImg.size(), CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
+            const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
+#include "LBSP_16bits_dbcross_3ch3t.i"
+          }
+        }
+      }
+
+      void LBSP::compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
+        CV_Assert(!oImage.empty());
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
+        cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
+        if (voKeypoints.empty()) {
+          oDescriptors.release();
+          return;
+        }
+        if (m_bOnlyUsingAbsThreshold)
+          lbsp_computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
+        else
+          lbsp_computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
+      }
+
+      void LBSP::compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const {
+        CV_Assert(voImageCollection.size() == vvoPointCollection.size());
+        voDescCollection.resize(voImageCollection.size());
+        for (size_t i = 0; i < voImageCollection.size(); i++)
+          compute2(voImageCollection[i], vvoPointCollection[i], voDescCollection[i]);
+      }
+
+      void LBSP::computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
+        CV_Assert(!oImage.empty());
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
+        cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
+        if (voKeypoints.empty()) {
+          oDescriptors.release();
+          return;
+        }
+        if (m_bOnlyUsingAbsThreshold)
+          lbsp_computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
+        else
+          lbsp_computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
+      }
+
+      void LBSP::reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput) {
+        CV_DbgAssert(!voKeypoints.empty());
+        CV_DbgAssert(!oDescriptors.empty() && oDescriptors.cols == 1);
+        CV_DbgAssert(oSize.width > 0 && oSize.height > 0);
+        CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(oDescriptors.type() == CV_16UC1 || oDescriptors.type() == CV_16UC3);
+        const size_t nChannels = (size_t)oDescriptors.channels();
+        const size_t nKeyPoints = voKeypoints.size();
+        if (nChannels == 1) {
+          oOutput.create(oSize, CV_16UC1);
+          oOutput = cv::Scalar_<ushort>(0);
+          for (size_t k = 0; k < nKeyPoints; ++k)
+            oOutput.at<ushort>(voKeypoints[k].pt) = oDescriptors.at<ushort>((int)k);
+        }
+        else { //nChannels==3
+          oOutput.create(oSize, CV_16UC3);
+          oOutput = cv::Scalar_<ushort>(0, 0, 0);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            ushort* output_ptr = (ushort*)(oOutput.data + oOutput.step.p[0] * (int)voKeypoints[k].pt.y);
+            const ushort* const desc_ptr = (ushort*)(oDescriptors.data + oDescriptors.step.p[0] * k);
+            const size_t idx = 3 * (int)voKeypoints[k].pt.x;
+            for (size_t n = 0; n < 3; ++n)
+              output_ptr[idx + n] = desc_ptr[n];
+          }
+        }
+      }
+
+      void LBSP::calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels) {
+        CV_DbgAssert(oDesc1.size() == oDesc2.size() && oDesc1.type() == oDesc2.type());
+        CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(oDesc1.type() == CV_16UC1 || oDesc1.type() == CV_16UC3);
+        CV_DbgAssert(CV_MAT_DEPTH(oDesc1.type()) == CV_16U);
+        CV_DbgAssert(DESC_SIZE * 8 <= UCHAR_MAX);
+        CV_DbgAssert(oDesc1.step.p[0] == oDesc2.step.p[0] && oDesc1.step.p[1] == oDesc2.step.p[1]);
+        const float fScaleFactor = (float)UCHAR_MAX / (DESC_SIZE * 8);
+        const size_t nChannels = CV_MAT_CN(oDesc1.type());
+        const size_t _step_row = oDesc1.step.p[0];
+        if (nChannels == 1) {
+          oOutput.create(oDesc1.size(), CV_8UC1);
+          oOutput = cv::Scalar(0);
+          for (int i = 0; i < oDesc1.rows; ++i) {
+            const size_t idx = _step_row*i;
+            const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
+            const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
+            for (int j = 0; j < oDesc1.cols; ++j)
+              oOutput.at<uchar>(i, j) = (uchar)(fScaleFactor*hdist(desc1_ptr[j], desc2_ptr[j]));
+          }
+        }
+        else { //nChannels==3
+          if (bForceMergeChannels)
+            oOutput.create(oDesc1.size(), CV_8UC1);
+          else
+            oOutput.create(oDesc1.size(), CV_8UC3);
+          oOutput = cv::Scalar::all(0);
+          for (int i = 0; i < oDesc1.rows; ++i) {
+            const size_t idx = _step_row*i;
+            const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
+            const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
+            uchar* output_ptr = oOutput.data + oOutput.step.p[0] * i;
+            for (int j = 0; j < oDesc1.cols; ++j) {
+              for (size_t n = 0; n < 3; ++n) {
+                const size_t idx2 = 3 * j + n;
+                if (bForceMergeChannels)
+                  output_ptr[j] += (uchar)((fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2])) / 3);
+                else
+                  output_ptr[idx2] = (uchar)(fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2]));
+              }
+            }
+          }
+        }
+      }
+
+      void LBSP::validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize) {
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImgSize, PATCH_SIZE / 2);
+      }
+
+      void LBSP::validateROI(cv::Mat& oROI) {
+        CV_Assert(!oROI.empty() && oROI.type() == CV_8UC1);
+        cv::Mat oROI_new(oROI.size(), CV_8UC1, cv::Scalar_<uchar>(0));
+        const size_t nBorderSize = PATCH_SIZE / 2;
+        const cv::Rect nROI_inner(nBorderSize, nBorderSize, oROI.cols - nBorderSize * 2, oROI.rows - nBorderSize * 2);
+        cv::Mat(oROI, nROI_inner).copyTo(cv::Mat(oROI_new, nROI_inner));
+        oROI = oROI_new;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/LBSP.h b/src/algorithms/LBSP/LBSP.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c8eb80256a0383f729ed8adfb5f909d7c809399
--- /dev/null
+++ b/src/algorithms/LBSP/LBSP.h
@@ -0,0 +1,128 @@
+#pragma once
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/features2d/features2d.hpp>
+
+#include "DistanceUtils.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*!
+        Local Binary Similarity Pattern (LBSP) feature extractor
+
+        Note 1: both grayscale and RGB/BGR images may be used with this extractor.
+        Note 2: using LBSP::compute2(...) is logically equivalent to using LBSP::compute(...) followed by LBSP::reshapeDesc(...).
+
+        For more details on the different parameters, see G.-A. Bilodeau et al, "Change Detection in Feature Space Using Local
+        Binary Similarity Patterns", in CRV 2013.
+
+        This algorithm is currently NOT thread-safe.
+      */
+      class LBSP : public cv::DescriptorExtractor {
+      public:
+        //! constructor 1, threshold = absolute intensity 'similarity' threshold used when computing comparisons
+        LBSP(size_t nThreshold);
+        //! constructor 2, threshold = relative intensity 'similarity' threshold used when computing comparisons
+        LBSP(float fRelThreshold, size_t nThresholdOffset = 0);
+        //! default destructor
+        virtual ~LBSP();
+        //! loads extractor params from the specified file node @@@@ not impl
+        virtual void read(const cv::FileNode&);
+        //! writes extractor params to the specified file storage @@@@ not impl
+        virtual void write(cv::FileStorage&) const;
+        //! sets the 'reference' image to be used for inter-frame comparisons (note: if no image is set or if the image is empty, the algorithm will default back to intra-frame comparisons)
+        virtual void setReference(const cv::Mat&);
+        //! returns the current descriptor size, in bytes
+        virtual int descriptorSize() const;
+        //! returns the current descriptor data type
+        virtual int descriptorType() const;
+        //! returns whether this extractor is using a relative threshold or not
+        virtual bool isUsingRelThreshold() const;
+        //! returns the current relative threshold used for comparisons (-1 = invalid/not used)
+        virtual float getRelThreshold() const;
+        //! returns the current absolute threshold used for comparisons (-1 = invalid/not used)
+        virtual size_t getAbsThreshold() const;
+
+        //! similar to DescriptorExtractor::compute(const cv::Mat& image, ...), but in this case, the descriptors matrix has the same shape as the input matrix (possibly slower, but the result can be displayed)
+        void compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
+        //! batch version of LBSP::compute2(const cv::Mat& image, ...), also similar to DescriptorExtractor::compute(const std::vector<cv::Mat>& imageCollection, ...)
+        void compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const;
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel version)
+        inline static void computeGrayscaleDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _t, ushort& _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC1);
+          CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_1ch.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
+        inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t* const _t, ushort* _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3);
+          CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_3ch3t.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
+        inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t _t, ushort* _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3);
+          CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_3ch1t.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel-RGB version)
+        inline static void computeSingleRGBDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _c, const size_t _t, ushort& _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3 && _c < 3);
+          CV_DbgAssert(LBSP::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP::PATCH_SIZE / 2 && _y >= (int)LBSP::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_s3ch.i"
+        }
+
+        //! utility function, used to reshape a descriptors matrix to its input image size via their keypoint locations
+        static void reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput);
+        //! utility function, used to illustrate the difference between two descriptor images
+        static void calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels = false);
+        //! utility function, used to filter out bad keypoints that would trigger out of bounds error because they're too close to the image border
+        static void validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize);
+        //! utility function, used to filter out bad pixels in a ROI that would trigger out of bounds error because they're too close to the image border
+        static void validateROI(cv::Mat& oROI);
+        //! utility, specifies the pixel size of the pattern used (width and height)
+        static const size_t PATCH_SIZE = 5;
+        //! utility, specifies the number of bytes per descriptor (should be the same as calling 'descriptorSize()')
+        static const size_t DESC_SIZE = 2;
+
+      protected:
+        //! classic 'compute' implementation, based on the regular DescriptorExtractor::computeImpl arguments & expected output
+        virtual void computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
+
+        const bool m_bOnlyUsingAbsThreshold;
+        const float m_fRelThreshold;
+        const size_t m_nThreshold;
+        cv::Mat m_oRefImage;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/LBSP_.cpp b/src/algorithms/LBSP/LBSP_.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0116dbbeec54cafafc3200ce65072216b72951f9
--- /dev/null
+++ b/src/algorithms/LBSP/LBSP_.cpp
@@ -0,0 +1,329 @@
+#include "LBSP_.h"
+
+//using namespace bgslibrary::algorithms::lbsp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      LBSP_::LBSP_(size_t nThreshold)
+        : m_bOnlyUsingAbsThreshold(true)
+        , m_fRelThreshold(0) // unused
+        , m_nThreshold(nThreshold)
+        , m_oRefImage() {}
+
+      LBSP_::LBSP_(float fRelThreshold, size_t nThresholdOffset)
+        : m_bOnlyUsingAbsThreshold(false)
+        , m_fRelThreshold(fRelThreshold)
+        , m_nThreshold(nThresholdOffset)
+        , m_oRefImage() {
+        CV_Assert(m_fRelThreshold >= 0);
+      }
+
+      LBSP_::~LBSP_() {}
+
+      void LBSP_::read(const cv::FileNode& /*fn*/) {
+        // ... = fn["..."];
+      }
+
+      void LBSP_::write(cv::FileStorage& /*fs*/) const {
+        //fs << "..." << ...;
+      }
+
+      void LBSP_::setReference(const cv::Mat& img) {
+        CV_DbgAssert(img.empty() || img.type() == CV_8UC1 || img.type() == CV_8UC3);
+        m_oRefImage = img;
+      }
+
+      int LBSP_::descriptorSize() const {
+        return DESC_SIZE;
+      }
+
+      int LBSP_::descriptorType() const {
+        return CV_16U;
+      }
+
+      bool LBSP_::isUsingRelThreshold() const {
+        return !m_bOnlyUsingAbsThreshold;
+      }
+
+      float LBSP_::getRelThreshold() const {
+        return m_fRelThreshold;
+      }
+
+      size_t LBSP_::getAbsThreshold() const {
+        return m_nThreshold;
+      }
+
+      static inline void LBSP__computeImpl(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        size_t _t) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create((int)nKeyPoints, 1, CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>((int)k);
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create((int)nKeyPoints, 1, CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
+#include "LBSP_16bits_dbcross_3ch1t.i"
+          }
+        }
+      }
+
+      static inline void LBSP__computeImpl(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        float fThreshold,
+        size_t nThresholdOffset) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(fThreshold >= 0);
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create((int)nKeyPoints, 1, CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>((int)k);
+            const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create((int)nKeyPoints, 1, CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * k));
+            const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
+#include "LBSP_16bits_dbcross_3ch3t.i"
+          }
+        }
+      }
+
+      static inline void LBSP__computeImpl2(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        size_t _t) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create(oInputImg.size(), CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>(_y, _x);
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create(oInputImg.size(), CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
+#include "LBSP_16bits_dbcross_3ch1t.i"
+          }
+        }
+      }
+
+      static inline void LBSP__computeImpl2(const cv::Mat& oInputImg,
+        const cv::Mat& oRefImg,
+        const std::vector<cv::KeyPoint>& voKeyPoints,
+        cv::Mat& oDesc,
+        float fThreshold,
+        size_t nThresholdOffset) {
+        CV_DbgAssert(oRefImg.empty() || (oRefImg.size == oInputImg.size && oRefImg.type() == oInputImg.type()));
+        CV_DbgAssert(oInputImg.type() == CV_8UC1 || oInputImg.type() == CV_8UC3);
+        CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(fThreshold >= 0);
+        const size_t nChannels = (size_t)oInputImg.channels();
+        const size_t _step_row = oInputImg.step.p[0];
+        const uchar* _data = oInputImg.data;
+        const uchar* _refdata = oRefImg.empty() ? oInputImg.data : oRefImg.data;
+        const size_t nKeyPoints = voKeyPoints.size();
+        if (nChannels == 1) {
+          oDesc.create(oInputImg.size(), CV_16UC1);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar _ref = _refdata[_step_row*(_y)+_x];
+            ushort& _res = oDesc.at<ushort>(_y, _x);
+            const size_t _t = (size_t)(_ref*fThreshold) + nThresholdOffset;
+#include "LBSP_16bits_dbcross_1ch.i"
+          }
+        }
+        else { //nChannels==3
+          oDesc.create(oInputImg.size(), CV_16UC3);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            const int _x = (int)voKeyPoints[k].pt.x;
+            const int _y = (int)voKeyPoints[k].pt.y;
+            const uchar* _ref = _refdata + _step_row*(_y)+3 * (_x);
+            ushort* _res = ((ushort*)(oDesc.data + oDesc.step.p[0] * _y + oDesc.step.p[1] * _x));
+            const size_t _t[3] = { (size_t)(_ref[0] * fThreshold) + nThresholdOffset,(size_t)(_ref[1] * fThreshold) + nThresholdOffset,(size_t)(_ref[2] * fThreshold) + nThresholdOffset };
+#include "LBSP_16bits_dbcross_3ch3t.i"
+          }
+        }
+      }
+
+      void LBSP_::compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
+        CV_Assert(!oImage.empty());
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
+        cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
+        if (voKeypoints.empty()) {
+          oDescriptors.release();
+          return;
+        }
+        if (m_bOnlyUsingAbsThreshold)
+          LBSP__computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
+        else
+          LBSP__computeImpl2(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
+      }
+
+      void LBSP_::compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const {
+        CV_Assert(voImageCollection.size() == vvoPointCollection.size());
+        voDescCollection.resize(voImageCollection.size());
+        for (size_t i = 0; i < voImageCollection.size(); i++)
+          compute2(voImageCollection[i], vvoPointCollection[i], voDescCollection[i]);
+      }
+
+      void LBSP_::computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const {
+        CV_Assert(!oImage.empty());
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImage.size(), PATCH_SIZE / 2);
+        cv::KeyPointsFilter::runByKeypointSize(voKeypoints, std::numeric_limits<float>::epsilon());
+        if (voKeypoints.empty()) {
+          oDescriptors.release();
+          return;
+        }
+        if (m_bOnlyUsingAbsThreshold)
+          LBSP__computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_nThreshold);
+        else
+          LBSP__computeImpl(oImage, m_oRefImage, voKeypoints, oDescriptors, m_fRelThreshold, m_nThreshold);
+      }
+
+      void LBSP_::reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput) {
+        CV_DbgAssert(!voKeypoints.empty());
+        CV_DbgAssert(!oDescriptors.empty() && oDescriptors.cols == 1);
+        CV_DbgAssert(oSize.width > 0 && oSize.height > 0);
+        CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(oDescriptors.type() == CV_16UC1 || oDescriptors.type() == CV_16UC3);
+        const size_t nChannels = (size_t)oDescriptors.channels();
+        const size_t nKeyPoints = voKeypoints.size();
+        if (nChannels == 1) {
+          oOutput.create(oSize, CV_16UC1);
+          oOutput = cv::Scalar_<ushort>(0);
+          for (size_t k = 0; k < nKeyPoints; ++k)
+            oOutput.at<ushort>(voKeypoints[k].pt) = oDescriptors.at<ushort>((int)k);
+        }
+        else { //nChannels==3
+          oOutput.create(oSize, CV_16UC3);
+          oOutput = cv::Scalar_<ushort>(0, 0, 0);
+          for (size_t k = 0; k < nKeyPoints; ++k) {
+            ushort* output_ptr = (ushort*)(oOutput.data + oOutput.step.p[0] * (int)voKeypoints[k].pt.y);
+            const ushort* const desc_ptr = (ushort*)(oDescriptors.data + oDescriptors.step.p[0] * k);
+            const size_t idx = 3 * (int)voKeypoints[k].pt.x;
+            for (size_t n = 0; n < 3; ++n)
+              output_ptr[idx + n] = desc_ptr[n];
+          }
+        }
+      }
+
+      void LBSP_::calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels) {
+        CV_DbgAssert(oDesc1.size() == oDesc2.size() && oDesc1.type() == oDesc2.type());
+        CV_DbgAssert(DESC_SIZE == 2); // @@@ also relies on a constant desc size
+        CV_DbgAssert(oDesc1.type() == CV_16UC1 || oDesc1.type() == CV_16UC3);
+        CV_DbgAssert(CV_MAT_DEPTH(oDesc1.type()) == CV_16U);
+        CV_DbgAssert(DESC_SIZE * 8 <= UCHAR_MAX);
+        CV_DbgAssert(oDesc1.step.p[0] == oDesc2.step.p[0] && oDesc1.step.p[1] == oDesc2.step.p[1]);
+        const float fScaleFactor = (float)UCHAR_MAX / (DESC_SIZE * 8);
+        const size_t nChannels = CV_MAT_CN(oDesc1.type());
+        const size_t _step_row = oDesc1.step.p[0];
+        if (nChannels == 1) {
+          oOutput.create(oDesc1.size(), CV_8UC1);
+          oOutput = cv::Scalar(0);
+          for (int i = 0; i < oDesc1.rows; ++i) {
+            const size_t idx = _step_row*i;
+            const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
+            const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
+            for (int j = 0; j < oDesc1.cols; ++j)
+              oOutput.at<uchar>(i, j) = (uchar)(fScaleFactor*hdist(desc1_ptr[j], desc2_ptr[j]));
+          }
+        }
+        else { //nChannels==3
+          if (bForceMergeChannels)
+            oOutput.create(oDesc1.size(), CV_8UC1);
+          else
+            oOutput.create(oDesc1.size(), CV_8UC3);
+          oOutput = cv::Scalar::all(0);
+          for (int i = 0; i < oDesc1.rows; ++i) {
+            const size_t idx = _step_row*i;
+            const ushort* const desc1_ptr = (ushort*)(oDesc1.data + idx);
+            const ushort* const desc2_ptr = (ushort*)(oDesc2.data + idx);
+            uchar* output_ptr = oOutput.data + oOutput.step.p[0] * i;
+            for (int j = 0; j < oDesc1.cols; ++j) {
+              for (size_t n = 0; n < 3; ++n) {
+                const size_t idx2 = 3 * j + n;
+                if (bForceMergeChannels)
+                  output_ptr[j] += (uchar)((fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2])) / 3);
+                else
+                  output_ptr[idx2] = (uchar)(fScaleFactor*hdist(desc1_ptr[idx2], desc2_ptr[idx2]));
+              }
+            }
+          }
+        }
+      }
+
+      void LBSP_::validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize) {
+        cv::KeyPointsFilter::runByImageBorder(voKeypoints, oImgSize, PATCH_SIZE / 2);
+      }
+
+      void LBSP_::validateROI(cv::Mat& oROI) {
+        CV_Assert(!oROI.empty() && oROI.type() == CV_8UC1);
+        cv::Mat oROI_new(oROI.size(), CV_8UC1, cv::Scalar_<uchar>(0));
+        const size_t nBorderSize = PATCH_SIZE / 2;
+        const cv::Rect nROI_inner(nBorderSize, nBorderSize, oROI.cols - nBorderSize * 2, oROI.rows - nBorderSize * 2);
+        cv::Mat(oROI, nROI_inner).copyTo(cv::Mat(oROI_new, nROI_inner));
+        oROI = oROI_new;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSP/LBSP_.h b/src/algorithms/LBSP/LBSP_.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b89a3736407413e726b228ba067c498edf37d5a
--- /dev/null
+++ b/src/algorithms/LBSP/LBSP_.h
@@ -0,0 +1,128 @@
+#pragma once
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/features2d/features2d.hpp>
+
+#include "DistanceUtils.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*!
+          Local Binary Similarity Pattern (LBSP) feature extractor
+
+          Note 1: both grayscale and RGB/BGR images may be used with this extractor.
+          Note 2: using LBSP_::compute2(...) is logically equivalent to using LBSP_::compute(...) followed by LBSP_::reshapeDesc(...).
+
+          For more details on the different parameters, see G.-A. Bilodeau et al, "Change Detection in Feature Space Using Local
+          Binary Similarity Patterns", in CRV 2013.
+
+          This algorithm is currently NOT thread-safe.
+      */
+      class LBSP_ : public cv::Feature2D {
+      public:
+        //! constructor 1, threshold = absolute intensity 'similarity' threshold used when computing comparisons
+        LBSP_(size_t nThreshold);
+        //! constructor 2, threshold = relative intensity 'similarity' threshold used when computing comparisons
+        LBSP_(float fRelThreshold, size_t nThresholdOffset = 0);
+        //! default destructor
+        virtual ~LBSP_();
+        //! loads extractor params from the specified file node @@@@ not impl
+        virtual void read(const cv::FileNode&);
+        //! writes extractor params to the specified file storage @@@@ not impl
+        virtual void write(cv::FileStorage&) const;
+        //! sets the 'reference' image to be used for inter-frame comparisons (note: if no image is set or if the image is empty, the algorithm will default back to intra-frame comparisons)
+        virtual void setReference(const cv::Mat&);
+        //! returns the current descriptor size, in bytes
+        virtual int descriptorSize() const;
+        //! returns the current descriptor data type
+        virtual int descriptorType() const;
+        //! returns whether this extractor is using a relative threshold or not
+        virtual bool isUsingRelThreshold() const;
+        //! returns the current relative threshold used for comparisons (-1 = invalid/not used)
+        virtual float getRelThreshold() const;
+        //! returns the current absolute threshold used for comparisons (-1 = invalid/not used)
+        virtual size_t getAbsThreshold() const;
+
+        //! similar to DescriptorExtractor::compute(const cv::Mat& image, ...), but in this case, the descriptors matrix has the same shape as the input matrix (possibly slower, but the result can be displayed)
+        void compute2(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
+        //! batch version of LBSP_::compute2(const cv::Mat& image, ...), also similar to DescriptorExtractor::compute(const std::vector<cv::Mat>& imageCollection, ...)
+        void compute2(const std::vector<cv::Mat>& voImageCollection, std::vector<std::vector<cv::KeyPoint> >& vvoPointCollection, std::vector<cv::Mat>& voDescCollection) const;
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel version)
+        inline static void computeGrayscaleDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _t, ushort& _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC1);
+          CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_1ch.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
+        inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t* const _t, ushort* _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3);
+          CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_3ch3t.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (3-channels version)
+        inline static void computeRGBDescriptor(const cv::Mat& oInputImg, const uchar* const _ref, const int _x, const int _y, const size_t _t, ushort* _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3);
+          CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_3ch1t.i"
+        }
+
+        //! utility function, shortcut/lightweight/direct single-point LBSP computation function for extra flexibility (1-channel-RGB version)
+        inline static void computeSingleRGBDescriptor(const cv::Mat& oInputImg, const uchar _ref, const int _x, const int _y, const size_t _c, const size_t _t, ushort& _res) {
+          CV_DbgAssert(!oInputImg.empty());
+          CV_DbgAssert(oInputImg.type() == CV_8UC3 && _c < 3);
+          CV_DbgAssert(LBSP_::DESC_SIZE == 2); // @@@ also relies on a constant desc size
+          CV_DbgAssert(_x >= (int)LBSP_::PATCH_SIZE / 2 && _y >= (int)LBSP_::PATCH_SIZE / 2);
+          CV_DbgAssert(_x < oInputImg.cols - (int)LBSP_::PATCH_SIZE / 2 && _y < oInputImg.rows - (int)LBSP_::PATCH_SIZE / 2);
+          const size_t _step_row = oInputImg.step.p[0];
+          const uchar* const _data = oInputImg.data;
+      #include "LBSP_16bits_dbcross_s3ch.i"
+        }
+
+        //! utility function, used to reshape a descriptors matrix to its input image size via their keypoint locations
+        static void reshapeDesc(cv::Size oSize, const std::vector<cv::KeyPoint>& voKeypoints, const cv::Mat& oDescriptors, cv::Mat& oOutput);
+        //! utility function, used to illustrate the difference between two descriptor images
+        static void calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels = false);
+        //! utility function, used to filter out bad keypoints that would trigger out of bounds error because they're too close to the image border
+        static void validateKeyPoints(std::vector<cv::KeyPoint>& voKeypoints, cv::Size oImgSize);
+        //! utility function, used to filter out bad pixels in a ROI that would trigger out of bounds error because they're too close to the image border
+        static void validateROI(cv::Mat& oROI);
+        //! utility, specifies the pixel size of the pattern used (width and height)
+        static const size_t PATCH_SIZE = 5;
+        //! utility, specifies the number of bytes per descriptor (should be the same as calling 'descriptorSize()')
+        static const size_t DESC_SIZE = 2;
+
+      protected:
+        //! classic 'compute' implementation, based on the regular DescriptorExtractor::computeImpl arguments & expected output
+        virtual void computeImpl(const cv::Mat& oImage, std::vector<cv::KeyPoint>& voKeypoints, cv::Mat& oDescriptors) const;
+
+        const bool m_bOnlyUsingAbsThreshold;
+        const float m_fRelThreshold;
+        const size_t m_nThreshold;
+        cv::Mat m_oRefImage;
+      };
+    }
+  }
+}
diff --git a/package_bgs/LBSP/LBSP_16bits_dbcross_1ch.i b/src/algorithms/LBSP/LBSP_16bits_dbcross_1ch.i
similarity index 100%
rename from package_bgs/LBSP/LBSP_16bits_dbcross_1ch.i
rename to src/algorithms/LBSP/LBSP_16bits_dbcross_1ch.i
diff --git a/package_bgs/LBSP/LBSP_16bits_dbcross_3ch1t.i b/src/algorithms/LBSP/LBSP_16bits_dbcross_3ch1t.i
similarity index 100%
rename from package_bgs/LBSP/LBSP_16bits_dbcross_3ch1t.i
rename to src/algorithms/LBSP/LBSP_16bits_dbcross_3ch1t.i
diff --git a/package_bgs/LBSP/LBSP_16bits_dbcross_3ch3t.i b/src/algorithms/LBSP/LBSP_16bits_dbcross_3ch3t.i
similarity index 100%
rename from package_bgs/LBSP/LBSP_16bits_dbcross_3ch3t.i
rename to src/algorithms/LBSP/LBSP_16bits_dbcross_3ch3t.i
diff --git a/package_bgs/LBSP/LBSP_16bits_dbcross_s3ch.i b/src/algorithms/LBSP/LBSP_16bits_dbcross_s3ch.i
similarity index 100%
rename from package_bgs/LBSP/LBSP_16bits_dbcross_s3ch.i
rename to src/algorithms/LBSP/LBSP_16bits_dbcross_s3ch.i
diff --git a/src/algorithms/LBSP/RandUtils.h b/src/algorithms/LBSP/RandUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..570d333f30c10bef209d0cb665af143e32752d1f
--- /dev/null
+++ b/src/algorithms/LBSP/RandUtils.h
@@ -0,0 +1,105 @@
+#pragma once
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lbsp
+    {
+      /*// gaussian 3x3 pattern, based on 'floor(fspecial('gaussian', 3, 1)*256)'
+      static const int s_nSamplesInitPatternWidth = 3;
+      static const int s_nSamplesInitPatternHeight = 3;
+      static const int s_nSamplesInitPatternTot = 256;
+      static const int s_anSamplesInitPattern[s_nSamplesInitPatternHeight][s_nSamplesInitPatternWidth] = {
+          {19,    32,    19,},
+          {32,    52,    32,},
+          {19,    32,    19,},
+      };*/
+
+      // gaussian 7x7 pattern, based on 'floor(fspecial('gaussian',7,2)*512)'
+      static const int s_nSamplesInitPatternWidth = 7;
+      static const int s_nSamplesInitPatternHeight = 7;
+      static const int s_nSamplesInitPatternTot = 512;
+      static const int s_anSamplesInitPattern[s_nSamplesInitPatternHeight][s_nSamplesInitPatternWidth] = {
+        {2,     4,     6,     7,     6,     4,     2,},
+        {4,     8,    12,    14,    12,     8,     4,},
+        {6,    12,    21,    25,    21,    12,     6,},
+        {7,    14,    25,    28,    25,    14,     7,},
+        {6,    12,    21,    25,    21,    12,     6,},
+        {4,     8,    12,    14,    12,     8,     4,},
+        {2,     4,     6,     7,     6,     4,     2,},
+      };
+
+      //! returns a random init/sampling position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
+      static inline void getRandSamplePosition(int& x_sample, int& y_sample, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
+        int r = 1+rand()%s_nSamplesInitPatternTot;
+        for(x_sample=0; x_sample<s_nSamplesInitPatternWidth; ++x_sample) {
+          for(y_sample=0; y_sample<s_nSamplesInitPatternHeight; ++y_sample) {
+            r -= s_anSamplesInitPattern[y_sample][x_sample];
+            if(r<=0)
+              goto stop;
+          }
+        }
+      stop:
+        x_sample += x_orig-s_nSamplesInitPatternWidth/2;
+        y_sample += y_orig-s_nSamplesInitPatternHeight/2;
+        if(x_sample<border)
+          x_sample = border;
+        else if(x_sample>=imgsize.width-border)
+          x_sample = imgsize.width-border-1;
+        if(y_sample<border)
+          y_sample = border;
+        else if(y_sample>=imgsize.height-border)
+          y_sample = imgsize.height-border-1;
+      }
+
+      // simple 8-connected (3x3) neighbors pattern
+      static const int s_anNeighborPatternSize_3x3 = 8;
+      static const int s_anNeighborPattern_3x3[8][2] = {
+        {-1, 1},  { 0, 1},  { 1, 1},
+        {-1, 0},            { 1, 0},
+        {-1,-1},  { 0,-1},  { 1,-1},
+      };
+
+      //! returns a random neighbor position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
+      static inline void getRandNeighborPosition_3x3(int& x_neighbor, int& y_neighbor, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
+        int r = rand()%s_anNeighborPatternSize_3x3;
+        x_neighbor = x_orig+s_anNeighborPattern_3x3[r][0];
+        y_neighbor = y_orig+s_anNeighborPattern_3x3[r][1];
+        if(x_neighbor<border)
+          x_neighbor = border;
+        else if(x_neighbor>=imgsize.width-border)
+          x_neighbor = imgsize.width-border-1;
+        if(y_neighbor<border)
+          y_neighbor = border;
+        else if(y_neighbor>=imgsize.height-border)
+          y_neighbor = imgsize.height-border-1;
+      }
+
+      // 5x5 neighbors pattern
+      static const int s_anNeighborPatternSize_5x5 = 24;
+      static const int s_anNeighborPattern_5x5[24][2] = {
+        {-2, 2},  {-1, 2},  { 0, 2},  { 1, 2},  { 2, 2},
+        {-2, 1},  {-1, 1},  { 0, 1},  { 1, 1},  { 2, 1},
+        {-2, 0},  {-1, 0},            { 1, 0},  { 2, 0},
+        {-2,-1},  {-1,-1},  { 0,-1},  { 1,-1},  { 2,-1},
+        {-2,-2},  {-1,-2},  { 0,-2},  { 1,-2},  { 2,-2},
+      };
+
+      //! returns a random neighbor position for the specified pixel position; also guards against out-of-bounds values via image/border size check.
+      static inline void getRandNeighborPosition_5x5(int& x_neighbor, int& y_neighbor, const int x_orig, const int y_orig, const int border, const cv::Size& imgsize) {
+        int r = rand()%s_anNeighborPatternSize_5x5;
+        x_neighbor = x_orig+s_anNeighborPattern_5x5[r][0];
+        y_neighbor = y_orig+s_anNeighborPattern_5x5[r][1];
+        if(x_neighbor<border)
+          x_neighbor = border;
+        else if(x_neighbor>=imgsize.width-border)
+          x_neighbor = imgsize.width-border-1;
+        if(y_neighbor<border)
+          y_neighbor = border;
+        else if(y_neighbor>=imgsize.height-border)
+          y_neighbor = imgsize.height-border-1;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/LBSimpleGaussian.cpp b/src/algorithms/LBSimpleGaussian.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab7e776acd98264aa29f375413bf6298ca490ef9
--- /dev/null
+++ b/src/algorithms/LBSimpleGaussian.cpp
@@ -0,0 +1,77 @@
+#include "LBSimpleGaussian.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+LBSimpleGaussian::LBSimpleGaussian() :
+  IBGS(quote(LBSimpleGaussian)),
+  sensitivity(66), noiseVariance(162), learningRate(18)
+{
+  debug_construction(LBSimpleGaussian);
+  initLoadSaveConfig(algorithmName);
+}
+
+LBSimpleGaussian::~LBSimpleGaussian() {
+  debug_destruction(LBSimpleGaussian);
+  delete m_pBGModel;
+}
+
+void LBSimpleGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage *frame = &_frame;
+#else
+  IplImage *frame = new IplImage(img_input);
+#endif
+
+  if (firstTime) {
+    int w = cvGetSize(frame).width;
+    int h = cvGetSize(frame).height;
+
+    m_pBGModel = new lb::BGModelGauss(w, h);
+    m_pBGModel->InitModel(frame);
+  }
+
+  m_pBGModel->setBGModelParameter(0, sensitivity);
+  m_pBGModel->setBGModelParameter(1, noiseVariance);
+  m_pBGModel->setBGModelParameter(2, learningRate);
+
+  m_pBGModel->UpdateModel(frame);
+
+  img_foreground = cv::cvarrToMat(m_pBGModel->GetFG());
+  img_background = cv::cvarrToMat(m_pBGModel->GetBG());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+
+  firstTime = false;
+}
+
+void LBSimpleGaussian::save_config(cv::FileStorage &fs) {
+  fs << "sensitivity" << sensitivity;
+  fs << "noiseVariance" << noiseVariance;
+  fs << "learningRate" << learningRate;
+  fs << "showOutput" << showOutput;
+}
+
+void LBSimpleGaussian::load_config(cv::FileStorage &fs) {
+  fs["sensitivity"] >> sensitivity;
+  fs["noiseVariance"] >> noiseVariance;
+  fs["learningRate"] >> learningRate;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/LBSimpleGaussian.h b/src/algorithms/LBSimpleGaussian.h
new file mode 100644
index 0000000000000000000000000000000000000000..b41d54d7be4287d30464105ccee56bfc7b95ad45
--- /dev/null
+++ b/src/algorithms/LBSimpleGaussian.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "lb/BGModelGauss.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LBSimpleGaussian : public IBGS
+    {
+    private:
+      lb::BGModel* m_pBGModel;
+      int sensitivity;
+      int noiseVariance;
+      int learningRate;
+
+    public:
+      LBSimpleGaussian();
+      ~LBSimpleGaussian();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LBSimpleGaussian);
+  }
+}
+
+#endif
diff --git a/src/algorithms/LOBSTER.cpp b/src/algorithms/LOBSTER.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2a03c1086caf687a391ccd609a500324502e7c7a
--- /dev/null
+++ b/src/algorithms/LOBSTER.cpp
@@ -0,0 +1,70 @@
+#include "LOBSTER.h"
+
+using namespace bgslibrary::algorithms;
+
+LOBSTER::LOBSTER() :
+  IBGS(quote(LOBSTER)),
+  pLOBSTER(nullptr),
+  fRelLBSPThreshold(lbsp::BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
+  nLBSPThresholdOffset(lbsp::BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD),
+  nDescDistThreshold(lbsp::BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD),
+  nColorDistThreshold(lbsp::BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD),
+  nBGSamples(lbsp::BGSLOBSTER_DEFAULT_NB_BG_SAMPLES),
+  nRequiredBGSamples(lbsp::BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES)
+{
+  debug_construction(LOBSTER);
+  initLoadSaveConfig(algorithmName);
+}
+
+LOBSTER::~LOBSTER() {
+  debug_destruction(LOBSTER);
+  if (pLOBSTER)
+    delete pLOBSTER;
+}
+
+void LOBSTER::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    pLOBSTER = new lbsp::BackgroundSubtractorLOBSTER(
+      fRelLBSPThreshold, nLBSPThresholdOffset, nDescDistThreshold,
+      nColorDistThreshold, nBGSamples, nRequiredBGSamples);
+
+    pLOBSTER->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
+    firstTime = false;
+  }
+
+  pLOBSTER->apply(img_input, img_foreground);
+  pLOBSTER->getBackgroundImage(img_background);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+}
+
+void LOBSTER::save_config(cv::FileStorage &fs) {
+  fs << "fRelLBSPThreshold" << fRelLBSPThreshold;
+  fs << "nLBSPThresholdOffset" << nLBSPThresholdOffset;
+  fs << "nDescDistThreshold" << nDescDistThreshold;
+  fs << "nColorDistThreshold" << nColorDistThreshold;
+  fs << "nBGSamples" << nBGSamples;
+  fs << "nRequiredBGSamples" << nRequiredBGSamples;
+  fs << "showOutput" << showOutput;
+}
+
+void LOBSTER::load_config(cv::FileStorage &fs) {
+  fs["fRelLBSPThreshold"] >> fRelLBSPThreshold;
+  fs["nLBSPThresholdOffset"] >> nLBSPThresholdOffset;
+  fs["nDescDistThreshold"] >> nDescDistThreshold;
+  fs["nColorDistThreshold"] >> nColorDistThreshold;
+  fs["nBGSamples"] >> nBGSamples;
+  fs["nRequiredBGSamples"] >> nRequiredBGSamples;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/LOBSTER.h b/src/algorithms/LOBSTER.h
new file mode 100644
index 0000000000000000000000000000000000000000..505fd779de190b12ea6554c4386ac0ead960ff40
--- /dev/null
+++ b/src/algorithms/LOBSTER.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+
+#include "LBSP/BackgroundSubtractorLOBSTER.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class LOBSTER : public IBGS
+    {
+    private:
+      lbsp::BackgroundSubtractorLOBSTER* pLOBSTER;
+
+      float fRelLBSPThreshold;
+      int nLBSPThresholdOffset;
+      int nDescDistThreshold;
+      int nColorDistThreshold;
+      int nBGSamples;
+      int nRequiredBGSamples;
+
+    public:
+      LOBSTER();
+      ~LOBSTER();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(LOBSTER);
+  }
+}
diff --git a/src/algorithms/MixtureOfGaussianV1.cpp b/src/algorithms/MixtureOfGaussianV1.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2cb1bb128dcd17bb24994451feebd2aaadce095
--- /dev/null
+++ b/src/algorithms/MixtureOfGaussianV1.cpp
@@ -0,0 +1,74 @@
+#include "MixtureOfGaussianV1.h"
+
+#if CV_MAJOR_VERSION == 2
+
+using namespace bgslibrary::algorithms;
+
+MixtureOfGaussianV1::MixtureOfGaussianV1() :
+  IBGS(quote(MixtureOfGaussianV1)),
+  alpha(0.05), enableThreshold(true), threshold(15)
+{
+  debug_construction(MixtureOfGaussianV1);
+  initLoadSaveConfig(algorithmName);
+}
+
+MixtureOfGaussianV1::~MixtureOfGaussianV1() {
+  debug_destruction(MixtureOfGaussianV1);
+}
+
+void MixtureOfGaussianV1::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  //------------------------------------------------------------------
+  // BackgroundSubtractorMOG
+  // http://opencv.itseez.com/modules/video/doc/motion_analysis_and_object_tracking.html#backgroundsubtractormog
+  //
+  // Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm.
+  //
+  // The class implements the algorithm described in:
+  //   P. KadewTraKuPong and R. Bowden,
+  //   An improved adaptive background mixture model for real-time tracking with shadow detection,
+  //   Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001
+  //------------------------------------------------------------------
+
+  mog(img_input, img_foreground, alpha);
+  mog.getBackgroundImage(img_background);
+
+  if (enableThreshold)
+    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
+
+  if (img_foreground.empty())
+    img_foreground = cv::Mat::zeros(img_input.size(), img_input.type());
+
+  if (img_background.empty())
+    img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void MixtureOfGaussianV1::save_config(cv::FileStorage &fs) {
+  fs << "alpha" << alpha;
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void MixtureOfGaussianV1::load_config(cv::FileStorage &fs) {
+  fs["alpha"] >> alpha;
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/MixtureOfGaussianV1.h b/src/algorithms/MixtureOfGaussianV1.h
new file mode 100644
index 0000000000000000000000000000000000000000..42c59774757add3871d2f2d1dad2d816e20437a5
--- /dev/null
+++ b/src/algorithms/MixtureOfGaussianV1.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION == 2
+
+#include <iostream>
+#include <opencv2/opencv.hpp>
+#include <opencv2/video/background_segm.hpp>
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class MixtureOfGaussianV1 : public IBGS
+    {
+    private:
+      cv::BackgroundSubtractorMOG mog;
+      double alpha;
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      MixtureOfGaussianV1();
+      ~MixtureOfGaussianV1();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(MixtureOfGaussianV1);
+  }
+}
+
+#endif
diff --git a/package_bgs/MixtureOfGaussianV2.cpp b/src/algorithms/MixtureOfGaussianV2.cpp
similarity index 54%
rename from package_bgs/MixtureOfGaussianV2.cpp
rename to src/algorithms/MixtureOfGaussianV2.cpp
index 085b1a9503f9297a9d553b4991ff29443aead97f..50244fb1f04841c4fc2db430acd505cff0e64cdf 100644
--- a/package_bgs/MixtureOfGaussianV2.cpp
+++ b/src/algorithms/MixtureOfGaussianV2.cpp
@@ -1,33 +1,17 @@
-/*
-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 "MixtureOfGaussianV2.h"
 
 using namespace bgslibrary::algorithms;
 
 MixtureOfGaussianV2::MixtureOfGaussianV2() :
+  IBGS(quote(MixtureOfGaussianV2)),
   alpha(0.05), enableThreshold(true), threshold(15)
 {
-  std::cout << "MixtureOfGaussianV2()" << std::endl;
-  setup("./config/MixtureOfGaussianV2.xml");
+  debug_construction(MixtureOfGaussianV2);
+  initLoadSaveConfig(algorithmName);
 }
 
-MixtureOfGaussianV2::~MixtureOfGaussianV2()
-{
-  std::cout << "~MixtureOfGaussianV2()" << std::endl;
+MixtureOfGaussianV2::~MixtureOfGaussianV2() {
+  debug_destruction(MixtureOfGaussianV2);
 }
 
 void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
@@ -35,7 +19,7 @@ void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output,
   init(img_input, img_output, img_bgmodel);
 
   if (firstTime) {
-#if CV_MAJOR_VERSION == 3
+#if CV_MAJOR_VERSION >= 3
     mog = cv::createBackgroundSubtractorMOG2();
 #endif
   }
@@ -60,7 +44,7 @@ void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output,
 #if CV_MAJOR_VERSION == 2
   mog(img_input, img_foreground, alpha);
   mog.getBackgroundImage(img_background);
-#elif CV_MAJOR_VERSION == 3
+#elif CV_MAJOR_VERSION >= 3
   mog->apply(img_input, img_foreground, alpha);
   mog->getBackgroundImage(img_background);
 #endif
@@ -69,10 +53,9 @@ void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output,
     cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
 
 #ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("GMM FG (Zivkovic&Heijden)", img_foreground);
-    cv::imshow("GMM BG (Zivkovic&Heijden)", img_background);
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
   }
 #endif
 
@@ -82,26 +65,16 @@ void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output,
   firstTime = false;
 }
 
-void MixtureOfGaussianV2::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void MixtureOfGaussianV2::save_config(cv::FileStorage &fs) {
+  fs << "alpha" << alpha;
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
 }
 
-void MixtureOfGaussianV2::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.05);
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void MixtureOfGaussianV2::load_config(cv::FileStorage &fs) {
+  fs["alpha"] >> alpha;
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
 }
diff --git a/src/algorithms/MixtureOfGaussianV2.h b/src/algorithms/MixtureOfGaussianV2.h
new file mode 100644
index 0000000000000000000000000000000000000000..5bd0d445c3d1da8b07367d745e546bf50a260130
--- /dev/null
+++ b/src/algorithms/MixtureOfGaussianV2.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <iostream>
+#include <opencv2/opencv.hpp>
+#include <opencv2/video/background_segm.hpp>
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class MixtureOfGaussianV2 : public IBGS
+    {
+    private:
+#if CV_MAJOR_VERSION == 2
+      cv::BackgroundSubtractorMOG2 mog;
+#elif CV_MAJOR_VERSION >= 3
+      cv::Ptr<cv::BackgroundSubtractorMOG2> mog;
+#endif
+      double alpha;
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      MixtureOfGaussianV2();
+      ~MixtureOfGaussianV2();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(MixtureOfGaussianV2);
+  }
+}
diff --git a/package_bgs/MultiCue.cpp b/src/algorithms/MultiCue.cpp
similarity index 96%
rename from package_bgs/MultiCue.cpp
rename to src/algorithms/MultiCue.cpp
index 7717842975210f5ff32eeb876f615737d4c024bd..4d0d065b7268a0c7e9beda7107b789243e73eedb 100644
--- a/package_bgs/MultiCue.cpp
+++ b/src/algorithms/MultiCue.cpp
@@ -1,33 +1,29 @@
-/*
-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/>.
-*/
-//------------------------------------------------------------------------------------------------------------------------------------//
-//									A BGS Method Using Multiple Color, Texture, Appearance Cues in the Scene						  //
-//																																	  //
-//  - Paper: A New Framework for Background Subtraction Using Multiple Cues (ACCV2012)												  //
-//  - Code by: SeungJon Noh																											  //
-//------------------------------------------------------------------------------------------------------------------------------------//
-//#include "StdAfx.h"
 #include "MultiCue.h"
 
-using namespace bgslibrary::algorithms::libMultiCue;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::multiCue;
 using namespace bgslibrary::algorithms;
 
-MultiCue::MultiCue()
+#define MIN3(x,y,z)  ((y) <= (z) ? ((x) <= (y) ? (x) : (y)) : ((x) <= (z) ? (x) : (z)))
+#define MAX3(x,y,z)  ((y) >= (z) ? ((x) >= (y) ? (x) : (y)) : ((x) >= (z) ? (x) : (z)))
+
+#ifndef PI
+#define PI 3.141592653589793f
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+MultiCue::MultiCue() :
+  IBGS(quote(MultiCue))
 {
+  debug_construction(MultiCue);
   //----------------------------------
   //	User adjustable parameters
   //----------------------------------
@@ -62,14 +58,12 @@ MultiCue::MultiCue()
   g_bModelMemAllocated = FALSE;									//To handle memory..
   g_bNonModelMemAllocated = FALSE;								//To handle memory..
 
-  std::cout << "MultiCue()" << std::endl;
-  setup("./config/MultiCue.xml");
+  initLoadSaveConfig(algorithmName);
 }
 
-MultiCue::~MultiCue(void)
-{
+MultiCue::~MultiCue() {
+  debug_destruction(MultiCue);
   Destroy();
-  std::cout << "~MultiCue()" << std::endl;
 }
 
 //-----------------------------------------------------------------------------------------------------------------------------------------//
@@ -80,18 +74,22 @@ void MultiCue::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &i
   init(img_input, img_output, img_bgmodel);
 
   //--STep1: Background Modeling--//
-  //IplImage* frame = &IplImage(img_input);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage* frame = &_frame;
+#else
   IplImage* frame = new IplImage(img_input);
+#endif
+
   IplImage* result_image = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
   cvSetZero(result_image);
-  if (g_iFrameCount <= g_iTrainingPeriod)
-  {
+  if (g_iFrameCount <= g_iTrainingPeriod) {
     BackgroundModeling_Par(frame);
     g_iFrameCount++;
   }
   //--Step2: Background Subtraction--//
-  else
-  {
+  else {
     g_bForegroundMapEnable = FALSE;
 
     ForegroundExtraction(frame);
@@ -108,7 +106,7 @@ void MultiCue::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &i
 
 #ifndef MEX_COMPILE_FLAG
   if (showOutput)
-    cv::imshow("MultiCue FG", img_foreground);
+    cv::imshow(algorithmName + "_FG", img_foreground);
 #endif
 
   img_foreground.copyTo(img_output);
@@ -117,22 +115,38 @@ void MultiCue::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &i
   firstTime = false;
 }
 
-void MultiCue::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void MultiCue::save_config(cv::FileStorage &fs) {
+  fs << "g_fLearningRate" << g_fLearningRate;
+  fs << "g_iAbsortionPeriod" << g_iAbsortionPeriod;
+  fs << "g_iC_ModelThreshold" << g_iC_ModelThreshold;
+  fs << "g_iT_ModelThreshold" << g_iT_ModelThreshold;
+  fs << "g_iBackClearPeriod" << g_iBackClearPeriod;
+  fs << "g_iCacheClearPeriod" << g_iCacheClearPeriod;
+  fs << "g_nNeighborNum" << g_nNeighborNum;
+  fs << "g_nRadius" << g_nRadius;
+  fs << "g_nTextureTrainVolRange" << g_nTextureTrainVolRange;
+  fs << "g_bAbsorptionEnable" << g_bAbsorptionEnable;
+  fs << "g_iTrainingPeriod" << g_iTrainingPeriod;
+  fs << "g_iRWidth" << g_iRWidth;
+  fs << "g_iRHeight" << g_iRHeight;
+  fs << "showOutput" << showOutput;
 }
 
-void MultiCue::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void MultiCue::load_config(cv::FileStorage &fs) {
+  fs["g_fLearningRate"] >> g_fLearningRate;
+  fs["g_iAbsortionPeriod"] >> g_iAbsortionPeriod;
+  fs["g_iC_ModelThreshold"] >> g_iC_ModelThreshold;
+  fs["g_iT_ModelThreshold"] >> g_iT_ModelThreshold;
+  fs["g_iBackClearPeriod"] >> g_iBackClearPeriod;
+  fs["g_iCacheClearPeriod"] >> g_iCacheClearPeriod;
+  fs["g_nNeighborNum"] >> g_nNeighborNum;
+  fs["g_nRadius"] >> g_nRadius;
+  fs["g_nTextureTrainVolRange"] >> g_nTextureTrainVolRange;
+  fs["g_bAbsorptionEnable"] >> g_bAbsorptionEnable;
+  fs["g_iTrainingPeriod"] >> g_iTrainingPeriod;
+  fs["g_iRWidth"] >> g_iRWidth;
+  fs["g_iRHeight"] >> g_iRHeight;
+  fs["showOutput"] >> showOutput;
 }
 
 //-----------------------------------------------------------------------------------------------------------------------------------------//
@@ -212,7 +226,7 @@ void MultiCue::Destroy()
 {
   if (g_bModelMemAllocated == FALSE && g_bNonModelMemAllocated == FALSE) return;
 
-  short nNeighborNum = g_nNeighborNum;
+  //short nNeighborNum = g_nNeighborNum;
 
   if (g_bModelMemAllocated == TRUE) {
     T_ReleaseTextureModelRelatedMemory();
@@ -367,7 +381,7 @@ void MultiCue::PostProcessing(IplImage* frame) {
 //														the background-model update function			                                   //
 //-----------------------------------------------------------------------------------------------------------------------------------------//
 void MultiCue::UpdateModel_Par() {
-  short nNeighborNum = g_nNeighborNum;
+  //short nNeighborNum = g_nNeighborNum;
 
   //Step1: update map construction
   for (int i = 0; i < g_iRHeight; i++) {
@@ -529,8 +543,14 @@ void MultiCue::GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame) {
     cv::GaussianBlur(temp_img, temp_img, cv::Size(7, 7), dSigma);
 
     //Store results into aFilteredFrame[][][]
-    //IplImage* img = &IplImage(temp_img);
+    
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+    IplImage _img = cvIplImage(temp_img);
+    IplImage* img = &_img;
+#else
     IplImage* img = new IplImage(temp_img);
+#endif
+
     //int iWidthStep = img->widthStep;
 
     for (int i = 0; i < g_iRHeight; i++) {
@@ -825,7 +845,7 @@ void MultiCue::SetBoundingBox(int iLabelCount, int** aLabelTable) {
   for (int i = 1; i < g_iRHeight; i++) {
     for (int j = 1; j < g_iRWidth; j++) {
 
-      if ((aLabelTable[i][j] == 0)) continue;
+      if (aLabelTable[i][j] == 0) continue;
 
       iBoundBoxIndex = aLabelTable[i][j] - 1;
 
@@ -1108,11 +1128,11 @@ double MultiCue::CalculateHausdorffDist(IplImage* input_image, IplImage* model_i
   sort(vTempDist.begin(), vTempDist.end()); //in ascending order
 
   double dQuantileVal = 0.9, dForwardDistance;
-  int iDistIndex = (int)(dQuantileVal*vTempDist.size()); if (iDistIndex == vTempDist.size()) iDistIndex -= 1;
+  int iDistIndex = (int)(dQuantileVal*vTempDist.size());
+  if (iDistIndex == vTempDist.size()) iDistIndex -= 1;
 
   dForwardDistance = sqrt(vTempDist[iDistIndex]);
   return dForwardDistance;
-
 }
 
 
@@ -2067,3 +2087,5 @@ void MultiCue::C_Absorption(int iAbsorbCnt, point pos, short** aContinuCnt, shor
   pCache->m_Codewords = pTempCache;
   pCache->m_iNumEntries = k;
 }
+
+#endif
diff --git a/package_bgs/MultiCue.h b/src/algorithms/MultiCue.h
similarity index 89%
rename from package_bgs/MultiCue.h
rename to src/algorithms/MultiCue.h
index 44524e0ab11c7b192cb4a26e0f5875f58749fa9a..ca75a50eff404f33b9d4ae924114e47149b84f24 100644
--- a/package_bgs/MultiCue.h
+++ b/src/algorithms/MultiCue.h
@@ -1,37 +1,7 @@
-/*
-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 MIN3(x,y,z)  ((y) <= (z) ? ((x) <= (y) ? (x) : (y)) : ((x) <= (z) ? (x) : (z)))
-#define MAX3(x,y,z)  ((y) >= (z) ? ((x) >= (y) ? (x) : (y)) : ((x) >= (z) ? (x) : (z)))
-
-#ifndef PI
-#define PI 3.14159
-#endif
-
-typedef int BOOL;
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
 
 #if !defined(__APPLE__)
 #include <malloc.h>
@@ -49,8 +19,10 @@ namespace bgslibrary
 {
   namespace algorithms
   {
-    namespace libMultiCue
+    namespace multiCue
     {
+      typedef int BOOL;
+
       struct point {
         short m_nX;
         short m_nY;
@@ -119,19 +91,23 @@ namespace bgslibrary
 {
   namespace algorithms
   {
-    using namespace bgslibrary::algorithms::libMultiCue;
+    //using namespace bgslibrary::algorithms::multiCue;
 
     class MultiCue : public IBGS
     {
     private:
-      void saveConfig();
-      void loadConfig();
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
 
     public:
+      typedef bgslibrary::algorithms::multiCue::point point;
+      typedef bgslibrary::algorithms::multiCue::TextureModel TextureModel;
+      typedef bgslibrary::algorithms::multiCue::BoundingBoxInfo BoundingBoxInfo;
+      typedef bgslibrary::algorithms::multiCue::ColorModel ColorModel;
+      typedef bgslibrary::algorithms::multiCue::BOOL BOOL;
+
       MultiCue();
       ~MultiCue();
-
-    public:
       //----------------------------------------------------
       //		APIs and User-Adjustable Parameters
       //----------------------------------------------------
@@ -149,7 +125,6 @@ namespace bgslibrary
       short g_nTextureTrainVolRange;								//the codebook size factor for texture models.		(The parameter k in the paper)
       short g_nColorTrainVolRange;								//the codebook size factor for color models.		(The parameter eta_1 in the paper)
 
-    public:
       //----------------------------------------------------
       //	Implemented Function Lists
       //----------------------------------------------------
@@ -198,7 +173,7 @@ namespace bgslibrary
       void C_ClearNonEssentialEntries(short nClearNum, ColorModel* pModel);
       void C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short nReferredIdx, short nClearNum, ColorModel* pCachebook);
       void C_Absorption(int iAbsorbCnt, point pos, short** aContinuCnt, short** aRefferedIndex, ColorModel* pModel, ColorModel* pCache);
-    public:
+
       //----------------------------------------------------
       //	Implemented Variable Lists
       //----------------------------------------------------
@@ -250,5 +225,9 @@ namespace bgslibrary
       short** g_aCReferredIndex;					//To handle cache-book
       short** g_aCContinuousCnt;					//To handle cache-book
     };
+
+    bgs_register(MultiCue);
   }
 }
+
+#endif
diff --git a/src/algorithms/MultiLayer.cpp b/src/algorithms/MultiLayer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5223b587451484f2fa8182ed71034d2b0ceeaed
--- /dev/null
+++ b/src/algorithms/MultiLayer.cpp
@@ -0,0 +1,288 @@
+#include "MultiLayer.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+MultiLayer::MultiLayer() :
+  IBGS(quote(MultiLayer)),
+  frameNumber(0), saveModel(false),
+  disableDetectMode(true), disableLearning(false),
+  detectAfter(0), bg_model_preload(""), loadDefaultParams(true)
+{
+  debug_construction(MultiLayer);
+  initLoadSaveConfig(algorithmName);
+}
+
+MultiLayer::~MultiLayer() {
+  debug_destruction(MultiLayer);
+  finish();
+}
+
+void MultiLayer::setStatus(Status _status) {
+  status = _status;
+}
+
+void MultiLayer::finish() {
+  if (bg_model_preload.empty()) {
+    bg_model_preload = "./" + algorithmName + ".yml";
+  }
+
+  if (status == MLBGS_LEARN && saveModel == true) {
+    std::cout << algorithmName + " saving background model: " << bg_model_preload << std::endl;
+    BGS->Save(bg_model_preload.c_str());
+  }
+
+  cvReleaseImage(&fg_img);
+  cvReleaseImage(&bg_img);
+  cvReleaseImage(&fg_prob_img);
+  cvReleaseImage(&fg_mask_img);
+  cvReleaseImage(&fg_prob_img3);
+  cvReleaseImage(&merged_img);
+
+  delete BGS;
+}
+
+void MultiLayer::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+  CvSize img_size = cvSize(cvCeil((double)img_input.size().width), cvCeil((double)img_input.size().height));
+
+  if (firstTime) {
+    if (disableDetectMode)
+      status = MLBGS_LEARN;
+
+    if (status == MLBGS_LEARN)
+      std::cout << algorithmName + " in LEARN mode" << std::endl;
+
+    if (status == MLBGS_DETECT)
+      std::cout << algorithmName + " in DETECT mode" << std::endl;
+    
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+    IplImage _frame = cvIplImage(img_input);
+    org_img = &_frame;
+#else
+    org_img = new IplImage(img_input);
+#endif
+
+    fg_img = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
+    bg_img = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
+    fg_prob_img = cvCreateImage(img_size, org_img->depth, 1);
+    fg_mask_img = cvCreateImage(img_size, org_img->depth, 1);
+    fg_prob_img3 = cvCreateImage(img_size, org_img->depth, org_img->nChannels);
+    merged_img = cvCreateImage(cvSize(img_size.width * 2, img_size.height * 2), org_img->depth, org_img->nChannels);
+
+    BGS = new multilayer::CMultiLayerBGS();
+    BGS->Init(img_size.width, img_size.height);
+    BGS->SetForegroundMaskImage(fg_mask_img);
+    BGS->SetForegroundProbImage(fg_prob_img);
+
+    if (bg_model_preload.empty() == false) {
+      std::cout << algorithmName + " loading background model: " << bg_model_preload << std::endl;
+      BGS->Load(bg_model_preload.c_str());
+    }
+
+    if (status == MLBGS_DETECT) {
+      BGS->m_disableLearning = disableLearning;
+
+      if (disableLearning)
+        std::cout << algorithmName + " disabled learning in DETECT mode" << std::endl;
+      else
+        std::cout << algorithmName + " enabled learning in DETECT mode" << std::endl;
+    }
+
+    if (loadDefaultParams) {
+      std::cout << algorithmName + " loading default params" << std::endl;
+      max_mode_num = 5;
+      weight_updating_constant = 5.0;
+      texture_weight = 0.5;
+      bg_mode_percent = 0.6f;
+      pattern_neig_half_size = 4;
+      pattern_neig_gaus_sigma = 3.0f;
+      bg_prob_threshold = 0.2f;
+      bg_prob_updating_threshold = 0.2f;
+      robust_LBP_constant = 3;
+      min_noised_angle = 10.0 / 180.0 * PI; //0,01768
+      shadow_rate = 0.6f;
+      highlight_rate = 1.2f;
+      bilater_filter_sigma_s = 3.0f;
+      bilater_filter_sigma_r = 0.1f;
+    }
+    else
+      std::cout << algorithmName + " loading config params" << std::endl;
+
+    BGS->m_nMaxLBPModeNum = max_mode_num;
+    BGS->m_fWeightUpdatingConstant = weight_updating_constant;
+    BGS->m_fTextureWeight = texture_weight;
+    BGS->m_fBackgroundModelPercent = bg_mode_percent;
+    BGS->m_nPatternDistSmoothNeigHalfSize = pattern_neig_half_size;
+    BGS->m_fPatternDistConvGaussianSigma = pattern_neig_gaus_sigma;
+    BGS->m_fPatternColorDistBgThreshold = bg_prob_threshold;
+    BGS->m_fPatternColorDistBgUpdatedThreshold = bg_prob_updating_threshold;
+    BGS->m_fRobustColorOffset = robust_LBP_constant;
+    BGS->m_fMinNoisedAngle = min_noised_angle;
+    BGS->m_fRobustShadowRate = shadow_rate;
+    BGS->m_fRobustHighlightRate = highlight_rate;
+    BGS->m_fSigmaS = bilater_filter_sigma_s;
+    BGS->m_fSigmaR = bilater_filter_sigma_r;
+
+    if (loadDefaultParams) {
+      //frame_duration = 1.0 / 30.0;
+      //frame_duration = 1.0 / 25.0;
+      frame_duration = 1.0f / 10.0f;
+    }
+
+    BGS->SetFrameRate(frame_duration);
+
+    if (status == MLBGS_LEARN) {
+      if (loadDefaultParams) {
+        mode_learn_rate_per_second = 0.5;
+        weight_learn_rate_per_second = 0.5;
+        init_mode_weight = 0.05f;
+      }
+      else {
+        mode_learn_rate_per_second = learn_mode_learn_rate_per_second;
+        weight_learn_rate_per_second = learn_weight_learn_rate_per_second;
+        init_mode_weight = learn_init_mode_weight;
+      }
+    }
+
+    if (status == MLBGS_DETECT) {
+      if (loadDefaultParams) {
+        mode_learn_rate_per_second = 0.01f;
+        weight_learn_rate_per_second = 0.01f;
+        init_mode_weight = 0.001f;
+      }
+      else {
+        mode_learn_rate_per_second = detect_mode_learn_rate_per_second;
+        weight_learn_rate_per_second = detect_weight_learn_rate_per_second;
+        init_mode_weight = detect_init_mode_weight;
+      }
+    }
+
+    BGS->SetParameters(max_mode_num, mode_learn_rate_per_second, weight_learn_rate_per_second, init_mode_weight);
+    delete org_img;
+  }
+
+  //IplImage* inputImage = new IplImage(img_input);
+  //IplImage* img = cvCreateImage(img_size, IPL_DEPTH_8U, 3);
+  //cvCopy(inputImage, img);
+  //delete inputImage;
+
+  if (detectAfter > 0 && detectAfter == frameNumber) {
+    std::cout << algorithmName + " in DETECT mode" << std::endl;
+    status = MLBGS_DETECT;
+
+    mode_learn_rate_per_second = 0.01f;
+    weight_learn_rate_per_second = 0.01f;
+    init_mode_weight = 0.001f;
+
+    BGS->SetParameters(max_mode_num, mode_learn_rate_per_second, weight_learn_rate_per_second, init_mode_weight);
+    BGS->m_disableLearning = disableLearning;
+
+    if (disableLearning)
+      std::cout << algorithmName + " disabled learning in DETECT mode" << std::endl;
+    else
+      std::cout << algorithmName + " enabled learning in DETECT mode" << std::endl;
+  }
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  IplImage* img = &_frame;
+#else
+  IplImage* img = new IplImage(img_input);
+#endif
+
+  BGS->SetRGBInputImage(img);
+  BGS->Process();
+
+  BGS->GetBackgroundImage(bg_img);
+  BGS->GetForegroundImage(fg_img);
+  BGS->GetForegroundProbabilityImage(fg_prob_img3);
+  BGS->GetForegroundMaskImage(fg_mask_img);
+  BGS->MergeImages(4, img, bg_img, fg_prob_img3, fg_img, merged_img);
+
+  img_merged = cv::cvarrToMat(merged_img);
+  img_foreground = cv::cvarrToMat(fg_mask_img);
+  img_background = cv::cvarrToMat(bg_img);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_LAYERS", img_merged);
+    cv::imshow(algorithmName + "_FG", img_foreground);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete img;
+  //cvReleaseImage(&img);
+
+  firstTime = false;
+  frameNumber++;
+}
+
+void MultiLayer::save_config(cv::FileStorage &fs) {
+  fs << "preloadModel" << bg_model_preload;
+  fs << "saveModel" << saveModel;
+  fs << "detectAfter" << detectAfter;
+  fs << "disableDetectMode" << showOutput;
+  fs << "disableLearningInDetecMode" << disableLearning;
+  fs << "loadDefaultParams" << loadDefaultParams;
+  fs << "frame_duration" << frame_duration;
+  fs << "max_mode_num" << max_mode_num;
+  fs << "weight_updating_constant" << weight_updating_constant;
+  fs << "texture_weight" << texture_weight;
+  fs << "bg_mode_percent" << bg_mode_percent;
+  fs << "pattern_neig_half_size" << pattern_neig_half_size;
+  fs << "pattern_neig_gaus_sigma" << pattern_neig_gaus_sigma;
+  fs << "bg_prob_threshold" << bg_prob_threshold;
+  fs << "bg_prob_updating_threshold" << bg_prob_updating_threshold;
+  fs << "robust_LBP_constant" << robust_LBP_constant;
+  fs << "min_noised_angle" << min_noised_angle;
+  fs << "shadow_rate" << shadow_rate;
+  fs << "highlight_rate" << highlight_rate;
+  fs << "bilater_filter_sigma_s" << bilater_filter_sigma_s;
+  fs << "bilater_filter_sigma_r" << bilater_filter_sigma_r;
+  fs << "learn_mode_learn_rate_per_second" << learn_mode_learn_rate_per_second;
+  fs << "learn_weight_learn_rate_per_second" << learn_weight_learn_rate_per_second;
+  fs << "learn_init_mode_weight" << learn_init_mode_weight;
+  fs << "detect_mode_learn_rate_per_second" << detect_mode_learn_rate_per_second;
+  fs << "detect_weight_learn_rate_per_second" << detect_weight_learn_rate_per_second;
+  fs << "detect_init_mode_weight" << detect_init_mode_weight;
+  fs << "showOutput" << showOutput;
+}
+
+void MultiLayer::load_config(cv::FileStorage &fs) {
+  fs["preloadModel"] >> bg_model_preload;
+  fs["saveModel"] >> saveModel;
+  fs["detectAfter"] >> detectAfter;
+  fs["disableDetectMode"] >> disableDetectMode;
+  fs["disableLearningInDetecMode"] >> disableLearning;
+  fs["loadDefaultParams"] >> loadDefaultParams;
+  fs["frame_duration"] >> frame_duration;
+  fs["max_mode_num"] >> max_mode_num;
+  fs["weight_updating_constant"] >> weight_updating_constant;
+  fs["texture_weight"] >> texture_weight;
+  fs["bg_mode_percent"] >> bg_mode_percent;
+  fs["pattern_neig_half_size"] >> pattern_neig_half_size;
+  fs["pattern_neig_gaus_sigma"] >> pattern_neig_gaus_sigma;
+  fs["bg_prob_threshold"] >> bg_prob_threshold;
+  fs["bg_prob_updating_threshold"] >> bg_prob_updating_threshold;
+  fs["robust_LBP_constant"] >> robust_LBP_constant;
+  fs["min_noised_angle"] >> min_noised_angle;
+  fs["shadow_rate"] >> shadow_rate;
+  fs["highlight_rate"] >> highlight_rate;
+  fs["bilater_filter_sigma_s"] >> bilater_filter_sigma_s;
+  fs["bilater_filter_sigma_r"] >> bilater_filter_sigma_r;
+  fs["learn_mode_learn_rate_per_second"] >> learn_mode_learn_rate_per_second;
+  fs["learn_weight_learn_rate_per_second"] >> learn_weight_learn_rate_per_second;
+  fs["learn_init_mode_weight"] >> learn_init_mode_weight;
+  fs["detect_mode_learn_rate_per_second"] >> detect_mode_learn_rate_per_second;
+  fs["detect_weight_learn_rate_per_second"] >> detect_weight_learn_rate_per_second;
+  fs["detect_init_mode_weight"] >> detect_init_mode_weight;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/package_bgs/MultiLayer.h b/src/algorithms/MultiLayer.h
similarity index 69%
rename from package_bgs/MultiLayer.h
rename to src/algorithms/MultiLayer.h
index af7e128c9c8230653486bc5d1673405034e0eab8..b33d72fd076c929afe569ce33ea8721d914a137d 100644
--- a/package_bgs/MultiLayer.h
+++ b/src/algorithms/MultiLayer.h
@@ -1,21 +1,8 @@
-/*
-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
 
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 #include "IBGS.h"
 #include "MultiLayer/CMultiLayerBGS.h"
 
@@ -34,15 +21,15 @@ namespace bgslibrary
       };
 
     private:
-      long long frameNumber;
+      long frameNumber;
       cv::Mat img_merged;
       bool saveModel;
       bool disableDetectMode;
       bool disableLearning;
       int detectAfter;
-      CMultiLayerBGS* BGS;
+      multilayer::CMultiLayerBGS* BGS;
       Status status;
-      IplImage* img;
+      //IplImage* img;
       IplImage* org_img;
       IplImage* fg_img;
       IplImage* bg_img;
@@ -92,8 +79,12 @@ namespace bgslibrary
 
     private:
       void finish();
-      void saveConfig();
-      void loadConfig();
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
     };
+
+    bgs_register(MultiLayer);
   }
 }
+
+#endif
diff --git a/src/algorithms/MultiLayer/BGS.h b/src/algorithms/MultiLayer/BGS.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2754cf25316d43bbc1e8d905dc5079d967ec21d
--- /dev/null
+++ b/src/algorithms/MultiLayer/BGS.h
@@ -0,0 +1,175 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+// opencv legacy includes
+#include "OpenCvLegacyIncludes.h"
+
+#define BINARY_PATTERM_ELEM(c1, c2, offset)	\
+  ((float)(c2)-(float)(c1)+offset > 0)
+
+/*
+#define BINARY_PATTERM_ELEM(c1, c2, offset)	\
+( fabsf((float)(c2)-(float)(c1)) <= offset ? 1 : (float)(c2)-(float)(c1) >=0 )
+*/
+
+#ifndef PI
+#define PI 3.141592653589793f
+#endif
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      const int MAX_LBP_MODE_NUM = 5;
+      const float ROBUST_COLOR_OFFSET = 6.0f;
+      const float LOW_INITIAL_MODE_WEIGHT = 0.01f;
+      const float MODE_UPDATING_LEARN_RATE = 0.01f;
+      const float WEIGHT_UPDATING_LEARN_RATE = 0.01f;
+      const int COLOR_MAX_MIN_OFFSET = 5;
+      const float BACKGROUND_MODEL_PERCENT = 0.6f;
+      const float PATTERN_COLOR_DIST_BACKGROUND_THRESHOLD = 0.2f;
+      const float PATTERN_DIST_SMOOTH_NEIG_HALF_SIZE = 6;
+      const float PATTERN_DIST_CONV_GAUSSIAN_SIGMA = 2.5f;
+      const float ROBUST_SHADOW_RATE = 0.6f;
+      const float ROBUST_HIGHLIGHT_RATE = 1.20f;
+
+      /************************************************************************/
+      /* some data structures for multi-level LBP (local binary pattern)      */
+      /* texture feature for background subtraction                           */
+      /************************************************************************/
+      typedef struct _LBP
+      {
+        float* bg_pattern;			/* the average local binary pattern of background mode */
+        float* bg_intensity;			/* the average color intensity of background mode */
+        float* max_intensity;			/* the maximal color intensity of background mode */
+        float* min_intensity;			/* the minimal color intensity of background mode */
+        float weight;				/* the weight of background mode, i.e. probability that the background mode belongs to background */
+        float max_weight;			/* the maximal weight of background mode */
+        int bg_layer_num;			/* the background layer number of background mode */
+        unsigned long first_time;				/* the first time of background mode appearing */
+        unsigned long last_time;				/* the last time of background model appearing */
+        int freq;				/* the appearing frequency */
+        //long mnrl;				/* maximum negative run-length */
+        unsigned long layer_time;				/* the first time of background mode becoming a background layer */
+      }
+      LBPStruct;
+
+      typedef struct _PixelLBP
+      {
+        LBPStruct* LBPs;			/* the background modes */
+        unsigned short* lbp_idxes;		/* the indices of background modes */
+        unsigned int cur_bg_layer_no;
+        unsigned int num;			/* the total number of background modes */
+        unsigned int bg_num;			/* the number of the first background modes for foreground detection */
+        unsigned char* cur_intensity;		/* the color intensity of current pixel */
+        float* cur_pattern;			/* the local binary pattern of current pixel */
+        float matched_mode_first_time;		/* the index of currently matched pixel mode */
+      }
+      PixelLBPStruct;
+
+      /*********************************************************************************/
+      /* should replace the above structure using class in the future (not finished)   */
+      /*********************************************************************************/
+
+      class BG_PIXEL_MODE
+      {
+      public:
+        float* bg_lbp_pattern;			/* the average local binary pattern of background mode */
+        float* bg_intensity;			/* the average color intensity of background mode */
+        float* max_intensity;			/* the maximal color intensity of background mode */
+        float* min_intensity;			/* the minimal color intensity of background mode */
+        float weight;				/* the weight of background mode, i.e. probability that the background mode belongs to background */
+        float max_weight;			/* the maximal weight of background mode */
+        int bg_layer_num;			/* the background layer number of background mode */
+
+        int lbp_pattern_length;
+        int color_channel;
+
+        BG_PIXEL_MODE(int _lbp_pattern_length, int _color_channel = 3) {
+          lbp_pattern_length = _lbp_pattern_length;
+          color_channel = _color_channel;
+
+          bg_lbp_pattern = new float[lbp_pattern_length];
+          bg_intensity = new float[color_channel];
+          max_intensity = new float[color_channel];
+          min_intensity = new float[color_channel];
+        };
+
+        virtual ~BG_PIXEL_MODE() {
+          delete[] bg_lbp_pattern;
+          delete[] bg_intensity;
+          delete[] max_intensity;
+          delete[] min_intensity;
+        };
+      };
+
+      class BG_PIXEL_PATTERN
+      {
+      public:
+        BG_PIXEL_MODE** pixel_MODEs;		/* the background modes */
+        unsigned short* lbp_pattern_idxes;	/* the indices of background modes */
+        unsigned int cur_bg_layer_no;
+        unsigned int num;			/* the total number of background modes */
+        unsigned int bg_num;			/* the number of the first background modes for foreground detection */
+        unsigned char* cur_intensity;		/* the color intensity of current pixel */
+        float* cur_lbp_pattern;			/* the local binary pattern of current pixel */
+
+        int lbp_pattern_length;
+        int color_channel;
+        int pixel_mode_num;
+
+        BG_PIXEL_PATTERN(int _pixel_mode_num, int _lbp_pattern_length, int _color_channel = 3) {
+          pixel_mode_num = _pixel_mode_num;
+          lbp_pattern_length = _lbp_pattern_length;
+          color_channel = _color_channel;
+
+          pixel_MODEs = new BG_PIXEL_MODE*[pixel_mode_num];
+
+          for (int i = 0; i < pixel_mode_num; i++) {
+            pixel_MODEs[i] = new BG_PIXEL_MODE(_lbp_pattern_length, _color_channel);
+          }
+
+          lbp_pattern_idxes = new unsigned short[pixel_mode_num];
+          cur_intensity = new unsigned char[color_channel];
+          cur_lbp_pattern = new float[lbp_pattern_length];
+        };
+
+        virtual ~BG_PIXEL_PATTERN() {
+          delete[] lbp_pattern_idxes;
+          delete[] cur_intensity;
+          delete[] cur_lbp_pattern;
+
+          for (int i = 0; i < pixel_mode_num; i++)
+            delete pixel_MODEs[i];
+          delete[] pixel_MODEs;
+        };
+      };
+
+      class IMAGE_BG_MODEL
+      {
+        int pixel_length;
+
+        BG_PIXEL_PATTERN** pixel_PATTERNs;
+
+        IMAGE_BG_MODEL(int _pixel_length, int _pixel_mode_num, int _lbp_pattern_length, int _color_channel = 3) {
+          pixel_length = _pixel_length;
+
+          pixel_PATTERNs = new BG_PIXEL_PATTERN*[pixel_length];
+          for (int i = 0; i < pixel_length; i++)
+            pixel_PATTERNs[i] = new BG_PIXEL_PATTERN(_pixel_mode_num, _lbp_pattern_length, _color_channel);
+        }
+        virtual ~IMAGE_BG_MODEL() {
+          for (int i = 0; i < pixel_length; i++)
+            delete pixel_PATTERNs[i];
+          delete[] pixel_PATTERNs;
+        }
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/BackgroundSubtractionAPI.h b/src/algorithms/MultiLayer/BackgroundSubtractionAPI.h
new file mode 100644
index 0000000000000000000000000000000000000000..13f02084158d4f589bc13ed17d179764611ecf83
--- /dev/null
+++ b/src/algorithms/MultiLayer/BackgroundSubtractionAPI.h
@@ -0,0 +1,106 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+// opencv legacy includes
+#include "OpenCvLegacyIncludes.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      class CBackgroundSubtractionAPI
+      {
+      public:
+        //CBackgroundSubtractionAPI(){};
+        //virtual ~CBackgroundSubtractionAPI(){};
+
+        //-------------------------------------------------------------
+        // TO CALL AT INITIALISATION: DEFINES THE SIZE OF THE INPUT IMAGES
+        // NORMALLY, UNNECESSARY IF A CONFIGURATION FILE IS LOADED
+        void   Init(int width, int height);
+
+        //-------------------------------------------------------------
+        // PROVIDE A MASK TO DEFINE THE SET OF POINTS WHERE BACKGROUND
+        // SUBTRACTION DOES NOT NEED TO BE PERFORMED
+        //
+        //  mode is useful to specify if the points to remove from
+        //  processing are in addition to the ones potentially
+        //  removed according to the configuration file,
+        //  or if they are the only ones to be removed
+        //
+        // mode=0 : provided points need to be removed
+        //          in addition to those already removed
+        // mode=1 : the provided points are the only one to remove
+        //          from processing
+        // Note:  maskImage(li,co)=0 indicate the points to remove
+        //       from background processing
+        void   SetValidPointMask(IplImage* maskImage, int mode);
+
+        //-------------------------------------------------------------
+        //
+        //   set the frame rate, to adjust the update parameters
+        //   to the actual frame rate.
+        //   Can be called only once at initialisation,
+        //   but in online cases, can be used to indicate
+        //   the time interval during the last processed frame
+        //
+        //   frameDuration is in millisecond
+        void   SetFrameRate(float    frameDuration);
+
+        //-------------------------------------------------------------
+        //   PROVIDE A POINTER TO THE INPUT IMAGE
+        //   -> INDICATE WHERE THE NEW IMAGE TO PROCESS IS STORED
+        //
+        //   Here assumes that the input image will contain RGB images.
+        //   The memory of this image is handled by the caller.
+        //
+        //    The return value indicate whether the actual Background
+        //    Subtraction algorithm handles RGB images (1) or not (0).
+        //
+        int  SetRGBInputImage(IplImage  *  inputImage);
+
+        //-------------------------------------------------------------
+        //   PROVIDE A POINTER TO THE RESULT IMAGE
+        //   INDICATE WHERE THE BACKGROUND RESULT NEED TO BE STORED
+        //
+        //   The return value is 1 if correct image format is provided,
+        //   otherwise the return value is 0.
+        //   e.g. fg_mask_img = cvCreateImage(imgSize, IPL_DEPTH_8U, 1);
+        int  SetForegroundMaskImage(IplImage *fg_mask_img);
+
+        //   The return value is 1 if the function is implemented
+        //   with correct format, otherwise the return value is 0
+        //   e.g. fg_prob_img = cvCreateImage(imgSize, IPL_DEPTH_32F, 1);
+        int  SetForegroundProbImage(IplImage *fg_prob_img);
+
+        //-------------------------------------------------------------
+        // This function should be called each time a new image is
+        // available in the input image.
+        //
+        // The return value is 1 if everything goes well,
+        // otherwise the return value is 0.
+        //
+        int   Process();
+
+        //-------------------------------------------------------------
+        // this function should save parameters and information of the model
+        // (e.g. after a training of the model, or in such a way
+        // that the model can be reload to process the next frame
+        // type of save:
+        void   Save(char   *bg_model_fn);
+
+        //-------------------------------------------------------------
+        // this function should load the parameters necessary
+        // for the processing of the background subtraction or
+        // load background model information
+        void   Load(char  *bg_model_fn);
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/BlobExtraction.cpp b/src/algorithms/MultiLayer/BlobExtraction.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6f67a349afae929652f411e1f1f12069ff795663
--- /dev/null
+++ b/src/algorithms/MultiLayer/BlobExtraction.cpp
@@ -0,0 +1,1454 @@
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "BlobResult.h"
+#include "BlobExtraction.h"
+#include "OpenCvLegacyIncludes.h"
+
+//! Indica si la connectivitat es a 8 (si es desactiva es a 4)
+#define B_CONNECTIVITAT_8
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        //! si la imatge és cíclica verticalment (els blobs que toquen
+        //! les vores superior i inferior no es consideren externs)
+        //const int IMATGE_CICLICA_VERTICAL = 1;
+        //! si la imatge és cíclica horitzontalment (els blobs que toquen
+        //! les vores dreta i esquerra no es consideren externs)
+        //const int IMATGE_CICLICA_HORITZONTAL = 0;
+
+        const double SQRT2 = 1.41421356237310;
+        const double PERIMETRE_DIAGONAL = (SQRT2 - 2);
+
+        // color dels píxels de la màscara per ser exteriors
+        const int PIXEL_EXTERIOR = 0;
+
+        /**
+          - FUNCIÓ: BlobAnalysis
+          - FUNCIONALITAT: Extreu els blobs d'una imatge d'un sol canal
+          - PARÀMETRES:
+          - inputImage: Imatge d'entrada. Ha de ser d'un sol canal
+          - threshold: Nivell de gris per considerar un pixel blanc o negre
+          - maskImage: Imatge de màscara fora de la cual no es calculen els blobs. A més,
+          els blobs que toquen els pixels de la màscara a 0, són considerats
+          externs
+          - borderColor: Color del marc de la imatge (0=black or 1=white)
+          - findmoments: calcula els moments dels blobs o no
+          - RegionData: on es desarà el resultat
+          - RESULTAT:
+          - retorna true si tot ha anat bé, false si no. Deixa el resultat a blobs.
+          - RESTRICCIONS:
+          - La imatge d'entrada ha de ser d'un sol canal
+          - AUTOR: dgrossman@cdr.stanford.edu
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          - fpinyol@cvc.uab.es, rborras@cvc.uab.es: adaptació a les OpenCV
+          */
+        bool BlobAnalysis(IplImage* inputImage,
+          uchar threshold,
+          IplImage* maskImage,
+          bool borderColor,
+          bool findmoments,
+          blob_vector &RegionData)
+        {
+          // dimensions of input image taking in account the ROI
+          int Cols, Rows, startCol, startRow;
+
+          if (inputImage->roi)
+          {
+            CvRect imageRoi = cvGetImageROI(inputImage);
+            startCol = imageRoi.x;
+            startRow = imageRoi.y;
+            Cols = imageRoi.width;
+            Rows = imageRoi.height;
+          }
+          else
+          {
+            startCol = 0;
+            startRow = 0;
+            Cols = inputImage->width;
+            Rows = inputImage->height;
+          }
+
+          int Trans = Cols;				// MAX trans in any row
+          char* pMask = NULL;
+          char* pImage;
+
+          // Convert image array into transition array. In each row
+          // the transition array tells which columns have a color change
+          int iCol, iRow, iTran, Tran;				// Data for a given run
+          bool ThisCell, LastCell;		// Contents (colors (0 or 1)) within this row
+          int TransitionOffset = 0;		// Performance booster to avoid multiplication
+
+          // row 0 and row Rows+1 represent the border
+          int i;
+          int *Transition;				// Transition Matrix
+
+          int nombre_pixels_mascara = 0;
+          //! Imatge amb el perimetre extern de cada pixel
+          IplImage *imatgePerimetreExtern;
+
+          // input images must have only 1-channel and be an image
+          if (!CV_IS_IMAGE(inputImage) || (inputImage->nChannels != 1))
+          {
+            return false;
+          }
+          if (maskImage != NULL)
+          {
+            // input image and mask are a valid image?
+            if (!CV_IS_IMAGE(inputImage) || !CV_IS_IMAGE(maskImage))
+              return false;
+
+            // comprova que la màscara tingui les mateixes dimensions que la imatge
+            if (inputImage->width != maskImage->width || inputImage->height != maskImage->height)
+            {
+              return false;
+            }
+
+            // comprova que la màscara sigui una imatge d'un sol canal (grayscale)
+            if (maskImage->nChannels != 1)
+            {
+              return false;
+            }
+
+          }
+
+          // Initialize Transition array
+          Transition = new int[(Rows + 2)*(Cols + 2)];
+          memset(Transition, 0, (Rows + 2) * (Cols + 2) * sizeof(int));
+          Transition[0] = Transition[(Rows + 1) * (Cols + 2)] = Cols + 2;
+
+          // Start at the beginning of the image (startCol, startRow)
+          pImage = inputImage->imageData + startCol - 1 + startRow * inputImage->widthStep;
+
+          /*
+            Paral·lelització del càlcul de la matriu de transicions
+            Fem que cada iteració del for el faci un thread o l'altre ( tenim 2 possibles threads )
+            */
+          if (maskImage == NULL)
+          {
+            imatgePerimetreExtern = NULL;
+
+            //Fill Transition array
+            for (iRow = 1; iRow < Rows + 1; iRow++)		// Choose a row of Bordered image
+            {
+              TransitionOffset = iRow*(Cols + 2); //per a que sigui paral·litzable
+              iTran = 0;					// Index into Transition array
+              Tran = 0;					// No transitions at row start
+              LastCell = borderColor;
+
+              for (iCol = 0; iCol < Cols + 2; iCol++)	// Scan that row of Bordered image
+              {
+                if (iCol == 0 || iCol == Cols + 1)
+                  ThisCell = borderColor;
+                else
+                  ThisCell = ((unsigned char)*(pImage)) > threshold;
+
+                if (ThisCell != LastCell)
+                {
+                  Transition[TransitionOffset + iTran] = Tran;	// Save completed Tran
+                  iTran++;						// Prepare new index
+                  LastCell = ThisCell;			// With this color
+                }
+
+                Tran++;	// Tran continues
+                pImage++;
+              }
+
+              Transition[TransitionOffset + iTran] = Tran;	// Save completed run
+              if ((TransitionOffset + iTran + 1) < (Rows + 1)*(Cols + 2))
+              {
+                Transition[TransitionOffset + iTran + 1] = -1;
+              }
+              //jump to next row (beginning from (startCol, startRow))
+              pImage = inputImage->imageData - 1 + startCol + (iRow + startRow)*inputImage->widthStep;
+            }
+          }
+          else
+          {
+            //maskImage not NULL: Cal recòrrer la màscara també per calcular la matriu de transicions
+
+            char perimeter;
+            char *pPerimetre;
+
+            // creem la imatge que contindrà el perimetre extern de cada pixel
+            imatgePerimetreExtern = cvCreateImage(cvSize(maskImage->width, maskImage->height), IPL_DEPTH_8U, 1);
+            cvSetZero(imatgePerimetreExtern);
+
+            pMask = maskImage->imageData - 1;
+
+            //Fill Transition array
+            for (iRow = 1; iRow < Rows + 1; iRow++)		// Choose a row of Bordered image
+            {
+              TransitionOffset = iRow*(Cols + 2);
+              iTran = 0;					// Index into Transition array
+              Tran = 0;					// No transitions at row start
+              LastCell = borderColor;
+
+              pPerimetre = imatgePerimetreExtern->imageData + (iRow - 1) * imatgePerimetreExtern->widthStep;
+              //pMask = maskImage->imageData + (iRow-1) * maskImage->widthStep;
+
+              for (iCol = 0; iCol < Cols + 2; iCol++)	// Scan that row of Bordered image
+              {
+                if (iCol == 0 || iCol == Cols + 1 || ((unsigned char)*pMask) == PIXEL_EXTERIOR)
+                  ThisCell = borderColor;
+                else
+                  ThisCell = ((unsigned char)*(pImage)) > threshold;
+
+                if (ThisCell != LastCell)
+                {
+                  Transition[TransitionOffset + iTran] = Tran;	// Save completed Tran
+                  iTran++;						// Prepare new index
+                  LastCell = ThisCell;			// With this color
+                }
+
+                /*////////////////////////////////////////////////////////////////////////
+                  Calcul de la imatge amb els pixels externs
+                  ////////////////////////////////////////////////////////////////////////*/
+                  // pels pixels externs no cal calcular res pq no hi accedir-hem
+                if ((iCol > 0) && (iCol < Cols))
+                {
+                  if (*pMask == PIXEL_EXTERIOR)
+                  {
+                    *pPerimetre = 0;
+                  }
+                  else
+                  {
+                    perimeter = 0;
+
+                    // pixels al nord de l'actual
+                    if (iRow > 1)
+                    {
+                      if (*(pMask - maskImage->widthStep) == PIXEL_EXTERIOR) perimeter++;
+                    }
+
+                    // pixels a l'est i oest de l'actual
+                    if (iRow < imatgePerimetreExtern->height)
+                    {
+                      if ((iCol > 0) && (*(pMask - 1) == PIXEL_EXTERIOR)) perimeter++;
+
+                      if ((iCol < imatgePerimetreExtern->width - 1) && (*(pMask + 1) == PIXEL_EXTERIOR)) perimeter++;
+                    }
+
+                    // pixels al sud de l'actual
+                    if (iRow < imatgePerimetreExtern->height - 1)
+                    {
+                      if (*(pMask + maskImage->widthStep) == PIXEL_EXTERIOR) perimeter++;
+                    }
+
+                    *pPerimetre = perimeter;
+                  }
+                }
+
+                Tran++;	// Tran continues
+                pImage++;
+                pMask++;
+                pPerimetre++;
+              }
+              Transition[TransitionOffset + iTran] = Tran;	// Save completed run
+
+              if ((TransitionOffset + iTran + 1) < (Rows + 1)*(Cols + 2))
+              {
+                Transition[TransitionOffset + iTran + 1] = -1;
+              }
+
+
+              //jump to next row (beginning from (startCol, startRow))
+              pImage = inputImage->imageData - 1 + startCol + (iRow + startRow)*inputImage->widthStep;
+              //the mask should be the same size as image Roi, so don't take into account the offset
+              pMask = maskImage->imageData - 1 + iRow*maskImage->widthStep;
+            }
+          }
+
+          // Process transition code depending on Last row and This row
+          //
+          // Last ---++++++--+++++++++++++++-----+++++++++++++++++++-----++++++-------+++---
+          // This -----+++-----++++----+++++++++----+++++++---++------------------++++++++--
+          //
+          // There are various possibilities:
+          //
+          // Case     1       2       3       4       5       6       7       8
+          // Last |xxx    |xxxxoo |xxxxxxx|xxxxxxx|ooxxxxx|ooxxx  |ooxxxxx|    xxx|
+          // This |    yyy|    yyy|  yyyy |  yyyyy|yyyyyyy|yyyyyyy|yyyy   |yyyy   |
+          // Here o is optional
+          //
+          // Here are the primitive tests to distinguish these 6 cases:
+          //   A) Last end < This start - 1 OR NOT		Note: -1
+          //   B) This end < Last start OR NOT
+          //   C) Last start < This start OR NOT
+          //   D) This end < Last end OR NOT
+          //   E) This end = Last end OR NOT
+          //
+          // Here is how to use these tests to determine the case:
+          //   Case 1 = A [=> NOT B AND C AND NOT D AND NOT E]
+          //   Case 2 = C AND NOT D AND NOT E [AND NOT A AND NOT B]
+          //   Case 3 = C AND D [=> NOT E] [AND NOT A AND NOT B]
+          //   Case 4 = C AND NOT D AND E [AND NOT A AND NOT B]
+          //   Case 5 = NOT C AND E [=> NOT D] [AND NOT A AND NOT B]
+          //   Case 6 = NOT C AND NOT D AND NOT E [AND NOT A AND NOT B]
+          //   Case 7 = NOT C AND D [=> NOT E] [AND NOT A AND NOT B]
+          //   Case 8 = B [=> NOT A AND NOT C AND D AND NOT E]
+          //
+          // In cases 2,3,4,5,6,7 the following additional test is needed:
+          //   Match) This color = Last color OR NOT
+          //
+          // In cases 5,6,7 the following additional test is needed:
+          //   Known) This region was already matched OR NOT
+          //
+          // Here are the main tests and actions:
+          //   Case 1: LastIndex++;
+          //   Case 2: if(Match) {y = x;}
+          //           LastIndex++;
+          //   Case 3: if(Match) {y = x;}
+          //           else {y = new}
+          //           ThisIndex++;
+          //   Case 4: if(Match) {y = x;}
+          //           else {y = new}
+          //           LastIndex++;
+          //           ThisIndex++;
+          //   Case 5: if(Match AND NOT Known) {y = x}
+          //           else if(Match AND Known) {Subsume(x,y)}
+          //           LastIndex++;ThisIndex++
+          //   Case 6: if(Match AND NOT Known) {y = x}
+          //           else if(Match AND Known) {Subsume(x,y)}
+          //           LastIndex++;
+          //   Case 7: if(Match AND NOT Known) {y = x}
+          //           else if(Match AND Known) {Subsume(x,y)}
+          //           ThisIndex++;
+          //   Case 8: ThisIndex++;
+
+          int *SubsumedRegion = NULL;
+
+          double ThisParent;	// These data can change when the line is current
+          double ThisArea;
+          double ThisPerimeter;
+          double ThisSumX = 0;
+          double ThisSumY = 0;
+          double ThisSumXX = 0;
+          double ThisSumYY = 0;
+          double ThisSumXY = 0;
+          double ThisMinX;
+          double ThisMaxX;
+          double ThisMinY;
+          double ThisMaxY;
+          double LastPerimeter;	// This is the only data for retroactive change
+          double ThisExternPerimeter;
+
+          int HighRegionNum = 0;
+          //int RegionNum = 0;
+          int ErrorFlag = 0;
+
+          int LastRow, ThisRow;			// Row number
+          int LastStart, ThisStart;		// Starting column of run
+          int LastEnd, ThisEnd;			// Ending column of run
+          int LastColor, ThisColor;		// Color of run
+
+          int LastIndex, ThisIndex;		// Which run are we up to
+          int LastIndexCount, ThisIndexCount;	// Out of these runs
+          int LastRegionNum, ThisRegionNum;	// Which assignment
+          int *LastRegion;				// Row assignment of region number
+          int *ThisRegion;		// Row assignment of region number
+
+          int LastOffset = -(Trans + 2);	// For performance to avoid multiplication
+          int ThisOffset = 0;				// For performance to avoid multiplication
+          int ComputeData;
+
+          CvPoint actualedge;
+          uchar imagevalue;
+          bool CandidatExterior = false;
+
+          // apuntadors als blobs de la regió actual i last
+          CBlob *regionDataThisRegion, *regionDataLastRegion;
+
+          LastRegion = new int[Cols + 2];
+          ThisRegion = new int[Cols + 2];
+
+          for (i = 0; i < Cols + 2; i++)	// Initialize result arrays
+          {
+            LastRegion[i] = -1;
+            ThisRegion[i] = -1;
+          }
+
+          //create the external blob
+          RegionData.push_back(new CBlob());
+          SubsumedRegion = NewSubsume(SubsumedRegion, 0);
+          RegionData[0]->parent = -1;
+          RegionData[0]->area = (double)Transition[0];
+          RegionData[0]->perimeter = (double)(2 + 2 * Transition[0]);
+
+          ThisIndexCount = 1;
+          ThisRegion[0] = 0;	// Border region
+
+          // beginning of the image
+          // en cada linia, pimage apunta al primer pixel de la fila
+          pImage = inputImage->imageData - 1 + startCol + startRow * inputImage->widthStep;
+          //the mask should be the same size as image Roi, so don't take into account the offset
+          if (maskImage != NULL) pMask = maskImage->imageData - 1;
+
+          char *pImageAux, *pMaskAux = NULL;
+
+          // Loop over all rows
+          for (ThisRow = 1; ThisRow < Rows + 2; ThisRow++)
+          {
+            //cout << "========= THIS ROW = " << ThisRow << endl;	// for debugging
+            ThisOffset += Trans + 2;
+            ThisIndex = 0;
+            LastOffset += Trans + 2;;
+            LastRow = ThisRow - 1;
+            LastIndexCount = ThisIndexCount;
+            LastIndex = 0;
+
+            int EndLast = 0;
+            int EndThis = 0;
+
+            for (int j = 0; j < Trans + 2; j++)
+            {
+              int Index = ThisOffset + j;
+              int TranVal = Transition[Index];
+              if (TranVal > 0) ThisIndexCount = j + 1;	// stop at highest
+
+              if (ThisRegion[j] == -1) { EndLast = 1; }
+              if (TranVal < 0) { EndThis = 1; }
+
+              if (EndLast > 0 && EndThis > 0) { break; }
+
+              LastRegion[j] = ThisRegion[j];
+              ThisRegion[j] = -1;		// Flag indicates region is not initialized
+            }
+
+            int MaxIndexCount = LastIndexCount;
+            if (ThisIndexCount > MaxIndexCount) MaxIndexCount = ThisIndexCount;
+
+            // Main loop over runs within Last and This rows
+            while (LastIndex < LastIndexCount && ThisIndex < ThisIndexCount)
+            {
+              ComputeData = 0;
+
+              if (LastIndex == 0) LastStart = 0;
+              else LastStart = Transition[LastOffset + LastIndex - 1];
+              LastEnd = Transition[LastOffset + LastIndex] - 1;
+              LastColor = LastIndex - 2 * (LastIndex / 2);
+              LastRegionNum = LastRegion[LastIndex];
+
+              regionDataLastRegion = RegionData[LastRegionNum];
+
+
+              if (ThisIndex == 0) ThisStart = 0;
+              else ThisStart = Transition[ThisOffset + ThisIndex - 1];
+              ThisEnd = Transition[ThisOffset + ThisIndex] - 1;
+              ThisColor = ThisIndex - 2 * (ThisIndex / 2);
+              ThisRegionNum = ThisRegion[ThisIndex];
+
+              if (ThisRegionNum >= 0)
+                regionDataThisRegion = RegionData[ThisRegionNum];
+              else
+                regionDataThisRegion = NULL;
+
+
+              // blobs externs
+              CandidatExterior = false;
+              if (
+      #if !IMATGE_CICLICA_VERTICAL
+                ThisRow == 1 || ThisRow == Rows ||
+      #endif
+      #if !IMATGE_CICLICA_HORITZONTAL
+                ThisStart <= 1 || ThisEnd >= Cols ||
+      #endif
+                GetExternPerimeter(ThisStart, ThisEnd, ThisRow, inputImage->width, inputImage->height, imatgePerimetreExtern)
+                )
+              {
+                CandidatExterior = true;
+              }
+
+              int TestA = (LastEnd < ThisStart - 1);	// initially false
+              int TestB = (ThisEnd < LastStart);		// initially false
+              int TestC = (LastStart < ThisStart);	// initially false
+              int TestD = (ThisEnd < LastEnd);
+              int TestE = (ThisEnd == LastEnd);
+
+              int TestMatch = (ThisColor == LastColor);		// initially true
+              int TestKnown = (ThisRegion[ThisIndex] >= 0);	// initially false
+
+              int Case = 0;
+              if (TestA) Case = 1;
+              else if (TestB) Case = 8;
+              else if (TestC)
+              {
+                if (TestD) Case = 3;
+                else if (!TestE) Case = 2;
+                else Case = 4;
+              }
+              else
+              {
+                if (TestE) Case = 5;
+                else if (TestD) Case = 7;
+                else Case = 6;
+              }
+
+              // Initialize common variables
+              ThisArea = (float) 0.0;
+
+              if (findmoments)
+              {
+                ThisSumX = ThisSumY = (float) 0.0;
+                ThisSumXX = ThisSumYY = ThisSumXY = (float) 0.0;
+              }
+              ThisMinX = ThisMinY = (float) 1000000.0;
+              ThisMaxX = ThisMaxY = (float)-1.0;
+
+              LastPerimeter = ThisPerimeter = (float) 0.0;
+              ThisParent = (float)-1;
+              ThisExternPerimeter = 0.0;
+
+              // Determine necessary action and take it
+              switch (Case)
+              {
+              case 1: //|xxx    |
+                //|    yyy|
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                LastIndex++;
+
+                //afegim la cantonada a LastRegion
+                actualedge.x = ThisEnd;
+                actualedge.y = ThisRow - 1;
+                cvSeqPush(regionDataLastRegion->edges, &actualedge);
+
+                //afegim la cantonada a ThisRegion
+                actualedge.x = ThisStart - 1;
+                actualedge.y = ThisRow - 1;
+                cvSeqPush(regionDataThisRegion->edges, &actualedge);
+
+                break;
+
+
+              case 2: //|xxxxoo |
+                //|    yyy|
+
+                if (TestMatch)	// Same color
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  LastPerimeter = LastEnd - ThisStart + 1;	// to subtract
+                  ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter +
+                    PERIMETRE_DIAGONAL * 2;
+
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL * 2;
+                  }
+                  ComputeData = 1;
+                }
+
+                //afegim la cantonada a ThisRegion
+                if (ThisRegionNum != -1)
+                {
+                  // afegim dos vertexs si són diferents, només
+                  if (ThisStart - 1 != ThisEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                }
+                //afegim la cantonada a ThisRegion
+                if (LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  // afegim dos vertexs si són diferents, només
+                  if (ThisStart - 1 != ThisEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                  }
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                LastIndex++;
+                break;
+
+
+              case 3: //|xxxxxxx|
+                //|  yyyy |
+
+                if (TestMatch)	// Same color
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  LastPerimeter = ThisArea;	// to subtract
+                  ThisPerimeter = 2 + ThisArea + PERIMETRE_DIAGONAL * 2;
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL * 2;
+                  }
+                }
+                else		// Different color => New region
+                {
+                  ThisParent = LastRegionNum;
+                  ThisRegionNum = ++HighRegionNum;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  ThisPerimeter = 2 + 2 * ThisArea;
+                  RegionData.push_back(new CBlob());
+                  regionDataThisRegion = RegionData.back();
+
+                  SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
+                  if (CandidatExterior)
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                }
+
+                if (ThisRegionNum != -1)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                }
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                ComputeData = 1;
+                ThisIndex++;
+                break;
+
+
+              case 4:	//|xxxxxxx|
+                //|  yyyyy|
+
+                if (TestMatch)	// Same color
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  LastPerimeter = ThisArea;	// to subtract
+                  ThisPerimeter = 2 + ThisArea + PERIMETRE_DIAGONAL;
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL;
+                  }
+                }
+                else		// Different color => New region
+                {
+                  ThisParent = LastRegionNum;
+                  ThisRegionNum = ++HighRegionNum;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  ThisPerimeter = 2 + 2 * ThisArea;
+                  RegionData.push_back(new CBlob());
+                  regionDataThisRegion = RegionData.back();
+                  SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
+                  if (CandidatExterior)
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                }
+
+                if (ThisRegionNum != -1)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                }
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                ComputeData = 1;
+
+      #ifdef B_CONNECTIVITAT_8
+                if (TestMatch)
+                {
+                  LastIndex++;
+                  ThisIndex++;
+                }
+                else
+                {
+                  LastIndex++;
+                }
+      #else
+                LastIndex++;
+                ThisIndex++;
+      #endif					
+                break;
+
+
+              case 5:	//|ooxxxxx|
+                //|yyyyyyy|
+
+                if (!TestMatch && !TestKnown)	// Different color and unknown => new region
+                {
+                  ThisParent = LastRegionNum;
+                  ThisRegionNum = ++HighRegionNum;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  ThisPerimeter = 2 + 2 * ThisArea;
+                  RegionData.push_back(new CBlob());
+                  regionDataThisRegion = RegionData.back();
+                  SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
+                  if (CandidatExterior)
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                }
+                else if (TestMatch && !TestKnown)	// Same color and unknown
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  LastPerimeter = LastEnd - LastStart + 1;	// to subtract
+                  ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
+                    + PERIMETRE_DIAGONAL * (LastStart != ThisStart);
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL * (LastStart != ThisStart);
+                  }
+                  ComputeData = 1;
+                }
+                else if (TestMatch && TestKnown)	// Same color and known
+                {
+                  LastPerimeter = LastEnd - LastStart + 1;	// to subtract
+                  //ThisPerimeter = - LastPerimeter;
+                  ThisPerimeter = -2 * LastPerimeter
+                    + PERIMETRE_DIAGONAL * (LastStart != ThisStart);
+
+                  if (ThisRegionNum > LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
+                      findmoments, ThisRegionNum, LastRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
+                      if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
+                    }
+                    ThisRegionNum = LastRegionNum;
+                  }
+                  else if (ThisRegionNum < LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
+                      findmoments, LastRegionNum, ThisRegionNum);
+
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
+                      if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
+                    }
+                    LastRegionNum = ThisRegionNum;
+                  }
+                }
+
+
+                if (ThisRegionNum != -1)
+                {
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+
+                  if (ThisStart - 1 != LastEnd)
+                  {
+                    //afegim la cantonada a la regio
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                }
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+
+      #ifdef B_CONNECTIVITAT_8
+                if (TestMatch)
+                {
+                  LastIndex++;
+                  ThisIndex++;
+                }
+                else
+                {
+                  LastIndex++;
+                }
+      #else
+                LastIndex++;
+                ThisIndex++;
+      #endif	
+                break;
+
+
+              case 6:	//|ooxxx  |
+                //|yyyyyyy|
+
+                if (TestMatch && !TestKnown)
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  LastPerimeter = LastEnd - LastStart + 1;	// to subtract
+                  ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
+                    + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+                  }
+                  ComputeData = 1;
+                }
+                else if (TestMatch && TestKnown)
+                {
+                  LastPerimeter = LastEnd - LastStart + 1;	// to subtract
+                  //ThisPerimeter = - LastPerimeter;
+                  ThisPerimeter = -2 * LastPerimeter
+                    + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+
+                  if (ThisRegionNum > LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
+                      findmoments, ThisRegionNum, LastRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
+                      if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
+                    }
+                    ThisRegionNum = LastRegionNum;
+                  }
+                  else if (ThisRegionNum < LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
+                      findmoments, LastRegionNum, ThisRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
+                      if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
+                    }
+                    LastRegionNum = ThisRegionNum;
+                  }
+                }
+
+
+                if (ThisRegionNum != -1)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  if (ThisStart - 1 != LastEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                }
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  //afegim la cantonada a la regio
+                  if (ThisStart - 1 != LastEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                LastIndex++;
+                break;
+
+
+              case 7:	//|ooxxxxx|
+                //|yyyy   |
+
+                if (!TestMatch && !TestKnown)	// Different color and unknown => new region
+                {
+                  ThisParent = LastRegionNum;
+                  ThisRegionNum = ++HighRegionNum;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  ThisPerimeter = 2 + 2 * ThisArea;
+                  RegionData.push_back(new CBlob());
+                  regionDataThisRegion = RegionData.back();
+                  SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum);
+                  if (CandidatExterior)
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                }
+                else if (TestMatch && !TestKnown)
+                {
+                  ThisRegionNum = LastRegionNum;
+                  regionDataThisRegion = regionDataLastRegion;
+                  ThisArea = ThisEnd - ThisStart + 1;
+                  ThisPerimeter = 2 + ThisArea;
+                  LastPerimeter = ThisEnd - LastStart + 1;
+                  ThisPerimeter = 2 + 2 * ThisArea - LastPerimeter
+                    + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+                  if (CandidatExterior)
+                  {
+                    ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow,
+                      inputImage->width, inputImage->height,
+                      imatgePerimetreExtern);
+
+                    ThisExternPerimeter += PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+                  }
+                  ComputeData = 1;
+                }
+                else if (TestMatch && TestKnown)
+                {
+                  LastPerimeter = ThisEnd - LastStart + 1;	// to subtract
+                  //ThisPerimeter = - LastPerimeter;
+                  ThisPerimeter = -2 * LastPerimeter
+                    + PERIMETRE_DIAGONAL + PERIMETRE_DIAGONAL * (ThisStart != LastStart);
+
+                  if (ThisRegionNum > LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
+                      findmoments, ThisRegionNum, LastRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
+                      if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
+                    }
+                    ThisRegionNum = LastRegionNum;
+                  }
+                  else if (ThisRegionNum < LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
+                      findmoments, LastRegionNum, ThisRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
+                      if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
+                    }
+                    LastRegionNum = ThisRegionNum;
+                  }
+                }
+
+                if (ThisRegionNum != -1)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  if (ThisStart - 1 != LastEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                }
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisEnd;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+                  if (ThisStart - 1 != LastEnd)
+                  {
+                    actualedge.x = ThisStart - 1;
+                    actualedge.y = ThisRow - 1;
+                    cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                  }
+                }
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                ThisIndex++;
+                break;
+
+              case 8:	//|    xxx|
+                //|yyyy   |
+
+      #ifdef B_CONNECTIVITAT_8					
+              // fusionem blobs
+                if (TestMatch)
+                {
+                  if (ThisRegionNum > LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataThisRegion, regionDataLastRegion,
+                      findmoments, ThisRegionNum, LastRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == ThisRegionNum) ThisRegion[iOld] = LastRegionNum;
+                      if (LastRegion[iOld] == ThisRegionNum) LastRegion[iOld] = LastRegionNum;
+                    }
+                    ThisRegionNum = LastRegionNum;
+                  }
+                  else if (ThisRegionNum < LastRegionNum)
+                  {
+                    Subsume(RegionData, HighRegionNum, SubsumedRegion, regionDataLastRegion, regionDataThisRegion,
+                      findmoments, LastRegionNum, ThisRegionNum);
+                    for (int iOld = 0; iOld < MaxIndexCount; iOld++)
+                    {
+                      if (ThisRegion[iOld] == LastRegionNum) ThisRegion[iOld] = ThisRegionNum;
+                      if (LastRegion[iOld] == LastRegionNum) LastRegion[iOld] = ThisRegionNum;
+                    }
+                    LastRegionNum = ThisRegionNum;
+                  }
+
+                  regionDataThisRegion->perimeter = regionDataThisRegion->perimeter + PERIMETRE_DIAGONAL * 2;
+                }
+      #endif
+
+                if (ThisRegionNum != -1)
+                {
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataThisRegion->edges, &actualedge);
+                }
+      #ifdef B_CONNECTIVITAT_8					
+                // si hem creat un nou blob, afegim tb a l'anterior
+                if (!TestMatch && LastRegionNum != -1 && LastRegionNum != ThisRegionNum)
+                {
+      #endif					
+                  //afegim la cantonada a la regio
+                  actualedge.x = ThisStart - 1;
+                  actualedge.y = ThisRow - 1;
+                  cvSeqPush(regionDataLastRegion->edges, &actualedge);
+      #ifdef B_CONNECTIVITAT_8
+                }
+      #endif
+
+                ThisRegion[ThisIndex] = ThisRegionNum;
+                LastRegion[LastIndex] = LastRegionNum;
+                ThisIndex++;
+      #ifdef B_CONNECTIVITAT_8					
+                LastIndex--;
+      #endif
+                break;
+
+              default:
+                ErrorFlag = -1;
+              }	// end switch case
+
+              // calculate the blob moments and mean gray level of the current blob (ThisRegionNum)
+              if (ComputeData > 0)
+              {
+                // compute blob moments if necessary
+                if (findmoments)
+                {
+                  float ImageRow = (float)(ThisRow - 1);
+
+                  for (int k = ThisStart; k <= ThisEnd; k++)
+                  {
+                    ThisSumX += (float)(k - 1);
+                    ThisSumXX += (float)(k - 1) * (k - 1);
+                  }
+
+                  ThisSumXY = ThisSumX * ImageRow;
+                  ThisSumY = ThisArea * ImageRow;
+                  ThisSumYY = ThisSumY * ImageRow;
+
+                }
+
+                // compute the mean gray level and its std deviation
+                if (ThisRow <= Rows)
+                {
+                  pImageAux = pImage + ThisStart;
+                  if (maskImage != NULL) pMaskAux = pMask + ThisStart;
+                  for (int k = ThisStart; k <= ThisEnd; k++)
+                  {
+                    if ((k > 0) && (k <= Cols))
+                    {
+                      if (maskImage != NULL)
+                      {
+                        // només es té en compte el valor del píxel de la
+                        // imatge que queda dins de la màscara
+                        // (de pas, comptem el nombre de píxels de la màscara)
+                        if (((unsigned char)*pMaskAux) != PIXEL_EXTERIOR)
+                        {
+                          imagevalue = (unsigned char)(*pImageAux);
+                          regionDataThisRegion->mean += imagevalue;
+                          regionDataThisRegion->stddev += imagevalue*imagevalue;
+                        }
+                        else
+                        {
+                          nombre_pixels_mascara++;
+                        }
+                      }
+                      else
+                      {
+                        imagevalue = (unsigned char)(*pImageAux);
+                        regionDataThisRegion->mean += imagevalue;
+                        regionDataThisRegion->stddev += imagevalue*imagevalue;
+
+                      }
+                    }
+                    pImageAux++;
+                    if (maskImage != NULL) pMaskAux++;
+                  }
+                }
+
+                // compute the min and max values of X and Y
+                if (ThisStart - 1 < (int)ThisMinX) ThisMinX = (float)(ThisStart - 1);
+                if (ThisMinX < (float) 0.0) ThisMinX = (float) 0.0;
+                if (ThisEnd > (int) ThisMaxX) ThisMaxX = (float)ThisEnd;
+
+                if (ThisRow - 1 < ThisMinY) ThisMinY = ThisRow - 1;
+                if (ThisMinY < (float) 0.0) ThisMinY = (float) 0.0;
+                if (ThisRow > ThisMaxY) ThisMaxY = ThisRow;
+              }
+
+              // put the current results into RegionData
+              if (ThisRegionNum >= 0)
+              {
+                if (ThisParent >= 0) { regionDataThisRegion->parent = (int)ThisParent; }
+                regionDataThisRegion->etiqueta = ThisRegionNum;
+                regionDataThisRegion->area += ThisArea;
+                regionDataThisRegion->perimeter += ThisPerimeter;
+                regionDataThisRegion->externPerimeter += ThisExternPerimeter;
+
+                if (ComputeData > 0)
+                {
+                  if (findmoments)
+                  {
+                    regionDataThisRegion->sumx += ThisSumX;
+                    regionDataThisRegion->sumy += ThisSumY;
+                    regionDataThisRegion->sumxx += ThisSumXX;
+                    regionDataThisRegion->sumyy += ThisSumYY;
+                    regionDataThisRegion->sumxy += ThisSumXY;
+                  }
+                  regionDataThisRegion->perimeter -= LastPerimeter;
+                  regionDataThisRegion->minx = MIN(regionDataThisRegion->minx, ThisMinX);
+                  regionDataThisRegion->maxx = MAX(regionDataThisRegion->maxx, ThisMaxX);
+                  regionDataThisRegion->miny = MIN(regionDataThisRegion->miny, ThisMinY);
+                  regionDataThisRegion->maxy = MAX(regionDataThisRegion->maxy, ThisMaxY);
+                }
+                // blobs externs
+                if (CandidatExterior)
+                {
+                  regionDataThisRegion->exterior = true;
+                }
+
+              }
+            }	// end Main loop
+
+            if (ErrorFlag != 0) {
+              delete[] Transition;
+              delete[] ThisRegion;
+              delete[] LastRegion;
+              return false;
+            }
+            // ens situem al primer pixel de la seguent fila
+            pImage = inputImage->imageData - 1 + startCol + (ThisRow + startRow) * inputImage->widthStep;
+
+            if (maskImage != NULL)
+              pMask = maskImage->imageData - 1 + ThisRow * maskImage->widthStep;
+          }	// end Loop over all rows
+
+          // eliminem l'àrea del marc
+          // i també els píxels de la màscara
+          // ATENCIO: PERFER: el fet de restar el nombre_pixels_mascara del
+          // blob 0 només serà cert si la màscara té contacte amb el marc.
+          // Si no, s'haurà de trobar quin és el blob que conté més píxels del
+          // compte.
+          RegionData[0]->area -= (Rows + 1 + Cols + 1) * 2 + nombre_pixels_mascara;
+
+          // eliminem el perímetre de més:
+          // - sense marc: 2m+2n (perímetre extern)
+          // - amb marc:   2(m+2)+2(n+2) = 2m+2n + 8
+          // (segurament no és del tot acurat)
+          // (i amb les màscares encara menys...)
+          RegionData[0]->perimeter -= 8.0;
+
+          // Condense the list
+          blob_vector::iterator itNew, itOld, iti;
+          CBlob *blobActual;
+
+          itNew = RegionData.begin();
+          itOld = RegionData.begin();
+          int iNew = 0;
+          for (int iOld = 0; iOld <= HighRegionNum; iOld++, itOld++)
+          {
+            if (SubsumedRegion[iOld] < 1)	// This number not subsumed
+            {
+              // Move data from old region number to new region number
+              //*RegionData[iNew] = *RegionData[iOld];
+              **itNew = **itOld;
+
+              // Update and parent pointer if necessary
+              iti = RegionData.begin();
+              for (int i = 0; i <= HighRegionNum; i++)
+              {
+                //if(RegionData[i]->parent == iOld) { RegionData[i]->parent = iNew; }
+                if ((*iti)->parent == iOld) { (*iti)->parent = iNew; }
+
+                ++iti;
+              }
+              iNew++;
+              ++itNew;
+            }
+          }
+
+
+          HighRegionNum = iNew - 1;				// Update where the data ends
+          RegionData[HighRegionNum]->parent = -1;	// and set end of array flag
+
+
+          if (findmoments)
+          {
+            iti = RegionData.begin();
+            // Normalize summation fields into moments
+            for (ThisRegionNum = 0; ThisRegionNum <= HighRegionNum; ThisRegionNum++, iti++)
+            {
+              blobActual = *iti;
+
+              // Get averages
+              blobActual->sumx /= blobActual->area;
+              blobActual->sumy /= blobActual->area;
+              blobActual->sumxx /= blobActual->area;
+              blobActual->sumyy /= blobActual->area;
+              blobActual->sumxy /= blobActual->area;
+
+              // Create moments
+              blobActual->sumxx -= blobActual->sumx * blobActual->sumx;
+              blobActual->sumyy -= blobActual->sumy * blobActual->sumy;
+              blobActual->sumxy -= blobActual->sumx * blobActual->sumy;
+              if (blobActual->sumxy > -1.0E-14 && blobActual->sumxy < 1.0E-14)
+              {
+                blobActual->sumxy = (float) 0.0; // Eliminate roundoff error
+              }
+
+            }
+          }
+
+          //Get the real mean and std deviation
+          iti = RegionData.begin();
+          for (ThisRegionNum = 0; ThisRegionNum <= HighRegionNum; ThisRegionNum++, iti++)
+          {
+            blobActual = *iti;
+            if (blobActual->area > 1)
+            {
+              blobActual->stddev =
+                sqrt(
+                (
+                  blobActual->stddev * blobActual->area -
+                  blobActual->mean * blobActual->mean
+                  ) /
+                  (blobActual->area*(blobActual->area - 1))
+                );
+            }
+            else
+              blobActual->stddev = 0;
+
+            if (blobActual->area > 0)
+              blobActual->mean /= blobActual->area;
+            else
+              blobActual->mean = 0;
+
+          }
+          // eliminem els blobs subsumats
+          blob_vector::iterator itBlobs = RegionData.begin() + HighRegionNum + 1;
+          while (itBlobs != RegionData.end())
+          {
+            delete *itBlobs;
+            //RegionData.erase( itBlobs );
+            ++itBlobs;
+          }
+          RegionData.erase(RegionData.begin() + HighRegionNum + 1, RegionData.end());
+
+          //free(RegionData);
+          free(SubsumedRegion);
+          delete[] Transition;
+          delete[] ThisRegion;
+          delete[] LastRegion;
+
+          if (imatgePerimetreExtern) cvReleaseImage(&imatgePerimetreExtern);
+
+          return true;
+        }
+
+
+        int *NewSubsume(int *subsumed, int index_subsume)
+        {
+          if (index_subsume == 0)
+          {
+            subsumed = (int*)malloc(sizeof(int));
+          }
+          else
+          {
+            subsumed = (int*)realloc(subsumed, (index_subsume + 1) * sizeof(int));
+          }
+          subsumed[index_subsume] = 0;
+          return subsumed;
+        }
+
+        /**
+          Fusiona dos blobs i afegeix el blob les característiques del blob RegionData[HiNum]
+          al blob RegionData[LoNum]. Al final allibera el blob de RegionData[HiNum]
+          */
+        void Subsume(blob_vector &RegionData,
+          int HighRegionNum,
+          int* SubsumedRegion,
+          CBlob* blobHi,
+          CBlob* blobLo,
+          bool findmoments,
+          int HiNum,
+          int LoNum)
+        {
+          // cout << "\nSubsuming " << HiNum << " into " << LoNum << endl; // for debugging
+
+          int i;
+
+          blobLo->minx = MIN(blobHi->minx, blobLo->minx);
+          blobLo->miny = MIN(blobHi->miny, blobLo->miny);
+          blobLo->maxx = MAX(blobHi->maxx, blobLo->maxx);
+          blobLo->maxy = MAX(blobHi->maxy, blobLo->maxy);
+          blobLo->area += blobHi->area;
+          blobLo->perimeter += blobHi->perimeter;
+          blobLo->externPerimeter += blobHi->externPerimeter;
+          blobLo->exterior = blobLo->exterior || blobHi->exterior;
+          blobLo->mean += blobHi->mean;
+          blobLo->stddev += blobHi->stddev;
+
+          if (findmoments)
+          {
+            blobLo->sumx += blobHi->sumx;
+            blobLo->sumy += blobHi->sumy;
+            blobLo->sumxx += blobHi->sumxx;
+            blobLo->sumyy += blobHi->sumyy;
+            blobLo->sumxy += blobHi->sumxy;
+          }
+          // Make sure no region still has subsumed region as parent
+          blob_vector::iterator it = (RegionData.begin() + HiNum + 1);
+
+          for (i = HiNum + 1; i <= HighRegionNum; i++, it++)
+          {
+            if ((*it)->parent == (float)HiNum) { (*it)->parent = LoNum; }
+          }
+
+          // Mark dead region number for future compression
+          SubsumedRegion[HiNum] = 1;
+          // marquem el blob com a lliure
+          blobHi->etiqueta = -1;
+
+          // Atenció!!!! abans d'eliminar els edges
+          // s'han de traspassar del blob HiNum al blob LoNum
+          blobHi->CopyEdges(*blobLo);
+          blobHi->ClearEdges();
+        }
+
+        /**
+          - FUNCIÓ: GetExternPerimeter
+          - FUNCIONALITAT: Retorna el perimetre extern d'una run lenght
+          - PARÀMETRES:
+          - start: columna d'inici del run
+          - end: columna final del run
+          - row: fila del run
+          - maskImage: màscara pels pixels externs
+          - RESULTAT:
+          - quantitat de perimetre extern d'un run, suposant que és un blob
+          d'una única fila d'alçada
+          - RESTRICCIONS:
+          - AUTOR:
+          - DATA DE CREACIÓ: 2006/02/27
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+        double GetExternPerimeter(int start, int end, int row, int width, int height, IplImage *imatgePerimetreExtern)
+        {
+          double perimeter = 0.0f;
+          char *pPerimetre;
+
+
+          // comprovem les dimensions de la imatge
+          perimeter += (start <= 0) + (end >= width - 1);
+          if (row <= 1) perimeter += start - end;
+          if (row >= height - 1) perimeter += start - end;
+
+
+          // comprovem els pixels que toquen a la màscara (si s'escau)
+          if (imatgePerimetreExtern != NULL)
+          {
+            if (row <= 0 || row >= height) return perimeter;
+
+            if (start < 0) start = 1;
+            if (end >= width) end = width - 2;
+
+            pPerimetre = imatgePerimetreExtern->imageData + (row - 1) * imatgePerimetreExtern->widthStep + start;
+            for (int x = start - 1; x <= end; x++)
+            {
+              perimeter += *pPerimetre;
+              pPerimetre++;
+            }
+          }
+
+          return perimeter;
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/BlobExtraction.h b/src/algorithms/MultiLayer/BlobExtraction.h
new file mode 100644
index 0000000000000000000000000000000000000000..71e1f405768e11fc6be393846e88eb6f60e1ab01
--- /dev/null
+++ b/src/algorithms/MultiLayer/BlobExtraction.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        //! Extreu els blobs d'una imatge
+        bool BlobAnalysis(IplImage* inputImage, uchar threshold, IplImage* maskImage,
+          bool borderColor, bool findmoments, blob_vector &RegionData);
+
+        // FUNCIONS AUXILIARS
+
+        //! Fusiona dos blobs
+        void Subsume(blob_vector &RegionData, int, int*, CBlob*, CBlob*, bool, int, int);
+        //! Reallocata el vector auxiliar de blobs subsumats
+        int *NewSubsume(int *SubSumedRegion, int elems_inbuffer);
+        //! Retorna el perimetre extern d'una run lenght
+        double GetExternPerimeter(int start, int end, int row, int width, int height, IplImage *maskImage);
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/BlobLibraryConfiguration.h b/src/algorithms/MultiLayer/BlobLibraryConfiguration.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c7454e8076924645d1a68dea578b2f1caff0599
--- /dev/null
+++ b/src/algorithms/MultiLayer/BlobLibraryConfiguration.h
@@ -0,0 +1,9 @@
+#pragma once
+
+//! Indica si es volen fer servir les MatrixCV o no
+//! Use/Not use the MatrixCV class
+//#define MATRIXCV_ACTIU
+
+// Uses/not use the blob object factory
+//#define BLOB_OBJECT_FACTORY
+
diff --git a/src/algorithms/MultiLayer/BlobResult.cpp b/src/algorithms/MultiLayer/BlobResult.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b1a1bf6e005b048cd3ed793ca2f689de2dd98672
--- /dev/null
+++ b/src/algorithms/MultiLayer/BlobResult.cpp
@@ -0,0 +1,805 @@
+#include <limits.h>
+#include <stdio.h>
+#include <functional>
+#include <algorithm>
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "BlobResult.h"
+#include "BlobExtraction.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        /**
+          - FUNCIÓ: CBlobResult
+          - FUNCIONALITAT: Constructor estandard.
+          - PARÀMETRES:
+          - RESULTAT:
+          - Crea un CBlobResult sense cap blob
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobResult
+            - FUNCTIONALITY: Standard constructor
+            - PARAMETERS:
+            - RESULT:
+            - creates an empty set of blobs
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlobResult::CBlobResult()
+        {
+          m_blobs = blob_vector();
+        }
+
+        /**
+          - FUNCIÓ: CBlobResult
+          - FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seqüència de blobs
+          amb els blobs resultants de l'anàlisi de blobs de la imatge.
+          - PARÀMETRES:
+          - source: imatge d'on s'extreuran els blobs
+          - mask: màscara a aplicar. Només es calcularan els blobs on la màscara sigui
+          diferent de 0. Els blobs que toquin a un pixel 0 de la màscara seran
+          considerats exteriors.
+          - threshold: llindar que s'aplicarà a la imatge source abans de calcular els blobs
+          - findmoments: indica si s'han de calcular els moments de cada blob
+          - RESULTAT:
+          - objecte CBlobResult amb els blobs de la imatge source
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlob
+            - FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs in
+            the image
+            - PARAMETERS:
+            - source: image to extract the blobs from
+            - mask: optional mask to apply. The blobs will be extracted where the mask is
+            not 0. All the neighbouring blobs where the mask is 0 will be extern blobs
+            - threshold: threshold level to apply to the image before computing blobs
+            - findmoments: true to calculate the blob moments (slower)
+            - RESULT:
+            - object with all the blobs in the image. It throws an EXCEPCIO_CALCUL_BLOBS
+            if some error appears in the BlobAnalysis function
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlobResult::CBlobResult(IplImage *source, IplImage *mask, int threshold, bool findmoments)
+        {
+          bool success;
+
+          try
+          {
+            // cridem la funció amb el marc a true=1=blanc (així no unirà els blobs externs)
+            success = BlobAnalysis(source, (uchar)threshold, mask, true, findmoments, m_blobs);
+          }
+          catch (...)
+          {
+            success = false;
+          }
+
+          if (!success) throw EXCEPCIO_CALCUL_BLOBS;
+        }
+
+        /**
+          - FUNCIÓ: CBlobResult
+          - FUNCIONALITAT: Constructor de còpia. Inicialitza la seqüència de blobs
+          amb els blobs del paràmetre.
+          - PARÀMETRES:
+          - source: objecte que es copiarà
+          - RESULTAT:
+          - objecte CBlobResult amb els blobs de l'objecte source
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobResult
+            - FUNCTIONALITY: Copy constructor
+            - PARAMETERS:
+            - source: object to copy
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlobResult::CBlobResult(const CBlobResult &source)
+        {
+          m_blobs = blob_vector(source.GetNumBlobs());
+
+          // creem el nou a partir del passat com a paràmetre
+          m_blobs = blob_vector(source.GetNumBlobs());
+          // copiem els blobs de l'origen a l'actual
+          blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
+          blob_vector::iterator pBlobsDst = m_blobs.begin();
+
+          while (pBlobsSrc != source.m_blobs.end())
+          {
+            // no podem cridar a l'operador = ja que blob_vector és un
+            // vector de CBlob*. Per tant, creem un blob nou a partir del
+            // blob original
+            *pBlobsDst = new CBlob(**pBlobsSrc);
+            ++pBlobsSrc;
+            ++pBlobsDst;
+          }
+        }
+
+
+
+        /**
+          - FUNCIÓ: ~CBlobResult
+          - FUNCIONALITAT: Destructor estandard.
+          - PARÀMETRES:
+          - RESULTAT:
+          - Allibera la memòria reservada de cadascun dels blobs de la classe
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: ~CBlobResult
+            - FUNCTIONALITY: Destructor
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlobResult::~CBlobResult()
+        {
+          ClearBlobs();
+        }
+
+        /**************************************************************************
+          Operadors / Operators
+          **************************************************************************/
+
+
+          /**
+            - FUNCIÓ: operador =
+            - FUNCIONALITAT: Assigna un objecte source a l'actual
+            - PARÀMETRES:
+            - source: objecte a assignar
+            - RESULTAT:
+            - Substitueix els blobs actuals per els de l'objecte source
+            - RESTRICCIONS:
+            - AUTOR: Ricard Borràs
+            - DATA DE CREACIÓ: 25-05-2005.
+            - MODIFICACIÓ: Data. Autor. Descripció.
+            */
+            /**
+              - FUNCTION: Assigment operator
+              - FUNCTIONALITY:
+              - PARAMETERS:
+              - RESULT:
+              - RESTRICTIONS:
+              - AUTHOR: Ricard Borràs
+              - CREATION DATE: 25-05-2005.
+              - MODIFICATION: Date. Author. Description.
+              */
+        CBlobResult& CBlobResult::operator=(const CBlobResult& source)
+        {
+          // si ja són el mateix, no cal fer res
+          if (this != &source)
+          {
+            // alliberem el conjunt de blobs antic
+            for (int i = 0; i < GetNumBlobs(); i++)
+            {
+              delete m_blobs[i];
+            }
+            m_blobs.clear();
+            // creem el nou a partir del passat com a paràmetre
+            m_blobs = blob_vector(source.GetNumBlobs());
+            // copiem els blobs de l'origen a l'actual
+            blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
+            blob_vector::iterator pBlobsDst = m_blobs.begin();
+
+            while (pBlobsSrc != source.m_blobs.end())
+            {
+              // no podem cridar a l'operador = ja que blob_vector és un
+              // vector de CBlob*. Per tant, creem un blob nou a partir del
+              // blob original
+              *pBlobsDst = new CBlob(**pBlobsSrc);
+              ++pBlobsSrc;
+              ++pBlobsDst;
+            }
+          }
+          return *this;
+        }
+
+
+        /**
+          - FUNCIÓ: operador +
+          - FUNCIONALITAT: Concatena els blobs de dos CBlobResult
+          - PARÀMETRES:
+          - source: d'on s'agafaran els blobs afegits a l'actual
+          - RESULTAT:
+          - retorna un nou CBlobResult amb els dos CBlobResult concatenats
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - NOTA: per la implementació, els blobs del paràmetre es posen en ordre invers
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: + operator
+            - FUNCTIONALITY: Joins the blobs in source with the current ones
+            - PARAMETERS:
+            - source: object to copy the blobs
+            - RESULT:
+            - object with the actual blobs and the source blobs
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlobResult CBlobResult::operator+(const CBlobResult& source)
+        {
+          //creem el resultat a partir dels blobs actuals
+          CBlobResult resultat(*this);
+
+          // reservem memòria per als nous blobs
+          resultat.m_blobs.resize(resultat.GetNumBlobs() + source.GetNumBlobs());
+
+          // declarem els iterador per recòrrer els blobs d'origen i desti
+          blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin();
+          blob_vector::iterator pBlobsDst = resultat.m_blobs.end();
+
+          // insertem els blobs de l'origen a l'actual
+          while (pBlobsSrc != source.m_blobs.end())
+          {
+            --pBlobsDst;
+            *pBlobsDst = new CBlob(**pBlobsSrc);
+            ++pBlobsSrc;
+          }
+
+          return resultat;
+        }
+
+        /**************************************************************************
+          Operacions / Operations
+          **************************************************************************/
+
+          /**
+            - FUNCIÓ: AddBlob
+            - FUNCIONALITAT: Afegeix un blob al conjunt
+            - PARÀMETRES:
+            - blob: blob a afegir
+            - RESULTAT:
+            - modifica el conjunt de blobs actual
+            - RESTRICCIONS:
+            - AUTOR: Ricard Borràs
+            - DATA DE CREACIÓ: 2006/03/01
+            - MODIFICACIÓ: Data. Autor. Descripció.
+            */
+        void CBlobResult::AddBlob(CBlob *blob)
+        {
+          if (blob != NULL)
+            m_blobs.push_back(new CBlob(blob));
+        }
+
+
+        /**
+          - FUNCIÓ: GetSTLResult
+          - FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe
+          - PARÀMETRES:
+          - evaluador: Qualsevol objecte derivat de COperadorBlob
+          - RESULTAT:
+          - Retorna un array de double's STL amb el resultat per cada blob
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: GetResult
+            - FUNCTIONALITY: Computes the function evaluador on all the blobs of the class
+            and returns a vector with the result
+            - PARAMETERS:
+            - evaluador: function to apply to each blob (any object derived from the
+            COperadorBlob class )
+            - RESULT:
+            - vector with all the results in the same order as the blobs
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double_stl_vector CBlobResult::GetSTLResult(funcio_calculBlob *evaluador) const
+        {
+          if (GetNumBlobs() <= 0)
+          {
+            return double_stl_vector();
+          }
+
+          // definim el resultat
+          double_stl_vector result = double_stl_vector(GetNumBlobs());
+          // i iteradors sobre els blobs i el resultat
+          double_stl_vector::iterator itResult = result.begin();
+          blob_vector::const_iterator itBlobs = m_blobs.begin();
+
+          // avaluem la funció en tots els blobs
+          while (itBlobs != m_blobs.end())
+          {
+            *itResult = (*evaluador)(**itBlobs);
+            ++itBlobs;
+            ++itResult;
+          }
+          return result;
+        }
+
+        /**
+          - FUNCIÓ: GetNumber
+          - FUNCIONALITAT: Calcula el resultat especificat sobre un únic blob de la classe
+          - PARÀMETRES:
+          - evaluador: Qualsevol objecte derivat de COperadorBlob
+          - indexblob: número de blob del que volem calcular el resultat.
+          - RESULTAT:
+          - Retorna un double amb el resultat
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: GetNumber
+            - FUNCTIONALITY: Computes the function evaluador on a blob of the class
+            - PARAMETERS:
+            - indexBlob: index of the blob to compute the function
+            - evaluador: function to apply to each blob (any object derived from the
+            COperadorBlob class )
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobResult::GetNumber(int indexBlob, funcio_calculBlob *evaluador) const
+        {
+          if (indexBlob < 0 || indexBlob >= GetNumBlobs())
+            RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
+          return (*evaluador)(*m_blobs[indexBlob]);
+        }
+
+        /////////////////////////// FILTRAT DE BLOBS ////////////////////////////////////
+
+        /**
+          - FUNCIÓ: Filter
+          - FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb només
+          els blobs que han passat el filtre.
+          El filtrat es basa en especificar condicions sobre un resultat dels blobs
+          i seleccionar (o excloure) aquells blobs que no compleixen una determinada
+          condicio
+          - PARÀMETRES:
+          - dst: variable per deixar els blobs filtrats
+          - filterAction:	acció de filtrat. Incloure els blobs trobats (B_INCLUDE),
+          o excloure els blobs trobats (B_EXCLUDE)
+          - evaluador: Funció per evaluar els blobs (qualsevol objecte derivat de COperadorBlob
+          - Condition: tipus de condició que ha de superar la mesura (FilterType)
+          sobre cada blob per a ser considerat.
+          B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
+          B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
+          - LowLimit:  valor numèric per a la comparació (Condition) de la mesura (FilterType)
+          - HighLimit: valor numèric per a la comparació (Condition) de la mesura (FilterType)
+          (només té sentit per a aquelles condicions que tenen dos valors
+          (B_INSIDE, per exemple).
+          - RESULTAT:
+          - Deixa els blobs resultants del filtrat a destination
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: Filter
+            - FUNCTIONALITY: Get some blobs from the class based on conditions on measures
+            of the blobs.
+            - PARAMETERS:
+            - dst: where to store the selected blobs
+            - filterAction:	B_INCLUDE: include the blobs which pass the filter in the result
+            B_EXCLUDE: exclude the blobs which pass the filter in the result
+            - evaluador: Object to evaluate the blob
+            - Condition: How to decide if  the result returned by evaluador on each blob
+            is included or not. It can be:
+            B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
+            B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
+            - LowLimit:  numerical value to evaluate the Condition on evaluador(blob)
+            - HighLimit: numerical value to evaluate the Condition on evaluador(blob).
+            Only useful for B_INSIDE and B_OUTSIDE
+            - RESULT:
+            - It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE)
+            the Condition on the result returned by evaluador on each blob
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlobResult::Filter(CBlobResult &dst,
+          int filterAction,
+          funcio_calculBlob *evaluador,
+          int condition,
+          double lowLimit, double highLimit /*=0*/)
+
+        {
+          int i, numBlobs;
+          bool resultavaluacio;
+          double_stl_vector avaluacioBlobs;
+          double_stl_vector::iterator itavaluacioBlobs;
+
+          if (GetNumBlobs() <= 0) return;
+          if (!evaluador) return;
+          //avaluem els blobs amb la funció pertinent
+          avaluacioBlobs = GetSTLResult(evaluador);
+          itavaluacioBlobs = avaluacioBlobs.begin();
+          numBlobs = GetNumBlobs();
+          switch (condition)
+          {
+          case B_EQUAL:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs == lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_NOT_EQUAL:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs != lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_GREATER:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs > lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_LESS:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs < lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_GREATER_OR_EQUAL:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs >= lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_LESS_OR_EQUAL:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = *itavaluacioBlobs <= lowLimit;
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_INSIDE:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = (*itavaluacioBlobs >= lowLimit) && (*itavaluacioBlobs <= highLimit);
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          case B_OUTSIDE:
+            for (i = 0; i < numBlobs; i++, itavaluacioBlobs++)
+            {
+              resultavaluacio = (*itavaluacioBlobs < lowLimit) || (*itavaluacioBlobs > highLimit);
+              if ((resultavaluacio && filterAction == B_INCLUDE) ||
+                (!resultavaluacio && filterAction == B_EXCLUDE))
+              {
+                dst.m_blobs.push_back(new CBlob(GetBlob(i)));
+              }
+            }
+            break;
+          }
+
+
+          // en cas de voler filtrar un CBlobResult i deixar-ho en el mateix CBlobResult
+          // ( operacio inline )
+          if (&dst == this)
+          {
+            // esborrem els primers blobs ( que són els originals )
+            // ja que els tindrem replicats al final si passen el filtre
+            blob_vector::iterator itBlobs = m_blobs.begin();
+            for (int i = 0; i < numBlobs; i++)
+            {
+              delete *itBlobs;
+              ++itBlobs;
+            }
+            m_blobs.erase(m_blobs.begin(), itBlobs);
+          }
+        }
+
+
+        /**
+          - FUNCIÓ: GetBlob
+          - FUNCIONALITAT: Retorna un blob si aquest existeix (index != -1)
+          - PARÀMETRES:
+          - indexblob: index del blob a retornar
+          - RESULTAT:
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /*
+            - FUNCTION: GetBlob
+            - FUNCTIONALITY: Gets the n-th blob (without ordering the blobs)
+            - PARAMETERS:
+            - indexblob: index in the blob array
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlob CBlobResult::GetBlob(int indexblob) const
+        {
+          if (indexblob < 0 || indexblob >= GetNumBlobs())
+            RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
+
+          return *m_blobs[indexblob];
+        }
+        CBlob *CBlobResult::GetBlob(int indexblob)
+        {
+          if (indexblob < 0 || indexblob >= GetNumBlobs())
+            RaiseError(EXCEPTION_BLOB_OUT_OF_BOUNDS);
+
+          return m_blobs[indexblob];
+        }
+
+        /**
+          - FUNCIÓ: GetNthBlob
+          - FUNCIONALITAT: Retorna l'enèssim blob segons un determinat criteri
+          - PARÀMETRES:
+          - criteri: criteri per ordenar els blobs (objectes derivats de COperadorBlob)
+          - nBlob: index del blob a retornar
+          - dst: on es retorna el resultat
+          - RESULTAT:
+          - retorna el blob nBlob a dst ordenant els blobs de la classe segons el criteri
+          en ordre DESCENDENT. Per exemple, per obtenir el blob major:
+          GetNthBlob( CBlobGetArea(), 0, blobMajor );
+          GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob més gran)
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /*
+            - FUNCTION: GetNthBlob
+            - FUNCTIONALITY: Gets the n-th blob ordering first the blobs with some criteria
+            - PARAMETERS:
+            - criteri: criteria to order the blob array
+            - nBlob: index of the returned blob in the ordered blob array
+            - dst: where to store the result
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlobResult::GetNthBlob(funcio_calculBlob *criteri, int nBlob, CBlob &dst) const
+        {
+          // verifiquem que no estem accedint fora el vector de blobs
+          if (nBlob < 0 || nBlob >= GetNumBlobs())
+          {
+            //RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS );
+            dst = CBlob();
+            return;
+          }
+
+          double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat;
+          double valorEnessim;
+
+          //avaluem els blobs amb la funció pertinent
+          avaluacioBlobs = GetSTLResult(criteri);
+
+          avaluacioBlobsOrdenat = double_stl_vector(GetNumBlobs());
+
+          // obtenim els nBlob primers resultats (en ordre descendent)
+          std::partial_sort_copy(avaluacioBlobs.begin(),
+            avaluacioBlobs.end(),
+            avaluacioBlobsOrdenat.begin(),
+            avaluacioBlobsOrdenat.end(),
+            std::greater<double>());
+
+          valorEnessim = avaluacioBlobsOrdenat[nBlob];
+
+          // busquem el primer blob que té el valor n-ssim
+          double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin();
+
+          bool trobatBlob = false;
+          int indexBlob = 0;
+          while (itAvaluacio != avaluacioBlobs.end() && !trobatBlob)
+          {
+            if (*itAvaluacio == valorEnessim)
+            {
+              trobatBlob = true;
+              dst = CBlob(GetBlob(indexBlob));
+            }
+            ++itAvaluacio;
+            indexBlob++;
+          }
+        }
+
+        /**
+          - FUNCIÓ: ClearBlobs
+          - FUNCIONALITAT: Elimina tots els blobs de l'objecte
+          - PARÀMETRES:
+          - RESULTAT:
+          - Allibera tota la memòria dels blobs
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs Navarra
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /*
+            - FUNCTION: ClearBlobs
+            - FUNCTIONALITY: Clears all the blobs from the object and releases all its memory
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlobResult::ClearBlobs()
+        {
+          /*for( int i = 0; i < GetNumBlobs(); i++ )
+            {
+            delete m_blobs[i];
+            }*/
+          blob_vector::iterator itBlobs = m_blobs.begin();
+          while (itBlobs != m_blobs.end())
+          {
+            delete *itBlobs;
+            ++itBlobs;
+          }
+
+          m_blobs.clear();
+        }
+
+        /**
+          - FUNCIÓ: RaiseError
+          - FUNCIONALITAT: Funció per a notificar errors al l'usuari (en debug) i llença
+          les excepcions
+          - PARÀMETRES:
+          - errorCode: codi d'error
+          - RESULTAT:
+          - Ensenya un missatge a l'usuari (en debug) i llença una excepció
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs Navarra
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /*
+            - FUNCTION: RaiseError
+            - FUNCTIONALITY: Error handling function
+            - PARAMETERS:
+            - errorCode: reason of the error
+            - RESULT:
+            - in _DEBUG version, shows a message box with the error. In release is silent.
+            In both cases throws an exception with the error.
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlobResult::RaiseError(const int errorCode) const
+        {
+          throw errorCode;
+        }
+
+
+
+        /**************************************************************************
+          Auxiliars / Auxiliary functions
+          **************************************************************************/
+
+
+          /**
+            - FUNCIÓ: PrintBlobs
+            - FUNCIONALITAT: Escriu els paràmetres (àrea, perímetre, exterior, mitjana)
+            de tots els blobs a un fitxer.
+            - PARÀMETRES:
+            - nom_fitxer: path complet del fitxer amb el resultat
+            - RESULTAT:
+            - RESTRICCIONS:
+            - AUTOR: Ricard Borràs
+            - DATA DE CREACIÓ: 25-05-2005.
+            - MODIFICACIÓ: Data. Autor. Descripció.
+            */
+            /*
+              - FUNCTION: PrintBlobs
+              - FUNCTIONALITY: Prints some blob features in an ASCII file
+              - PARAMETERS:
+              - nom_fitxer: full path + filename to generate
+              - RESULT:
+              - RESTRICTIONS:
+              - AUTHOR: Ricard Borràs
+              - CREATION DATE: 25-05-2005.
+              - MODIFICATION: Date. Author. Description.
+              */
+        void CBlobResult::PrintBlobs(char *nom_fitxer) const
+        {
+          double_stl_vector area, /*perimetre,*/ exterior, mitjana, compacitat, longitud,
+            externPerimeter, perimetreConvex, perimetre;
+          int i;
+          FILE *fitxer_sortida;
+
+          area = GetSTLResult(CBlobGetArea());
+          perimetre = GetSTLResult(CBlobGetPerimeter());
+          exterior = GetSTLResult(CBlobGetExterior());
+          mitjana = GetSTLResult(CBlobGetMean());
+          compacitat = GetSTLResult(CBlobGetCompactness());
+          longitud = GetSTLResult(CBlobGetLength());
+          externPerimeter = GetSTLResult(CBlobGetExternPerimeter());
+          perimetreConvex = GetSTLResult(CBlobGetHullPerimeter());
+
+          fitxer_sortida = fopen(nom_fitxer, "w");
+
+          for (i = 0; i < GetNumBlobs(); i++)
+          {
+            fprintf(fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n",
+              i, area[i], perimetre[i], externPerimeter[i], perimetreConvex[i], exterior[i], mitjana[i], compacitat[i], longitud[i]);
+          }
+          fclose(fitxer_sortida);
+
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/BlobResult.h b/src/algorithms/MultiLayer/BlobResult.h
new file mode 100644
index 0000000000000000000000000000000000000000..2213231fa8dcd48e5b6abdc828b2516310ad8837
--- /dev/null
+++ b/src/algorithms/MultiLayer/BlobResult.h
@@ -0,0 +1,150 @@
+#pragma once
+
+#include <math.h>
+#include <vector>
+#include <functional>
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "BlobLibraryConfiguration.h"
+// opencv legacy includes
+#include "OpenCvLegacyIncludes.h"
+#include "blob.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        typedef std::vector<double> double_stl_vector;
+
+        /**************************************************************************
+          Filtres / Filters
+          **************************************************************************/
+
+          //! accions que es poden fer amb els filtres
+          //! Actions performed by a filter (include or exclude blobs)
+        const long B_INCLUDE = 1L;
+        const long B_EXCLUDE = 2L;
+
+        //! condicions sobre els filtres
+        //! Conditions to apply the filters
+        const long B_EQUAL = 3L;
+        const long B_NOT_EQUAL = 4L;
+        const long B_GREATER = 5L;
+        const long B_LESS = 6L;
+        const long B_GREATER_OR_EQUAL = 7L;
+        const long B_LESS_OR_EQUAL = 8L;
+        const long B_INSIDE = 9L;
+        const long B_OUTSIDE = 10L;
+
+        /**************************************************************************
+          Excepcions / Exceptions
+          **************************************************************************/
+
+          //! Excepcions llençades per les funcions:
+        const int EXCEPTION_BLOB_OUT_OF_BOUNDS = 1000;
+        const int EXCEPCIO_CALCUL_BLOBS = 1001;
+
+        //! definició de que es un vector de blobs
+        typedef std::vector<CBlob*>	blob_vector;
+
+        /**
+            Classe que conté un conjunt de blobs i permet extreure'n propietats
+            o filtrar-los segons determinats criteris.
+            Class to calculate the blobs of an image and calculate some properties
+            on them. Also, the class provides functions to filter the blobs using
+            some criteria.
+            */
+        class CBlobResult
+        {
+        public:
+          //! constructor estandard, crea un conjunt buit de blobs
+          //! Standard constructor, it creates an empty set of blobs
+          CBlobResult();
+          //! constructor a partir d'una imatge
+          //! Image constructor, it creates an object with the blobs of the image
+          CBlobResult(IplImage *source, IplImage *mask, int threshold, bool findmoments);
+          //! constructor de còpia
+          //! Copy constructor
+          CBlobResult(const CBlobResult &source);
+          //! Destructor
+          virtual ~CBlobResult();
+
+          //! operador = per a fer assignacions entre CBlobResult
+          //! Assigment operator
+          CBlobResult& operator=(const CBlobResult& source);
+          //! operador + per concatenar dos CBlobResult
+          //! Addition operator to concatenate two sets of blobs
+          CBlobResult operator+(const CBlobResult& source);
+
+          //! Afegeix un blob al conjunt
+          //! Adds a blob to the set of blobs
+          void AddBlob(CBlob *blob);
+
+      #ifdef MATRIXCV_ACTIU
+          //! Calcula un valor sobre tots els blobs de la classe retornant una MatrixCV
+          //! Computes some property on all the blobs of the class
+          double_vector GetResult(funcio_calculBlob *evaluador) const;
+      #endif
+          //! Calcula un valor sobre tots els blobs de la classe retornant un std::vector<double>
+          //! Computes some property on all the blobs of the class
+          double_stl_vector GetSTLResult(funcio_calculBlob *evaluador) const;
+
+          //! Calcula un valor sobre un blob de la classe
+          //! Computes some property on one blob of the class
+          double GetNumber(int indexblob, funcio_calculBlob *evaluador) const;
+
+          //! Retorna aquells blobs que compleixen les condicions del filtre en el destination
+          //! Filters the blobs of the class using some property
+          void Filter(CBlobResult &dst,
+            int filterAction, funcio_calculBlob *evaluador,
+            int condition, double lowLimit, double highLimit = 0);
+
+          //! Retorna l'enèssim blob segons un determinat criteri
+          //! Sorts the blobs of the class acording to some criteria and returns the n-th blob
+          void GetNthBlob(funcio_calculBlob *criteri, int nBlob, CBlob &dst) const;
+
+          //! Retorna el blob enèssim
+          //! Gets the n-th blob of the class ( without sorting )
+          CBlob GetBlob(int indexblob) const;
+          CBlob *GetBlob(int indexblob);
+
+          //! Elimina tots els blobs de l'objecte
+          //! Clears all the blobs of the class
+          void ClearBlobs();
+
+          //! Escriu els blobs a un fitxer
+          //! Prints some features of all the blobs in a file
+          void PrintBlobs(char *nom_fitxer) const;
+
+
+          //Metodes GET/SET
+
+          //! Retorna el total de blobs
+          //! Gets the total number of blobs
+          int GetNumBlobs() const
+          {
+            return(m_blobs.size());
+          }
+
+        private:
+          //! Funció per gestionar els errors
+          //! Function to manage the errors
+          void RaiseError(const int errorCode) const;
+
+        protected:
+          //! Vector amb els blobs
+          //! Vector with all the blobs
+          blob_vector		m_blobs;
+        };
+      }
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/MultiLayer/CMultiLayerBGS.cpp b/src/algorithms/MultiLayer/CMultiLayerBGS.cpp
similarity index 95%
rename from package_bgs/MultiLayer/CMultiLayerBGS.cpp
rename to src/algorithms/MultiLayer/CMultiLayerBGS.cpp
index 43417361cff3902bc8bf8bdfa0ba2a2f20c8b1b1..cc5f3389f9ac5668083d8caccc54493c6743c417 100644
--- a/package_bgs/MultiLayer/CMultiLayerBGS.cpp
+++ b/src/algorithms/MultiLayer/CMultiLayerBGS.cpp
@@ -1,65 +1,24 @@
-/*
-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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// BackgroundSubtraction.cpp: implementation of the CMultiLayerBGS class.
-//
-//////////////////////////////////////////////////////////////////////
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
 
-#include "CMultiLayerBGS.h"
+#include <ctime>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <cmath>
+#include <iostream>
 
-#include <ctime>						// clock
-#include <cstdlib>						// C standard library
-#include <cstdio>						// C I/O (for sscanf)
-#include <cstring>						// string manipulation
-#include <fstream>						// file I/O
-#include <cmath>						// math includes
-#include <iostream>                                             // I/O streams
+#include "CMultiLayerBGS.h"
 #include "OpenCvLegacyIncludes.h"
 
-using namespace Blob;
+//#if CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9
+//#define CV_RGB(r, g, b) cvScalar((b), (g), (r), 0)
+//#endif
+//#define CV_RGB_LEGACY(r, g, b) cvScalar((b), (g), (r), 0)
 
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
+using namespace bgslibrary::algorithms::multilayer;
+using namespace bgslibrary::algorithms::multilayer::blob;
 
 CMultiLayerBGS::CMultiLayerBGS() {
   m_nMaxLBPModeNum = MAX_LBP_MODE_NUM;
@@ -1279,7 +1238,7 @@ void CMultiLayerBGS::GetBgLayerNoImage(IplImage *bg_layer_no_img, CvScalar *laye
     rgb[0] = rgb[1] = rgb[2] = 0;
     int rgb_idx = 0;
     for (int l = 0; l < bg_layer_color_num; l++) {
-      bg_layer_colors[l] = CV_RGB(rgb[0], rgb[1], rgb[2]);
+      bg_layer_colors[l] = CV_RGB_LEGACY(rgb[0], rgb[1], rgb[2]);
       rgb[rgb_idx] += 200;
       rgb[rgb_idx] %= 255;
       rgb_idx++;
@@ -1419,7 +1378,7 @@ void CMultiLayerBGS::GetColoredBgMultiLayeredImage(IplImage *bg_multi_layer_img,
     lbp_idxes = (*PLBP).lbp_idxes;
     bLayeredBg = false;
 
-    if ((*_fg_maskD == 0)) {
+    if (*_fg_maskD == 0) {
       bg_layer_num = LBPs[lbp_idxes[0]].bg_layer_num;
       int first_layer_idx = 0;
       for (c = 0; c < (int)lbp_num; c++) {
@@ -1685,7 +1644,7 @@ void CMultiLayerBGS::GetFloatEdgeImage(IplImage *src, IplImage *dst) {
 
 void CMultiLayerBGS::ExportLogMessage(char *msg) {
   const char *log_fn = "log_message.txt";
-  ofstream fout(log_fn, ios::app);
+  std::ofstream fout(log_fn, std::ios::app);
   if (fout.fail()) {
     printf("Error opening log output file %s.\n", log_fn);
     fout.close();
@@ -1708,7 +1667,7 @@ void CMultiLayerBGS::UpdatePatternColorDistWeights(float *cur_pattern, float *bg
     bg_true_num += (bg_pattern[a] > 0.5f);
     bg_false_num += (bg_pattern[a] < 0.5f);
   }
-  m_fTextureWeight = expf(-(fabsf(cur_true_num - cur_false_num) + fabsf(bg_true_num - bg_false_num) + 0.8f) / (float)m_nLBPLength);
+  m_fTextureWeight = expf(-(std::abs(cur_true_num - cur_false_num) + std::abs(bg_true_num - bg_false_num) + 0.8f) / (float)m_nLBPLength);
   m_fTextureWeight = MAX(MIN(m_fTextureWeight, 0.5f), 0.1f);
   m_fColorWeight = 1.0f - m_fTextureWeight;
 }
@@ -1872,7 +1831,7 @@ void CMultiLayerBGS::Save(const char *bg_model_fn, int save_type) {
 }
 
 bool CMultiLayerBGS::Load(const char *bg_model_fn) {
-  ifstream fin(bg_model_fn, ios::in);
+  std::ifstream fin(bg_model_fn, std::ios::in);
   if (fin.fail()) {
     printf("Error opening background model file %s.\n", bg_model_fn);
     fin.close();
@@ -2148,3 +2107,5 @@ int CMultiLayerBGS::SetForegroundProbImage(IplImage* fg_prob_img) {
 void CMultiLayerBGS::SetCurrentFrameNumber(unsigned long cur_frame_no) {
   m_nCurImgFrameIdx = cur_frame_no;
 }
+
+#endif
diff --git a/src/algorithms/MultiLayer/CMultiLayerBGS.h b/src/algorithms/MultiLayer/CMultiLayerBGS.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bf46309d0c77807b00fa1bb8ee68019e1039cc5
--- /dev/null
+++ b/src/algorithms/MultiLayer/CMultiLayerBGS.h
@@ -0,0 +1,281 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+/*
+Since the used fast cross bilateral filter codes can not be compiled under Windows,
+we don't use the bilateral filter to remove the noise in the foreground detection
+step. If you compile it under Linux, please uncomment it.
+*/
+
+//#define LINUX_BILATERAL_FILTER
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctime>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <cmath>
+#include <iostream>
+
+//#include <opencv2/imgproc.hpp>
+
+// opencv legacy includes
+#include <opencv2/imgproc/imgproc_c.h>
+
+#include "LocalBinaryPattern.h"
+#include "BlobResult.h"
+#include "OpenCvDataConversion.h"
+#include "BackgroundSubtractionAPI.h"
+
+#ifdef LINUX_BILATERAL_FILTER
+#include "CrossBilateralFilter.h"
+#endif
+
+#define CV_RGB_LEGACY(r, g, b) cvScalar((b), (g), (r), 0)
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      class CMultiLayerBGS : public CBackgroundSubtractionAPI
+      {
+      public:
+        //-------------------------------------------------------------
+        // TO CALL AT INITIALISATION: DEFINES THE SIZE OF THE INPUT IMAGES
+        // NORMALLY, UNNECESSARY IF A CONFIGURATION FILE IS LOADED
+        void   Init(int width, int height);
+
+        //-------------------------------------------------------------
+        // PROVIDE A MASK TO DEFINE THE SET OF POINTS WHERE BACKGROUND
+        // SUBTRACTION DOES NOT NEED TO BE PERFORMED
+        //
+        //  mode is useful to specify if the points to remove from
+        //  processing are in addition to the ones potentially
+        //  removed according to the configuration file,
+        //  or if they are the only ones to be removed
+        //
+        // mode=0 : provided points need to be removed
+        //          in addition to those already removed
+        // mode=1 : the provided points are the only one to remove
+        //          from processing
+        // Note:  maskImage(li,co)=0 indicate the points to remove
+        //       from background processing
+        void   SetValidPointMask(IplImage* maskImage, int mode);
+
+        //-------------------------------------------------------------
+        //
+        //   set the frame rate, to adjust the update parameters
+        //   to the actual frame rate.
+        //   Can be called only once at initialisation,
+        //   but in online cases, can be used to indicate
+        //   the time interval during the last processed frame
+        //
+        //   frameDuration is in millisecond
+        void   SetFrameRate(float    frameDuration);
+
+        //-------------------------------------------------------------
+        //
+        //   set some main parameters for background model learning.
+        //   in general, we can set large updating rates for background
+        //   model learning and set small updating rates in foreground
+        //   detection
+        void SetParameters(int max_lbp_mode_num,		// maximal LBP mode number
+          float mode_updating_learn_rate_per_second,	// background mode updating learning rate per second
+          float weight_updating_learn_rate_per_second,	// mode's weight updating learning rate per second
+          float low_init_mode_weight);			// the low initial mode weight
+
+      //-------------------------------------------------------------
+      //   PROVIDE A POINTER TO THE INPUT IMAGE
+      //   -> INDICATE WHERE THE NEW IMAGE TO PROCESS IS STORED
+      //
+      //   Here assumes that the input image will contain RGB images.
+      //   The memory of this image is handled by the caller.
+      //
+      //    The return value indicate whether the actual Background
+      //    Subtraction algorithm handles RGB images (1) or not (0).
+      //
+        int   SetRGBInputImage(IplImage  *  inputImage, CvRect *roi = NULL);
+
+        //-------------------------------------------------------------
+        //   PROVIDE A POINTER TO THE RESULT IMAGE
+        //   INDICATE WHERE THE BACKGROUND RESULT NEED TO BE STORED
+        //
+        int SetForegroundMaskImage(IplImage* fg_mask_img);
+        int SetForegroundProbImage(IplImage* fg_prob_img);
+
+        //-------------------------------------------------------------
+        // This function should be called each time a new image is
+        // available in the input image.
+        //
+        // The return value is 0 if everything goes well, a non-zero value
+        // otherwise.
+        //
+        int   Process();
+
+        //-------------------------------------------------------------
+        // this function should save parameters and information of the model
+        // (e.g. after a training of the model, or in such a way
+        // that the model can be reload to process the next frame
+        // type of save:
+        //	0 - background model information (pixel by pixel)
+        //	1 - background model parameters
+        //	2 - both background information (pixel by pixel) and parameters
+        void   Save(const char   *bg_model_fn, int save_type);
+        void   Save(const char* bg_model_fn);
+
+        //-------------------------------------------------------------
+        // this function should load the parameters necessary
+        // for the processing of the background subtraction or
+        // load background model information
+        bool   Load(const char  *bg_model_fn);
+
+
+        void SetCurrentFrameNumber(unsigned long cur_frame_no);
+
+        void GetForegroundMaskImage(IplImage *fg_mask_img);
+        void GetForegroundImage(IplImage *fg_img, CvScalar bg_color = CV_RGB_LEGACY(0, 255, 0));
+        void GetBackgroundImage(IplImage *bk_img);
+        void GetForegroundProbabilityImage(IplImage* fg_prob_img);
+
+        void GetBgLayerNoImage(IplImage *bg_layer_no_img, CvScalar* layer_colors = NULL, int layer_num = 0);
+        void GetLayeredBackgroundImage(int layered_no, IplImage *layered_bg_img, CvScalar empty_color = CV_RGB_LEGACY(0, 0, 0));
+        void GetCurrentLayeredBackgroundImage(int layered_no, IplImage *layered_bg_img, IplImage *layered_fg_img = NULL,
+          CvScalar layered_bg_bk_color = CV_RGB_LEGACY(0, 0, 0), CvScalar layered_fg_color = CV_RGB_LEGACY(255, 0, 0),
+          int smooth_win = 13, float smooth_sigma = 3.0f, float below_layer_noise = 0.5f, float above_layer_noise = 0.3f, int min_blob_size = 50);
+        float DistLBP(LBPStruct *LBP1, LBPStruct *LBP2);
+        void GetColoredBgMultiLayeredImage(IplImage *bg_multi_layer_img, CvScalar *layer_colors);
+        void UpdatePatternColorDistWeights(float *cur_pattern, float *bg_pattern);
+        void ExportLogMessage(char* msg);
+        void Postprocessing();
+        void GetFloatEdgeImage(IplImage *src, IplImage *dst);
+        void RemoveBackgroundLayers(PixelLBPStruct *PLBP, bool *removed_modes = NULL);
+        float CalColorRangeDist(unsigned char *cur_intensity, float *bg_intensity, float *max_intensity,
+          float *min_intensity, float shadow_rate, float highlight_rate);
+        float CalVectorsAngle(float *c1, unsigned char *c2, int length);
+        float CalVectorsNoisedAngle(float *bg_color, unsigned char *noised_color, float offset, int length);
+        void ComputeGradientImage(IplImage *src, IplImage *dst, bool bIsFloat);
+        float CalColorBgDist(uchar *cur_intensity, float *bg_intensity, float *max_intensity, float *min_intensity);
+        float CalPatternBgDist(float *cur_pattern, float *bg_pattern);
+
+        void GetForegroundMaskMap(CvMat *fg_mask_mat);
+        void Initialization(IplImage *first_img, int lbp_level_num, float *radiuses, int *neig_pt_nums);
+        void GetCurrentBackgroundDistMap(CvMat *bk_dist_map);
+        void BackgroundSubtractionProcess();
+        void SetBkMaskImage(IplImage *mask_img);
+        void SetNewImage(IplImage *new_img, CvRect *roi = NULL);
+
+        void ResetAllParameters();
+        void QuickSort(float *pData, unsigned short *pIdxes, long low, long high, bool bAscent);
+        void UpdateBgPixelPattern(float *cur_pattern, float *bg_bg_pattern);
+        void UpdateBgPixelColor(unsigned char* cur_intensity, float* bg_intensity);
+        void Update_MAX_MIN_Intensity(unsigned char *cur_intensity, float *max_intensity, float *min_intensity);
+        void MergeImages(int num, ...);
+
+        int	m_nChannel;				/* most of opencv functions support 1,2,3 or 4 channels, for the input images */
+
+        PixelLBPStruct*	m_pPixelLBPs;			/* the LBP texture patterns for each image */
+        int	m_nMaxLBPModeNum;			/* the maximal number for the used LBP pattern models */
+        float	m_fModeUpdatingLearnRate;		/* the background mode learning rate */
+        float	m_fWeightUpdatingLearnRate;		/* the background mode weight updating rate */
+        float	m_f1_ModeUpdatingLearnRate;		/* 1 - background_mode_learning_rate */
+        float	m_f1_WeightUpdatingLearnRate;		/* 1 - background_mode_weight_updating_rate */
+        float	m_fRobustColorOffset;			/* the intensity offset robust to noise */
+        float	m_fLowInitialModeWeight;		/* the lowest weight of initial background mode */
+        int	m_nLBPLength;				/* the length of texture LBP operator */
+        float	m_fPatternColorDistBgThreshold;		/* the threshold value used to classify background and foreground */
+        float	m_fPatternColorDistBgUpdatedThreshold;	/* the threshold value used to update the background modeling */
+        float	m_fMinBgLayerWeight;			/* the minimal weight to remove background layers */
+
+        int	m_nPatternDistSmoothNeigHalfSize;	/* the neighboring half size of gaussian window to remove the noise
+                                              on the distance map */
+        float	m_fPatternDistConvGaussianSigma;	/* the gaussian sigma used to remove the noise on the distance map */
+
+        float	m_fBackgroundModelPercent;		/* the background mode percent, the first several background modes
+                                            with high mode weights should be regarded as reliable background modes */
+
+        float	m_fRobustShadowRate;			/* the minimal shadow rate, [0.4, 0.7] */
+        float	m_fRobustHighlightRate;			/* the maximal highlight rate, [1.1, 1.4] */
+
+        int	m_nLBPImgNum;				/* the number of images used for texture LBP feature */
+
+        float	m_fMinLBPBinaryProb;			/* the minimal LBP binary probability */
+        float	m_f1_MinLBPBinaryProb;			/* 1 - minimal_LBP_binary_probability */
+
+        CvSize	m_cvImgSize;				/* the image size (width, height) */
+
+        unsigned long	m_nCurImgFrameIdx;			/* the frame index of current image */
+
+        bool	m_bUsedGradImage;			/* the boolean variable signaling whether the gradient image is used
+                                    or not for computing LBP operator */
+
+        bool	m_bUsedColorLBP;			/* true - multi-channel color image for LBP operator,
+                                    false - gray-scale image for LBP operator  */
+
+        CLocalBinaryPattern	m_cLBP;			/* the class instant for computing LBP (local binary pattern) texture feature */
+
+        IplImage* m_pBkMaskImg;				/* the mask image corresponding to the input image,
+                                      i.e. all the masked pixels should be processed  */
+
+        IplImage* m_pOrgImg;				/* the original image */
+        IplImage** m_ppOrgLBPImgs;			/* the multi-layer images used for LBP feature extraction */
+        IplImage* m_pFgImg;				/* the foreground image */
+        IplImage* m_pBgImg;				/* the background image */
+        IplImage* m_pFgMaskImg;				/* the foreground mask image */
+        IplImage* m_pBgDistImg;				/* the background distance image (float) */
+        IplImage* m_pEdgeImg;				/* the edge image used for cross bilateral filter */
+        IplImage* m_pFgProbImg;				/* the foreground probability image (uchar) */
+
+        IplImage* m_pFirstAppearingTimeMap;
+
+      #ifdef LINUX_BILATERAL_FILTER
+        CCrossBilateralFilter	m_cCrossBF;		/* the class instant for cross bilateral filter
+                                            which should be used to remove noise on the distance map */
+      #endif
+
+        bool	m_disableLearning;
+        float	m_fSigmaS;				/* sigma in the spatial domain for cross bilateral filter */
+        float	m_fSigmaR;				/* sigma in the normalized intensity domain for cross bilateral filter */
+
+        float	m_fTextureWeight;			/* the weight value of texture LBP feature
+                                    for background modeling & foreground detection */
+
+        float	m_fColorWeight;				/* the weight value of color invariant feature
+                                    for background modeling & foreground detection */
+
+        float	m_fWeightUpdatingConstant;		/* the constant ( >= 1 ) for 'hysteries' weight updating scheme
+                                            (increase when matched, decrease when un-matched */
+
+        float	m_fReliableBackgroundModeWeight;	/* the weight value for background mode
+                                                which should be regarded as a reliable background mode,
+                                                which is useful for multi-layer scheme */
+
+        float	m_fMinNoisedAngle;			/* the minimal angle value between the background color
+                                      and the noised observed color */
+
+        float	m_fMinNoisedAngleSine;			/* the minimal angle sine value between the background color
+                                          and the noised observed color */
+
+        float	m_fFrameDuration;			/* frame duration */
+
+        float	m_fModeUpdatingLearnRatePerSecond;
+        float	m_fWeightUpdatingLearnRatePerSecond;
+
+        int m_nLBPLevelNum;
+        float m_pLBPRadiuses[10];
+        int m_pLBPMeigPointNums[10];
+
+        CvRect* m_pROI;
+        CMultiLayerBGS();
+        virtual ~CMultiLayerBGS();
+      };
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/MultiLayer/LocalBinaryPattern.cpp b/src/algorithms/MultiLayer/LocalBinaryPattern.cpp
similarity index 72%
rename from package_bgs/MultiLayer/LocalBinaryPattern.cpp
rename to src/algorithms/MultiLayer/LocalBinaryPattern.cpp
index 060b9ea959af92ea290fe056b88457963c6fae0d..89e53381c45815197e395aa992f37446c1d70258 100644
--- a/package_bgs/MultiLayer/LocalBinaryPattern.cpp
+++ b/src/algorithms/MultiLayer/LocalBinaryPattern.cpp
@@ -1,57 +1,11 @@
-/*
-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/>.
-*/
-/* --- --- ---
-* Copyright (C) 2008--2010 Idiap Research Institute (.....@idiap.ch)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-*    derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-// LocalBinaryPattern.cpp: implementation of the CLocalBinaryPattern class.
-//
-//////////////////////////////////////////////////////////////////////
-
 #include "LocalBinaryPattern.h"
 
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
 
-CLocalBinaryPattern::CLocalBinaryPattern()
-{
+using namespace bgslibrary::algorithms::multilayer;
+
+CLocalBinaryPattern::CLocalBinaryPattern() {
   m_ppOrgImgs = NULL;
   m_pRadiuses = NULL;
   m_fRobustWhiteNoise = 3.0f;
@@ -60,26 +14,20 @@ CLocalBinaryPattern::CLocalBinaryPattern()
   m_pShiftedImg = NULL;
 }
 
-CLocalBinaryPattern::~CLocalBinaryPattern()
-{
+CLocalBinaryPattern::~CLocalBinaryPattern() {
   FreeMemories();
 }
 
 void CLocalBinaryPattern::Initialization(IplImage **first_imgs, int imgs_num, int level_num, float *radius, int *neig_pt_num, float robust_white_noise, int type)
 {
-
   m_nImgsNum = imgs_num;
-
   m_nLBPLevelNum = level_num;
-
   m_pRadiuses = new float[m_nLBPLevelNum];
   m_pNeigPointsNums = new int[m_nLBPLevelNum];
   m_ppOrgImgs = first_imgs;
-
   int a, b;
   for (a = 0; a < m_nImgsNum; a++) {
     m_cvImgSize = cvGetSize(first_imgs[a]);
-
     if (first_imgs[a]->nChannels > 1) {
       printf("Input image channel must be 1!");
       exit(1);
@@ -98,9 +46,7 @@ void CLocalBinaryPattern::Initialization(IplImage **first_imgs, int imgs_num, in
   }
 
   m_pShiftedImg = cvCloneImage(m_ppOrgImgs[0]);
-
   m_pXYShifts = new CvPoint[tot_neig_pts_num];
-
   m_nMaxShift.x = 0;
   m_nMaxShift.y = 0;
   int shift_idx = 0;
@@ -308,3 +254,4 @@ void CLocalBinaryPattern::CalImageDifferenceMap(IplImage *cent_img, IplImage *ne
 
 }
 
+#endif
diff --git a/src/algorithms/MultiLayer/LocalBinaryPattern.h b/src/algorithms/MultiLayer/LocalBinaryPattern.h
new file mode 100644
index 0000000000000000000000000000000000000000..23d96368c301df4c7d76408f167acf297a1c9310
--- /dev/null
+++ b/src/algorithms/MultiLayer/LocalBinaryPattern.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include <cstdio>
+
+#include "BGS.h"
+#include "OpenCvDataConversion.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      /************************************************************************/
+      /* two types of computing the LBP operators but currently GENERAL_LBP   */
+      /* has been implemented.                                                */
+      /************************************************************************/
+      const int	GENERAL_LBP = 0;
+      const int SYMMETRIC_LBP = 1;
+
+      class CLocalBinaryPattern
+      {
+      public:
+        void CalImageDifferenceMap(IplImage *cent_img, IplImage *neig_img, float *pattern, CvRect *roi = NULL);
+        void CalNeigPixelOffset(float radius, int tot_neig_pts_num, int neig_pt_idx, int &offset_x, int &offset_y);
+        void CalShiftedImage(IplImage *src, int offset_x, int offset_y, IplImage *dst, CvRect *roi = NULL);
+        void FreeMemories();
+        void ComputeLBP(PixelLBPStruct *PLBP, CvRect *roi = NULL);
+        void SetNewImages(IplImage **new_imgs);
+
+        IplImage** m_ppOrgImgs;			/* the original images used for computing the LBP operators */
+
+        void Initialization(IplImage **first_imgs, int imgs_num,
+          int level_num, float *radius, int *neig_pt_num,
+          float robust_white_noise = 3.0f, int type = GENERAL_LBP);
+
+        CLocalBinaryPattern();
+        virtual ~CLocalBinaryPattern();
+
+        float	m_fRobustWhiteNoise;		/* the robust noise value for computing the LBP operator in each channel */
+
+      private:
+        void SetShiftedMeshGrid(CvSize img_size, float offset_x, float offset_y, CvMat *grid_map_x, CvMat *grid_map_y);
+
+        float*	m_pRadiuses;			/* the circle radiuses for the LBP operator */
+        //int	m_nLBPType;			/* the type of computing LBP operator */
+        int*	m_pNeigPointsNums;		/* the numbers of neighboring pixels on multi-level circles */
+        int	m_nImgsNum;			/* the number of multi-channel image */
+        int	m_nLBPLevelNum;			/* the number of multi-level LBP operator */
+        CvSize	m_cvImgSize;			/* the image size (width, height) */
+
+        CvPoint* m_pXYShifts;
+        CvPoint	m_nMaxShift;
+
+        IplImage* m_pShiftedImg;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/OpenCvDataConversion.h b/src/algorithms/MultiLayer/OpenCvDataConversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..76af1d5d35435eee44b1619089eeaf87b7f7a4fa
--- /dev/null
+++ b/src/algorithms/MultiLayer/OpenCvDataConversion.h
@@ -0,0 +1,190 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include <stdio.h>
+
+// opencv legacy includes
+#include "OpenCvLegacyIncludes.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      template <class TI, class TM>		/* class TI - the type of image data, class TM - the type of matrix data */
+      class COpencvDataConversion
+      {
+      public:
+
+        /* get the image data */
+        TI * GetImageData(IplImage *img)
+        {
+          if (!img->roi) {	/* no ROI used, i.e. the whole image */
+            int y; //, x;
+            TI* img_data = new TI[img->width*img->height*img->nChannels];
+            TI* temp = img_data;
+            TI* x_data;
+
+            for (y = 0; y < img->height; y++) {
+              x_data = (TI*)(img->imageData + img->widthStep*y);
+              int row_length = img->width*img->nChannels;
+              memcpy(temp, x_data, sizeof(TI)*row_length);
+              temp += row_length;
+              /*
+              for ( x = 0 ; x < img->width*img->nChannels ; x++ )
+              *temp++ = *x_data++;
+              */
+            }
+
+            return img_data;
+          }
+          else {	/* get image data only in ROI */
+            int y;//, x;
+            TI* img_data = new TI[img->roi->width*img->roi->height*img->nChannels];
+            TI* temp = img_data;
+            TI* x_data;
+            for (y = img->roi->yOffset; y < img->roi->yOffset + img->roi->height; y++) {
+              x_data = (TI*)(img->imageData + img->widthStep*y + img->roi->xOffset*sizeof(TI)*img->nChannels);
+              int row_length = img->roi->width*img->nChannels;
+              memcpy(temp, x_data, sizeof(TI)*row_length);
+              temp += row_length;
+              /*
+              for ( x = 0 ; x < img->roi->width*img->nChannels ; x++ )
+              *temp++ = *x_data++;
+              */
+            }
+            return img_data;
+          }
+        };
+
+        /* set the image data */
+        void SetImageData(IplImage *img, TI *img_data)
+        {
+          if (!img->roi) {	/* no ROI used, i.e. the whole image */
+            int y;//, x;
+            TI* temp = img_data;
+            TI* x_data;
+            for (y = 0; y < img->height; y++) {
+              x_data = (TI*)(img->imageData + img->widthStep*y);
+              int row_length = img->width*img->nChannels;
+              memcpy(x_data, temp, sizeof(TI)*row_length);
+              temp += row_length;
+              /*
+              for ( x = 0 ; x < img->width*img->nChannels ; x++ )
+              *x_data++ = *temp++;
+              */
+            }
+          }
+          else {	/* set image data only in ROI */
+            int y;//, x;
+            TI* temp = img_data;
+            TI* x_data;
+            for (y = img->roi->yOffset; y < img->roi->yOffset + img->roi->height; y++) {
+              x_data = (TI*)(img->imageData + img->widthStep*y + img->roi->xOffset*sizeof(TI)*img->nChannels);
+              int row_length = img->roi->width*img->nChannels;
+              memcpy(x_data, temp, sizeof(TI)*row_length);
+              temp += row_length;
+              /*
+              for ( x = 0 ; x < img->roi->width*img->nChannels ; x++ )
+              *x_data++ = *temp++;
+              */
+            }
+          }
+        }
+
+        /* get the matrix data */
+        TM * GetMatData(CvMat *mat)
+        {
+          TM* mat_data = new TM[mat->width*mat->height];
+          memcpy(mat_data, mat->data.ptr, sizeof(TM)*mat->width*mat->height);
+          return mat_data;
+
+          /*
+          int y, x;
+          TM* mat_data = new TM[mat->width*mat->height];
+          TM* temp = mat_data;
+          TM* x_data;
+          for ( y = 0 ; y < mat->height ; y++ ) {
+          x_data = (TM*)(mat->data.ptr + mat->step*y);
+          for ( x = 0 ; x < mat->width ; x++ )
+          *temp++ = *x_data++;
+          }
+          return mat_data;
+          */
+        };
+
+        /* set the matrix data */
+        void SetMatData(CvMat *mat, TM *mat_data)
+        {
+          memcpy(mat->data.ptr, mat_data, sizeof(TM)*mat->width*mat->height);
+
+          /*
+          int y, x;
+          TM* temp = mat_data;
+          TM* x_data;
+          for ( y = 0 ; y < mat->height ; y++ ) {
+          x_data = (TM*)(mat->data.ptr + mat->step*y);
+          for ( x = 0 ; x < mat->width ; x++ )
+          *x_data++ = *temp++;
+          }
+          */
+        }
+
+        /* convert the image data to the matrix data */
+        void ConvertData(IplImage *img_src, CvMat *mat_dst)
+        {
+          if (img_src->nChannels > 1) {
+            printf("Must be one-channel image for ConvertImageData!\n");
+            exit(1);
+          }
+
+          TI* _img_data = GetImageData(img_src);
+          TM* _mat_data = new TM[img_src->width*img_src->height];
+
+          TI* img_data = _img_data;
+          TM* mat_data = _mat_data;
+          int i;
+          for (i = 0; i < img_src->width*img_src->height; i++)
+            *mat_data++ = (TM)(*img_data++);
+
+          SetMatData(mat_dst, _mat_data);
+
+          delete[] _img_data;
+          delete[] _mat_data;
+        }
+
+        /* convert the matrix data to the image data */
+        void ConvertData(CvMat *mat_src, IplImage *img_dst)
+        {
+          if (img_dst->nChannels > 1) {
+            printf("Must be one-channel image for ConvertImageData!\n");
+            exit(1);
+          }
+
+          TM* _mat_data = GetMatData(mat_src);
+          TI* _img_data = new TI[mat_src->width*mat_src->height];
+
+          TM* mat_data = _mat_data;
+          TI* img_data = _img_data;
+
+          int i;
+          for (i = 0; i < mat_src->width*mat_src->height; i++)
+            *img_data++ = (TI)(*mat_data++);
+
+          SetImageData(img_dst, _img_data);
+
+          delete[] _img_data;
+          delete[] _mat_data;
+        }
+
+        COpencvDataConversion() {};
+        virtual ~COpencvDataConversion() {};
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/OpenCvLegacyIncludes.h b/src/algorithms/MultiLayer/OpenCvLegacyIncludes.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c2e5409342da270145c13f97c566d68b6073015
--- /dev/null
+++ b/src/algorithms/MultiLayer/OpenCvLegacyIncludes.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+// opencv legacy includes
+#include "opencv2/core/core_c.h"
+#include "opencv2/imgproc/imgproc_c.h"
+
+#endif
diff --git a/src/algorithms/MultiLayer/blob.cpp b/src/algorithms/MultiLayer/blob.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..64b4f642939938b53c0db301563148026e0e14c2
--- /dev/null
+++ b/src/algorithms/MultiLayer/blob.cpp
@@ -0,0 +1,1099 @@
+#include <limits.h>
+#include "blob.h"
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        /**
+          - FUNCIÓ: CBlob
+          - FUNCIONALITAT: Constructor estàndard
+          - PARÀMETRES:
+          - RESULTAT:
+          - inicialització de totes les variables internes i de l'storage i la sequencia
+          per a les cantonades del blob
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlob
+            - FUNCTIONALITY: Standard constructor
+            - PARAMETERS:
+            - RESULT:
+            - memory allocation for the blob edges and initialization of member variables
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlob::CBlob()
+        {
+          etiqueta = -1;		// Flag indicates null region
+          exterior = 0;
+          area = 0.0f;
+          perimeter = 0.0f;
+          parent = -1;
+          minx = LONG_MAX;
+          maxx = 0;
+          miny = LONG_MAX;
+          maxy = 0;
+          sumx = 0;
+          sumy = 0;
+          sumxx = 0;
+          sumyy = 0;
+          sumxy = 0;
+          mean = 0;
+          stddev = 0;
+          externPerimeter = 0;
+
+          m_storage = cvCreateMemStorage(0);
+          edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
+            sizeof(CvContour),
+            sizeof(CvPoint), m_storage);
+        }
+
+        /**
+          - FUNCIÓ: CBlob
+          - FUNCIONALITAT: Constructor de còpia
+          - PARÀMETRES:
+          - RESULTAT:
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlob
+            - FUNCTIONALITY: Copy constructor
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlob::CBlob(const CBlob &src)
+        {
+          // copiem les propietats del blob origen a l'actual
+          etiqueta = src.etiqueta;
+          exterior = src.exterior;
+          area = src.Area();
+          perimeter = src.Perimeter();
+          parent = src.parent;
+          minx = src.minx;
+          maxx = src.maxx;
+          miny = src.miny;
+          maxy = src.maxy;
+          sumx = src.sumx;
+          sumy = src.sumy;
+          sumxx = src.sumxx;
+          sumyy = src.sumyy;
+          sumxy = src.sumxy;
+          mean = src.mean;
+          stddev = src.stddev;
+          externPerimeter = src.externPerimeter;
+
+          // copiem els edges del blob origen a l'actual
+          CvSeqReader reader;
+          CvSeqWriter writer;
+          CvPoint edgeactual;
+
+          // creem una sequencia buida per als edges
+          m_storage = cvCreateMemStorage(0);
+          edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
+            sizeof(CvContour),
+            sizeof(CvPoint), m_storage);
+
+          cvStartReadSeq(src.Edges(), &reader);
+          cvStartAppendToSeq(edges, &writer);
+
+          for (int i = 0; i < src.Edges()->total; i++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            CV_WRITE_SEQ_ELEM(edgeactual, writer);
+          }
+
+          cvEndWriteSeq(&writer);
+        }
+        CBlob::CBlob(const CBlob *src)
+        {
+          // copiem les propietats del blob origen a l'actual
+          etiqueta = src->etiqueta;
+          exterior = src->exterior;
+          area = src->Area();
+          perimeter = src->Perimeter();
+          parent = src->parent;
+          minx = src->minx;
+          maxx = src->maxx;
+          miny = src->miny;
+          maxy = src->maxy;
+          sumx = src->sumx;
+          sumy = src->sumy;
+          sumxx = src->sumxx;
+          sumyy = src->sumyy;
+          sumxy = src->sumxy;
+          mean = src->mean;
+          stddev = src->stddev;
+          externPerimeter = src->externPerimeter;
+
+          // copiem els edges del blob origen a l'actual
+          CvSeqReader reader;
+          CvSeqWriter writer;
+          CvPoint edgeactual;
+
+          // creem una sequencia buida per als edges
+          m_storage = cvCreateMemStorage(0);
+          edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
+            sizeof(CvContour),
+            sizeof(CvPoint), m_storage);
+
+          cvStartReadSeq(src->Edges(), &reader);
+          cvStartAppendToSeq(edges, &writer);
+
+          for (int i = 0; i < src->Edges()->total; i++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            CV_WRITE_SEQ_ELEM(edgeactual, writer);
+          }
+
+          cvEndWriteSeq(&writer);
+        }
+
+        /**
+          - FUNCIÓ: ~CBlob
+          - FUNCIONALITAT: Destructor estàndard
+          - PARÀMETRES:
+          - RESULTAT:
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlob
+            - FUNCTIONALITY: Standard destructor
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlob::~CBlob()
+        {
+          // Eliminar vèrtexs del blob
+          cvClearSeq(edges);
+          // i la zona de memòria on són
+          cvReleaseMemStorage(&m_storage);
+        }
+
+        /**
+          - FUNCIÓ: operator=
+          - FUNCIONALITAT: Operador d'assignació
+          - PARÀMETRES:
+          - src: blob a assignar a l'actual
+          - RESULTAT:
+          - Substitueix el blob actual per el src
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: Assigment operator
+            - FUNCTIONALITY: Assigns a blob to the current
+            - PARAMETERS:
+            - src: blob to assign
+            - RESULT:
+            - the current blob is replaced by the src blob
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CBlob& CBlob::operator=(const CBlob &src)
+        {
+          // si ja són el mateix, no cal fer res
+          if (this != &src)
+          {
+            // Eliminar vèrtexs del blob
+            cvClearSeq(edges);
+            // i la zona de memòria on són
+            cvReleaseMemStorage(&m_storage);
+
+            // creem una sequencia buida per als edges
+            m_storage = cvCreateMemStorage(0);
+            edges = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2,
+              sizeof(CvContour),
+              sizeof(CvPoint), m_storage);
+
+            // copiem les propietats del blob origen a l'actual
+            etiqueta = src.etiqueta;
+            exterior = src.exterior;
+            area = src.Area();
+            perimeter = src.Perimeter();
+            parent = src.parent;
+            minx = src.minx;
+            maxx = src.maxx;
+            miny = src.miny;
+            maxy = src.maxy;
+            sumx = src.sumx;
+            sumy = src.sumy;
+            sumxx = src.sumxx;
+            sumyy = src.sumyy;
+            sumxy = src.sumxy;
+            mean = src.mean;
+            stddev = src.stddev;
+            externPerimeter = src.externPerimeter;
+
+            // copiem els edges del blob origen a l'actual
+            CvSeqReader reader;
+            CvSeqWriter writer;
+            CvPoint edgeactual;
+
+            cvStartReadSeq(src.Edges(), &reader);
+            cvStartAppendToSeq(edges, &writer);
+
+            for (int i = 0; i < src.Edges()->total; i++)
+            {
+              CV_READ_SEQ_ELEM(edgeactual, reader);
+              CV_WRITE_SEQ_ELEM(edgeactual, writer);
+            }
+
+            cvEndWriteSeq(&writer);
+          }
+          return *this;
+        }
+
+        /**
+          - FUNCIÓ: FillBlob
+          - FUNCIONALITAT: Pinta l'interior d'un blob amb el color especificat
+          - PARÀMETRES:
+          - imatge: imatge on es vol pintar el el blob
+          - color: color amb que es vol pintar el blob
+          - RESULTAT:
+          - retorna la imatge d'entrada amb el blob pintat
+          - RESTRICCIONS:
+          - AUTOR:
+          - Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: FillBlob
+            - FUNCTIONALITY:
+            - Fills the blob with a specified colour
+            - PARAMETERS:
+            - imatge: where to paint
+            - color: colour to paint the blob
+            - RESULT:
+            - modifies input image and returns the seed point used to fill the blob
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlob::FillBlob(IplImage *imatge, CvScalar color, int offsetX /*=0*/, int offsetY /*=0*/) const
+        {
+
+          //verifiquem que existeixi el blob i que tingui cantonades
+          if (edges == NULL || edges->total == 0) return;
+
+          CvPoint edgeactual, pt1, pt2;
+          CvSeqReader reader;
+          vectorPunts vectorEdges = vectorPunts(edges->total);
+          vectorPunts::iterator itEdges, itEdgesSeguent;
+          bool dinsBlob;
+          int yActual;
+
+          // passem els punts del blob a un vector de punts de les STL
+          cvStartReadSeq(edges, &reader);
+          itEdges = vectorEdges.begin();
+          while (itEdges != vectorEdges.end())
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            *itEdges = edgeactual;
+            ++itEdges;
+          }
+          // ordenem el vector per les Y's i les X's d'esquerra a dreta
+          std::sort(vectorEdges.begin(), vectorEdges.end(), comparaCvPoint());
+
+          // recorrem el vector ordenat i fem linies entre punts consecutius
+          itEdges = vectorEdges.begin();
+          itEdgesSeguent = vectorEdges.begin() + 1;
+          dinsBlob = true;
+          while (itEdges != (vectorEdges.end() - 1))
+          {
+            yActual = (*itEdges).y;
+
+            if (((*itEdges).x != (*itEdgesSeguent).x) &&
+              ((*itEdgesSeguent).y == yActual)
+              )
+            {
+              if (dinsBlob)
+              {
+                pt1 = *itEdges;
+                pt1.x += offsetX;
+                pt1.y += offsetY;
+
+                pt2 = *itEdgesSeguent;
+                pt2.x += offsetX;
+                pt2.y += offsetY;
+
+                cvLine(imatge, pt1, pt2, color);
+              }
+              dinsBlob = !dinsBlob;
+            }
+            ++itEdges;
+            ++itEdgesSeguent;
+            if ((*itEdges).y != yActual) dinsBlob = true;
+          }
+          vectorEdges.clear();
+        }
+
+        /**
+          - FUNCIÓ: CopyEdges
+          - FUNCIONALITAT: Afegeix els vèrtexs del blob al blob destination
+          - PARÀMETRES:
+          - destination: blob al que volem afegir els vèrtexs
+          - RESULTAT:
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CopyEdges
+            - FUNCTIONALITY: Adds the blob edges to destination
+            - PARAMETERS:
+            - destination: where to add the edges
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlob::CopyEdges(CBlob &destination) const
+        {
+          CvSeqReader reader;
+          CvSeqWriter writer;
+          CvPoint edgeactual;
+
+          cvStartReadSeq(edges, &reader);
+          cvStartAppendToSeq(destination.Edges(), &writer);
+
+          for (int i = 0; i < edges->total; i++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            CV_WRITE_SEQ_ELEM(edgeactual, writer);
+          }
+
+          cvEndWriteSeq(&writer);
+        }
+
+        /**
+          - FUNCIÓ: ClearEdges
+          - FUNCIONALITAT: Elimina els vèrtexs del blob
+          - PARÀMETRES:
+          - RESULTAT:
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: ClearEdges
+            - FUNCTIONALITY: Delete current blob edges
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        void CBlob::ClearEdges()
+        {
+          // Eliminar vèrtexs del blob eliminat
+          cvClearSeq(edges);
+        }
+
+        /**
+          - FUNCIÓ: GetConvexHull
+          - FUNCIONALITAT: Retorna el poligon convex del blob
+          - PARÀMETRES:
+          - dst: sequencia on desarem el resultat (no ha d'estar inicialitzada)
+          - RESULTAT:
+          - true si tot ha anat bé
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: GetConvexHull
+            - FUNCTIONALITY: Calculates the convex hull polygon of the blob
+            - PARAMETERS:
+            - dst: where to store the result
+            - RESULT:
+            - true if no error ocurred
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        bool CBlob::GetConvexHull(CvSeq **dst) const
+        {
+          if (edges != NULL && edges->total > 0)
+          {
+            *dst = cvConvexHull2(edges, 0, CV_CLOCKWISE, 0);
+            return true;
+          }
+          return false;
+        }
+
+        /**
+          - FUNCIÓ: GetEllipse
+          - FUNCIONALITAT: Retorna l'ellipse que s'ajusta millor a les cantonades del blob
+          - PARÀMETRES:
+          - RESULTAT:
+          - estructura amb l'ellipse
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 25-05-2005.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: GetEllipse
+            - FUNCTIONALITY: Calculates the ellipse that best fits the edges of the blob
+            - PARAMETERS:
+            - RESULT:
+            - CvBox2D struct with the calculated ellipse
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        CvBox2D CBlob::GetEllipse() const
+        {
+          CvBox2D elipse;
+          // necessitem 6 punts per calcular l'elipse
+          if (edges != NULL && edges->total > 6)
+          {
+            elipse = cvFitEllipse2(edges);
+          }
+          else
+          {
+            elipse.center.x = 0.0;
+            elipse.center.y = 0.0;
+            elipse.size.width = 0.0;
+            elipse.size.height = 0.0;
+            elipse.angle = 0.0;
+          }
+          return elipse;
+        }
+
+
+
+        /***************************************************************************
+          Implementació de les classes per al càlcul de característiques sobre el blob
+
+          Implementation of the helper classes to perform operations on blobs
+          **************************************************************************/
+
+          /**
+            - FUNCIÓ: Moment
+            - FUNCIONALITAT: Calcula el moment pq del blob
+            - RESULTAT:
+            - retorna el moment pq especificat o 0 si el moment no està implementat
+            - RESTRICCIONS:
+            - Implementats els moments pq: 00, 01, 10, 20, 02
+            - AUTOR: Ricard Borràs
+            - DATA DE CREACIÓ: 20-07-2004.
+            - MODIFICACIÓ: Data. Autor. Descripció.
+            */
+            /**
+              - FUNCTION: Moment
+              - FUNCTIONALITY: Calculates the pq moment of the blob
+              - PARAMETERS:
+              - RESULT:
+              - returns the pq moment or 0 if the moment it is not implemented
+              - RESTRICTIONS:
+              - Currently, only implemented the 00, 01, 10, 20, 02 pq moments
+              - AUTHOR: Ricard Borràs
+              - CREATION DATE: 20-07-2004.
+              - MODIFICATION: Date. Author. Description.
+              */
+        double CBlobGetMoment::operator()(const CBlob &blob) const
+        {
+          //Moment 00
+          if ((m_p == 0) && (m_q == 0))
+            return blob.Area();
+
+          //Moment 10
+          if ((m_p == 1) && (m_q == 0))
+            return blob.SumX();
+
+          //Moment 01
+          if ((m_p == 0) && (m_q == 1))
+            return blob.SumY();
+
+          //Moment 20
+          if ((m_p == 2) && (m_q == 0))
+            return blob.SumXX();
+
+          //Moment 02
+          if ((m_p == 0) && (m_q == 2))
+            return blob.SumYY();
+
+          return 0;
+        }
+
+        /**
+          - FUNCIÓ: HullPerimeter
+          - FUNCIONALITAT: Calcula la longitud del perimetre convex del blob.
+          Fa servir la funció d'OpenCV cvConvexHull2 per a
+          calcular el perimetre convex.
+
+          - PARÀMETRES:
+          - RESULTAT:
+          - retorna la longitud del perímetre convex del blob. Si el blob no té coordenades
+          associades retorna el perímetre normal del blob.
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobGetHullPerimeter
+            - FUNCTIONALITY: Calculates the convex hull perimeter of the blob
+            - PARAMETERS:
+            - RESULT:
+            - returns the convex hull perimeter of the blob or the perimeter if the
+            blob edges could not be retrieved
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetHullPerimeter::operator()(const CBlob &blob) const
+        {
+          if (blob.Edges() != NULL && blob.Edges()->total > 0)
+          {
+            CvSeq *hull = cvConvexHull2(blob.Edges(), 0, CV_CLOCKWISE, 1);
+            return fabs(cvArcLength(hull, CV_WHOLE_SEQ, 1));
+          }
+          return blob.Perimeter();
+        }
+
+        double CBlobGetHullArea::operator()(const CBlob &blob) const
+        {
+          if (blob.Edges() != NULL && blob.Edges()->total > 0)
+          {
+            CvSeq *hull = cvConvexHull2(blob.Edges(), 0, CV_CLOCKWISE, 1);
+            return fabs(cvContourArea(hull));
+          }
+          return blob.Perimeter();
+        }
+
+        /**
+          - FUNCIÓ: MinX_at_MinY
+          - FUNCIONALITAT: Calcula el valor MinX a MinY.
+          - PARÀMETRES:
+          - blob: blob del que volem calcular el valor
+          - RESULTAT:
+          - retorna la X minima en la Y minima.
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobGetMinXatMinY
+            - FUNCTIONALITY: Calculates the minimum X on the minimum Y
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetMinXatMinY::operator()(const CBlob &blob) const
+        {
+          double MinX_at_MinY = LONG_MAX;
+
+          CvSeqReader reader;
+          CvPoint edgeactual;
+
+          cvStartReadSeq(blob.Edges(), &reader);
+
+          for (int j = 0; j < blob.Edges()->total; j++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            if ((edgeactual.y == blob.MinY()) && (edgeactual.x < MinX_at_MinY))
+            {
+              MinX_at_MinY = edgeactual.x;
+            }
+          }
+
+          return MinX_at_MinY;
+        }
+
+        /**
+          - FUNCIÓ: MinY_at_MaxX
+          - FUNCIONALITAT: Calcula el valor MinX a MaxX.
+          - PARÀMETRES:
+          - blob: blob del que volem calcular el valor
+          - RESULTAT:
+          - retorna la Y minima en la X maxima.
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobGetMinXatMinY
+            - FUNCTIONALITY: Calculates the minimum Y on the maximum X
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetMinYatMaxX::operator()(const CBlob &blob) const
+        {
+          double MinY_at_MaxX = LONG_MAX;
+
+          CvSeqReader reader;
+          CvPoint edgeactual;
+
+          cvStartReadSeq(blob.Edges(), &reader);
+
+          for (int j = 0; j < blob.Edges()->total; j++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            if ((edgeactual.x == blob.MaxX()) && (edgeactual.y < MinY_at_MaxX))
+            {
+              MinY_at_MaxX = edgeactual.y;
+            }
+          }
+
+          return MinY_at_MaxX;
+        }
+
+        /**
+          - FUNCIÓ: MaxX_at_MaxY
+          - FUNCIONALITAT: Calcula el valor MaxX a MaxY.
+          - PARÀMETRES:
+          - blob: blob del que volem calcular el valor
+          - RESULTAT:
+          - retorna la X maxima en la Y maxima.
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobGetMaxXatMaxY
+            - FUNCTIONALITY: Calculates the maximum X on the maximum Y
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetMaxXatMaxY::operator()(const CBlob &blob) const
+        {
+          double MaxX_at_MaxY = LONG_MIN;
+
+          CvSeqReader reader;
+          CvPoint edgeactual;
+
+          cvStartReadSeq(blob.Edges(), &reader);
+
+          for (int j = 0; j < blob.Edges()->total; j++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            if ((edgeactual.y == blob.MaxY()) && (edgeactual.x > MaxX_at_MaxY))
+            {
+              MaxX_at_MaxY = edgeactual.x;
+            }
+          }
+
+          return MaxX_at_MaxY;
+        }
+
+        /**
+          - FUNCIÓ: MaxY_at_MinX
+          - FUNCIONALITAT: Calcula el valor MaxY a MinX.
+          - PARÀMETRES:
+          - blob: blob del que volem calcular el valor
+          - RESULTAT:
+          - retorna la Y maxima en la X minima.
+          - RESTRICCIONS:
+          - AUTOR: Ricard Borràs
+          - DATA DE CREACIÓ: 20-07-2004.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: CBlobGetMaxYatMinX
+            - FUNCTIONALITY: Calculates the maximum Y on the minimum X
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetMaxYatMinX::operator()(const CBlob &blob) const
+        {
+          double MaxY_at_MinX = LONG_MIN;
+
+          CvSeqReader reader;
+          CvPoint edgeactual;
+
+          cvStartReadSeq(blob.Edges(), &reader);
+
+          for (int j = 0; j < blob.Edges()->total; j++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            if ((edgeactual.x == blob.MinY()) && (edgeactual.y > MaxY_at_MinX))
+            {
+              MaxY_at_MinX = edgeactual.y;
+            }
+          }
+
+          return MaxY_at_MinX;
+        }
+
+        /**
+          Retorna l'elongació del blob (longitud/amplada)
+          */
+          /**
+            - FUNCTION: CBlobGetElongation
+            - FUNCTIONALITY: Calculates the elongation of the blob ( length/breadth )
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - See below to see how the lenght and the breadth are aproximated
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetElongation::operator()(const CBlob &blob) const
+        {
+          double ampladaC, longitudC, amplada, longitud;
+
+          ampladaC = (double)(blob.Perimeter() + sqrt(pow(blob.Perimeter(), 2) - 16 * blob.Area())) / 4;
+          if (ampladaC <= 0.0) return 0;
+          longitudC = (double)blob.Area() / ampladaC;
+
+          longitud = MAX(longitudC, ampladaC);
+          amplada = MIN(longitudC, ampladaC);
+
+          return (double)longitud / amplada;
+        }
+
+        /**
+          Retorna la compacitat del blob
+          */
+          /**
+            - FUNCTION: CBlobGetCompactness
+            - FUNCTIONALITY: Calculates the compactness of the blob
+            ( maximum for circle shaped blobs, minimum for the rest)
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetCompactness::operator()(const CBlob &blob) const
+        {
+          if (blob.Area() != 0.0)
+            return (double)pow(blob.Perimeter(), 2) / (4 * CV_PI*blob.Area());
+          else
+            return 0.0;
+        }
+
+        /**
+          Retorna la rugositat del blob
+          */
+          /**
+            - FUNCTION: CBlobGetRoughness
+            - FUNCTIONALITY: Calculates the roughness of the blob
+            ( ratio between perimeter and convex hull perimeter)
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetRoughness::operator()(const CBlob &blob) const
+        {
+          CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter();
+
+          double hullPerimeter = getHullPerimeter(blob);
+
+          if (hullPerimeter != 0.0)
+            return blob.Perimeter() / hullPerimeter;//HullPerimeter();
+
+          return 0.0;
+        }
+
+        /**
+          Retorna la longitud del blob
+          */
+          /**
+            - FUNCTION: CBlobGetLength
+            - FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the blob)
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - The lenght is an aproximation to the real lenght
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetLength::operator()(const CBlob &blob) const
+        {
+          double ampladaC, longitudC;
+          double tmp;
+
+          tmp = blob.Perimeter()*blob.Perimeter() - 16 * blob.Area();
+
+          if (tmp > 0.0)
+            ampladaC = (double)(blob.Perimeter() + sqrt(tmp)) / 4;
+          // error intrínsec en els càlculs de l'àrea i el perímetre
+          else
+            ampladaC = (double)(blob.Perimeter()) / 4;
+
+          if (ampladaC <= 0.0) return 0;
+          longitudC = (double)blob.Area() / ampladaC;
+
+          return MAX(longitudC, ampladaC);
+        }
+
+        /**
+          Retorna l'amplada del blob
+          */
+          /**
+            - FUNCTION: CBlobGetBreadth
+            - FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the blob)
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - The breadth is an aproximation to the real breadth
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetBreadth::operator()(const CBlob &blob) const
+        {
+          double ampladaC, longitudC;
+          double tmp;
+
+          tmp = blob.Perimeter()*blob.Perimeter() - 16 * blob.Area();
+
+          if (tmp > 0.0)
+            ampladaC = (double)(blob.Perimeter() + sqrt(tmp)) / 4;
+          // error intrínsec en els càlculs de l'àrea i el perímetre
+          else
+            ampladaC = (double)(blob.Perimeter()) / 4;
+
+          if (ampladaC <= 0.0) return 0;
+          longitudC = (double)blob.Area() / ampladaC;
+
+          return MIN(longitudC, ampladaC);
+        }
+
+        /**
+          Calcula la distància entre un punt i el centre del blob
+          */
+          /**
+            - FUNCTION: CBlobGetDistanceFromPoint
+            - FUNCTIONALITY: Calculates the euclidean distance between the blob center and
+            the point specified in the constructor
+            - PARAMETERS:
+            - RESULT:
+            - RESTRICTIONS:
+            - AUTHOR: Ricard Borràs
+            - CREATION DATE: 25-05-2005.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetDistanceFromPoint::operator()(const CBlob &blob) const
+        {
+          double xmitjana, ymitjana;
+          CBlobGetXCenter getXCenter;
+          CBlobGetYCenter getYCenter;
+
+          xmitjana = m_x - getXCenter(blob);
+          ymitjana = m_y - getYCenter(blob);
+
+          return sqrt((xmitjana*xmitjana) + (ymitjana*ymitjana));
+        }
+
+        /**
+          - FUNCIÓ: BlobGetXYInside
+          - FUNCIONALITAT: Calcula si un punt cau dins de la capsa rectangular
+          del blob
+          - RESULTAT:
+          - retorna 1 si hi està; 0 si no
+          - RESTRICCIONS:
+          - AUTOR: Francesc Pinyol Margalef
+          - DATA DE CREACIÓ: 16-01-2006.
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+          /**
+            - FUNCTION: BlobGetXYInside
+            - FUNCTIONALITY: Calculates whether a point is inside the
+            rectangular bounding box of a blob
+            - PARAMETERS:
+            - RESULT:
+            - returns 1 if it is inside; o if not
+            - RESTRICTIONS:
+            - AUTHOR: Francesc Pinyol Margalef
+            - CREATION DATE: 16-01-2006.
+            - MODIFICATION: Date. Author. Description.
+            */
+        double CBlobGetXYInside::operator()(const CBlob &blob) const
+        {
+          if (blob.Edges() == NULL || blob.Edges()->total == 0) return 0.0;
+
+          // passem els punts del blob a un vector de punts de les STL
+          CvSeqReader reader;
+          CBlob::vectorPunts vectorEdges;
+          CBlob::vectorPunts::iterator itEdges, itEdgesSeguent;
+          CvPoint edgeactual;
+          bool dinsBlob;
+
+          // agafem tots els punts amb la mateixa y que l'actual
+          cvStartReadSeq(blob.Edges(), &reader);
+
+          for (int i = 0; i < blob.Edges()->total; i++)
+          {
+            CV_READ_SEQ_ELEM(edgeactual, reader);
+            if (edgeactual.y == m_p.y)
+              vectorEdges.push_back(edgeactual);
+          }
+
+          if (vectorEdges.empty()) return 0.0;
+
+          // ordenem el vector per les Y's i les X's d'esquerra a dreta
+          std::sort(vectorEdges.begin(), vectorEdges.end(), CBlob::comparaCvPoint());
+
+          // recorrem el punts del blob de la mateixa fila que el punt d'entrada
+          // i mirem si la X del punt d'entrada està entre dos coordenades "plenes"
+          // del blob
+          itEdges = vectorEdges.begin();
+          itEdgesSeguent = vectorEdges.begin() + 1;
+          dinsBlob = true;
+
+          while (itEdges != (vectorEdges.end() - 1))
+          {
+            if ((*itEdges).x <= m_p.x && (*itEdgesSeguent).x >= m_p.x && dinsBlob)
+            {
+              vectorEdges.clear();
+              return 1.0;
+            }
+
+            ++itEdges;
+            ++itEdgesSeguent;
+            dinsBlob = !dinsBlob;
+          }
+
+          vectorEdges.clear();
+          return 0.0;
+        }
+
+      #ifdef BLOB_OBJECT_FACTORY
+        /**
+          - FUNCIÓ: RegistraTotsOperadors
+          - FUNCIONALITAT: Registrar tots els operadors definits a blob.h
+          - PARÀMETRES:
+          - fabricaOperadorsBlob: fàbrica on es registraran els operadors
+          - RESULTAT:
+          - Modifica l'objecte fabricaOperadorsBlob
+          - RESTRICCIONS:
+          - Només es registraran els operadors de blob.h. Si se'n volen afegir, cal afegir-los amb
+          el mètode Register de la fàbrica.
+          - AUTOR: rborras
+          - DATA DE CREACIÓ: 2006/05/18
+          - MODIFICACIÓ: Data. Autor. Descripció.
+          */
+        void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob)
+        {
+          // blob shape
+          fabricaOperadorsBlob.Register(CBlobGetArea().GetNom(), Type2Type<CBlobGetArea>());
+          fabricaOperadorsBlob.Register(CBlobGetBreadth().GetNom(), Type2Type<CBlobGetBreadth>());
+          fabricaOperadorsBlob.Register(CBlobGetCompactness().GetNom(), Type2Type<CBlobGetCompactness>());
+          fabricaOperadorsBlob.Register(CBlobGetElongation().GetNom(), Type2Type<CBlobGetElongation>());
+          fabricaOperadorsBlob.Register(CBlobGetExterior().GetNom(), Type2Type<CBlobGetExterior>());
+          fabricaOperadorsBlob.Register(CBlobGetLength().GetNom(), Type2Type<CBlobGetLength>());
+          fabricaOperadorsBlob.Register(CBlobGetPerimeter().GetNom(), Type2Type<CBlobGetPerimeter>());
+          fabricaOperadorsBlob.Register(CBlobGetRoughness().GetNom(), Type2Type<CBlobGetRoughness>());
+
+          // extern pixels
+          fabricaOperadorsBlob.Register(CBlobGetExternPerimeterRatio().GetNom(), Type2Type<CBlobGetExternPerimeterRatio>());
+          fabricaOperadorsBlob.Register(CBlobGetExternHullPerimeterRatio().GetNom(), Type2Type<CBlobGetExternHullPerimeterRatio>());
+          fabricaOperadorsBlob.Register(CBlobGetExternPerimeter().GetNom(), Type2Type<CBlobGetExternPerimeter>());
+
+
+          // hull
+          fabricaOperadorsBlob.Register(CBlobGetHullPerimeter().GetNom(), Type2Type<CBlobGetHullPerimeter>());
+          fabricaOperadorsBlob.Register(CBlobGetHullArea().GetNom(), Type2Type<CBlobGetHullArea>());
+
+
+          // elipse info
+          fabricaOperadorsBlob.Register(CBlobGetMajorAxisLength().GetNom(), Type2Type<CBlobGetMajorAxisLength>());
+          fabricaOperadorsBlob.Register(CBlobGetMinorAxisLength().GetNom(), Type2Type<CBlobGetMinorAxisLength>());
+          fabricaOperadorsBlob.Register(CBlobGetAxisRatio().GetNom(), Type2Type<CBlobGetAxisRatio>());
+          fabricaOperadorsBlob.Register(CBlobGetOrientation().GetNom(), Type2Type<CBlobGetOrientation>());
+          fabricaOperadorsBlob.Register(CBlobGetOrientationCos().GetNom(), Type2Type<CBlobGetOrientationCos>());
+          fabricaOperadorsBlob.Register(CBlobGetAreaElipseRatio().GetNom(), Type2Type<CBlobGetAreaElipseRatio>());
+
+          // min an max
+          fabricaOperadorsBlob.Register(CBlobGetMaxX().GetNom(), Type2Type<CBlobGetMaxX>());
+          fabricaOperadorsBlob.Register(CBlobGetMaxY().GetNom(), Type2Type<CBlobGetMaxY>());
+          fabricaOperadorsBlob.Register(CBlobGetMinX().GetNom(), Type2Type<CBlobGetMinX>());
+          fabricaOperadorsBlob.Register(CBlobGetMinY().GetNom(), Type2Type<CBlobGetMinY>());
+
+          fabricaOperadorsBlob.Register(CBlobGetMaxXatMaxY().GetNom(), Type2Type<CBlobGetMaxXatMaxY>());
+          fabricaOperadorsBlob.Register(CBlobGetMaxYatMinX().GetNom(), Type2Type<CBlobGetMaxYatMinX>());
+          fabricaOperadorsBlob.Register(CBlobGetMinXatMinY().GetNom(), Type2Type<CBlobGetMinXatMinY>());
+          fabricaOperadorsBlob.Register(CBlobGetMinYatMaxX().GetNom(), Type2Type<CBlobGetMinYatMaxX>());
+
+          // grey level stats
+          fabricaOperadorsBlob.Register(CBlobGetMean().GetNom(), Type2Type<CBlobGetMean>());
+          fabricaOperadorsBlob.Register(CBlobGetStdDev().GetNom(), Type2Type<CBlobGetStdDev>());
+
+          // coordinate info
+          fabricaOperadorsBlob.Register(CBlobGetXYInside().GetNom(), Type2Type<CBlobGetXYInside>());
+          fabricaOperadorsBlob.Register(CBlobGetDiffY().GetNom(), Type2Type<CBlobGetDiffY>());
+          fabricaOperadorsBlob.Register(CBlobGetDiffX().GetNom(), Type2Type<CBlobGetDiffX>());
+          fabricaOperadorsBlob.Register(CBlobGetXCenter().GetNom(), Type2Type<CBlobGetXCenter>());
+          fabricaOperadorsBlob.Register(CBlobGetYCenter().GetNom(), Type2Type<CBlobGetYCenter>());
+          fabricaOperadorsBlob.Register(CBlobGetDistanceFromPoint().GetNom(), Type2Type<CBlobGetDistanceFromPoint>());
+
+          // moments
+          fabricaOperadorsBlob.Register(CBlobGetMoment().GetNom(), Type2Type<CBlobGetMoment>());
+
+        }
+      #endif
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/MultiLayer/blob.h b/src/algorithms/MultiLayer/blob.h
new file mode 100644
index 0000000000000000000000000000000000000000..b80c5730eb7cabd25b0bef0b8febc50192610399
--- /dev/null
+++ b/src/algorithms/MultiLayer/blob.h
@@ -0,0 +1,797 @@
+#pragma once
+
+#include <functional>
+#include <vector>
+#include <algorithm>
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "BlobLibraryConfiguration.h"
+// opencv legacy includes
+#include "OpenCvLegacyIncludes.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace multilayer
+    {
+      namespace blob
+      {
+        //! Factor de conversió de graus a radians
+        const double DEGREE2RAD = (CV_PI / 180.0);
+
+        /**
+          Classe que representa un blob, entés com un conjunt de pixels del
+          mateix color contigus en una imatge binaritzada.
+
+          Class to represent a blob, a group of connected pixels in a binary image
+          */
+        class CBlob
+        {
+        public:
+          //! Constructor estàndard
+          //! Standard constructor
+          CBlob();
+          //! Constructor de còpia
+          //! Copy constructor
+          CBlob(const CBlob &src);
+          CBlob(const CBlob *src);
+
+          //! Destructor estàndard
+          //! Standard Destructor
+          ~CBlob();
+
+          //! Operador d'assignació
+          //! Assigment operator
+          CBlob& operator=(const CBlob &src);
+
+          //! Indica si el blob està buit ( no té cap info associada )
+          //! Shows if the blob has associated information
+          bool IsEmpty() const
+          {
+            return (area == 0.0 && perimeter == 0.0);
+          };
+
+          //! Neteja les cantonades del blob
+          //! Clears the edges of the blob
+          void ClearEdges();
+          //! Copia les cantonades del blob a un altre (les afegeix al destí)
+          //! Adds the blob edges to another blob
+          void CopyEdges(CBlob &destination) const;
+          //! Retorna el poligon convex del blob
+          //! Calculates the convex hull of the blob
+          bool GetConvexHull(CvSeq **dst) const;
+          //! Calcula l'elipse que s'adapta als vèrtexs del blob
+          //! Fits an ellipse to the blob edges
+          CvBox2D GetEllipse() const;
+
+          //! Pinta l'interior d'un blob d'un color determinat
+          //! Paints the blob in an image
+          void FillBlob(IplImage *imatge, CvScalar color, int offsetX = 0, int offsetY = 0) const;
+
+          //! Funcions GET sobre els valors dels blobs
+          //! Get functions
+
+          inline int Label() const { return etiqueta; }
+          inline int Parent() const { return parent; }
+          inline double Area() const { return area; }
+          inline double Perimeter() const { return perimeter; }
+          inline double ExternPerimeter() const { return externPerimeter; }
+          inline int	  Exterior() const { return exterior; }
+          inline double Mean() const { return mean; }
+          inline double StdDev() const { return stddev; }
+          inline double MinX() const { return minx; }
+          inline double MinY() const { return miny; }
+          inline double MaxX() const { return maxx; }
+          inline double MaxY() const { return maxy; }
+          inline CvSeq *Edges() const { return edges; }
+          inline double SumX() const { return sumx; }
+          inline double SumY() const { return sumy; }
+          inline double SumXX() const { return sumxx; }
+          inline double SumYY() const { return sumyy; }
+          inline double SumXY() const { return sumxy; }
+
+          //! etiqueta del blob
+          //! label of the blob
+          int etiqueta;
+          //! flag per indicar si es exterior o no
+          //! true for extern blobs
+          int exterior;
+          //! area del blob
+          //! Blob area
+          double area;
+          //! perimetre del blob
+          //! Blob perimeter
+          double perimeter;
+          //! quantitat de perimetre del blob extern
+          //! amount of blob perimeter which is exterior
+          double externPerimeter;
+          //! etiqueta del blob pare
+          //! label of the parent blob
+          int parent;
+          //! moments
+          double sumx;
+          double sumy;
+          double sumxx;
+          double sumyy;
+          double sumxy;
+          //! Bounding rect
+          double minx;
+          double maxx;
+          double miny;
+          double maxy;
+
+          //! mitjana
+          //! mean of the grey scale values of the blob pixels
+          double mean;
+          //! desviació standard
+          //! standard deviation of the grey scale values of the blob pixels
+          double stddev;
+
+          //! àrea de memòria on es desaran els punts de contorn del blob
+          //! storage which contains the edges of the blob
+          CvMemStorage *m_storage;
+          //!	Sequència de punts del contorn del blob
+          //! Sequence with the edges of the blob
+          CvSeq *edges;
+
+
+          //! Point datatype for plotting (FillBlob)
+          typedef std::vector<CvPoint> vectorPunts;
+
+          //! Helper class to compare two CvPoints (for sorting in FillBlob)
+          struct comparaCvPoint : public std::binary_function<CvPoint, CvPoint, bool>
+          {
+            //! Definim que un punt és menor com més amunt a la dreta estigui
+            bool operator()(CvPoint a, CvPoint b)
+            {
+              if (a.y == b.y)
+                return a.x < b.x;
+              else
+                return a.y < b.y;
+            }
+          };
+        };
+
+
+
+        /**************************************************************************
+          Definició de les classes per a fer operacions sobre els blobs
+
+          Helper classes to perform operations on blobs
+          **************************************************************************/
+
+
+          //! Classe d'on derivarem totes les operacions sobre els blobs
+          //! Interface to derive all blob operations
+        class COperadorBlob
+        {
+        public:
+          virtual ~COperadorBlob() {};
+
+          //! Aplica l'operació al blob
+          virtual double operator()(const CBlob &blob) const = 0;
+          //! Obté el nom de l'operador
+          virtual const char *GetNom() const = 0;
+
+          operator COperadorBlob*() const
+          {
+            return (COperadorBlob*)this;
+          }
+        };
+
+        typedef COperadorBlob funcio_calculBlob;
+
+      #ifdef BLOB_OBJECT_FACTORY
+        /**
+          Funció per comparar dos identificadors dins de la fàbrica de COperadorBlobs
+          */
+        struct functorComparacioIdOperador
+        {
+          bool operator()(const char* s1, const char* s2) const
+          {
+            return strcmp(s1, s2) < 0;
+          }
+        };
+
+        //! Definition of Object factory type for COperadorBlob objects
+        typedef ObjectFactory<COperadorBlob, const char *, functorComparacioIdOperador > t_OperadorBlobFactory;
+
+        //! Funció global per a registrar tots els operadors definits a blob.h
+        void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob);
+
+      #endif
+
+        //! Classe per calcular l'àrea d'un blob
+        //! Class to get the area of a blob
+        class CBlobGetArea : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.Area();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetArea";
+          }
+        };
+
+        //! Classe per calcular el perimetre d'un blob
+        //! Class to get the perimeter of a blob
+        class CBlobGetPerimeter : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.Perimeter();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetPerimeter";
+          }
+        };
+
+        //! Classe que diu si un blob és extern o no
+        //! Class to get the extern flag of a blob
+        class CBlobGetExterior : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.Exterior();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetExterior";
+          }
+        };
+
+        //! Classe per calcular la mitjana de nivells de gris d'un blob
+        //! Class to get the mean grey level of a blob
+        class CBlobGetMean : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.Mean();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMean";
+          }
+        };
+
+        //! Classe per calcular la desviació estàndard dels nivells de gris d'un blob
+        //! Class to get the standard deviation of the grey level values of a blob
+        class CBlobGetStdDev : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.StdDev();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetStdDev";
+          }
+        };
+
+        //! Classe per calcular la compacitat d'un blob
+        //! Class to calculate the compactness of a blob
+        class CBlobGetCompactness : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetCompactness";
+          }
+        };
+
+        //! Classe per calcular la longitud d'un blob
+        //! Class to calculate the length of a blob
+        class CBlobGetLength : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetLength";
+          }
+        };
+
+        //! Classe per calcular l'amplada d'un blob
+        //! Class to calculate the breadth of a blob
+        class CBlobGetBreadth : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetBreadth";
+          }
+        };
+
+        //! Classe per calcular la diferència en X del blob
+        class CBlobGetDiffX : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.maxx - blob.minx;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetDiffX";
+          }
+        };
+
+        //! Classe per calcular la diferència en X del blob
+        class CBlobGetDiffY : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.maxy - blob.miny;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetDiffY";
+          }
+        };
+
+        //! Classe per calcular el moment PQ del blob
+        //! Class to calculate the P,Q moment of a blob
+        class CBlobGetMoment : public COperadorBlob
+        {
+        public:
+          //! Constructor estàndard
+          //! Standard constructor (gets the 00 moment)
+          CBlobGetMoment()
+          {
+            m_p = m_q = 0;
+          }
+          //! Constructor: indiquem el moment p,q a calcular
+          //! Constructor: gets the PQ moment
+          CBlobGetMoment(int p, int q)
+          {
+            m_p = p;
+            m_q = q;
+          };
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetMoment";
+          }
+
+        private:
+          //! moment que volem calcular
+          int m_p, m_q;
+        };
+
+        //! Classe per calcular el perimetre del poligon convex d'un blob
+        //! Class to calculate the convex hull perimeter of a blob
+        class CBlobGetHullPerimeter : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetHullPerimeter";
+          }
+        };
+
+        //! Classe per calcular l'àrea del poligon convex d'un blob
+        //! Class to calculate the convex hull area of a blob
+        class CBlobGetHullArea : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetHullArea";
+          }
+        };
+
+        //! Classe per calcular la x minima en la y minima
+        //! Class to calculate the minimum x on the minimum y
+        class CBlobGetMinXatMinY : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetMinXatMinY";
+          }
+        };
+
+        //! Classe per calcular la y minima en la x maxima
+        //! Class to calculate the minimum y on the maximum x
+        class CBlobGetMinYatMaxX : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetMinYatMaxX";
+          }
+        };
+
+        //! Classe per calcular la x maxima en la y maxima
+        //! Class to calculate the maximum x on the maximum y
+        class CBlobGetMaxXatMaxY : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetMaxXatMaxY";
+          }
+        };
+
+        //! Classe per calcular la y maxima en la x minima
+        //! Class to calculate the maximum y on the minimum y
+        class CBlobGetMaxYatMinX : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetMaxYatMinX";
+          }
+        };
+
+        //! Classe per a calcular la x mínima
+        //! Class to get the minimum x
+        class CBlobGetMinX : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MinX();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMinX";
+          }
+        };
+
+        //! Classe per a calcular la x màxima
+        //! Class to get the maximum x
+        class CBlobGetMaxX : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MaxX();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMaxX";
+          }
+        };
+
+        //! Classe per a calcular la y mínima
+        //! Class to get the minimum y
+        class CBlobGetMinY : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MinY();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMinY";
+          }
+        };
+
+        //! Classe per a calcular la y màxima
+        //! Class to get the maximum y
+        class CBlobGetMaxY : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MaxY();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMax";
+          }
+        };
+
+
+        //! Classe per calcular l'elongacio d'un blob
+        //! Class to calculate the elongation of the blob
+        class CBlobGetElongation : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetElongation";
+          }
+        };
+
+        //! Classe per calcular la rugositat d'un blob
+        //! Class to calculate the roughness of the blob
+        class CBlobGetRoughness : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetRoughness";
+          }
+        };
+
+        //! Classe per calcular la distància entre el centre del blob i un punt donat
+        //! Class to calculate the euclidean distance between the center of a blob and a given point
+        class CBlobGetDistanceFromPoint : public COperadorBlob
+        {
+        public:
+          //! Standard constructor (distance to point 0,0)
+          CBlobGetDistanceFromPoint()
+          {
+            m_x = m_y = 0.0;
+          }
+          //! Constructor (distance to point x,y)
+          CBlobGetDistanceFromPoint(const double x, const double y)
+          {
+            m_x = x;
+            m_y = y;
+          }
+
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetDistanceFromPoint";
+          }
+
+        private:
+          // coordenades del punt on volem calcular la distància
+          double m_x, m_y;
+        };
+
+        //! Classe per calcular el nombre de pixels externs d'un blob
+        //! Class to get the number of extern pixels of a blob
+        class CBlobGetExternPerimeter : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.ExternPerimeter();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetExternPerimeter";
+          }
+        };
+
+        //! Classe per calcular el ratio entre el perimetre i nombre pixels externs
+        //! valors propers a 0 indiquen que la majoria del blob és intern
+        //! valors propers a 1 indiquen que la majoria del blob és extern
+        //! Class to calculate the ratio between the perimeter and the number of extern pixels
+        class CBlobGetExternPerimeterRatio : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            if (blob.Perimeter() != 0)
+              return blob.ExternPerimeter() / blob.Perimeter();
+            else
+              return blob.ExternPerimeter();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetExternPerimeterRatio";
+          }
+        };
+
+        //! Classe per calcular el ratio entre el perimetre convex i nombre pixels externs
+        //! valors propers a 0 indiquen que la majoria del blob és intern
+        //! valors propers a 1 indiquen que la majoria del blob és extern
+        //! Class to calculate the ratio between the perimeter and the number of extern pixels
+        class CBlobGetExternHullPerimeterRatio : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CBlobGetHullPerimeter getHullPerimeter;
+            double hullPerimeter;
+
+            if ((hullPerimeter = getHullPerimeter(blob)) != 0)
+              return blob.ExternPerimeter() / hullPerimeter;
+            else
+              return blob.ExternPerimeter();
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetExternHullPerimeterRatio";
+          }
+        };
+
+        //! Classe per calcular el centre en el eix X d'un blob
+        //! Class to calculate the center in the X direction
+        class CBlobGetXCenter : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MinX() + ((blob.MaxX() - blob.MinX()) / 2.0);
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetXCenter";
+          }
+        };
+
+        //! Classe per calcular el centre en el eix Y d'un blob
+        //! Class to calculate the center in the Y direction
+        class CBlobGetYCenter : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            return blob.MinY() + ((blob.MaxY() - blob.MinY()) / 2.0);
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetYCenter";
+          }
+        };
+
+        //! Classe per calcular la longitud de l'eix major d'un blob
+        //! Class to calculate the length of the major axis of the ellipse that fits the blob edges
+        class CBlobGetMajorAxisLength : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CvBox2D elipse = blob.GetEllipse();
+
+            return elipse.size.width;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMajorAxisLength";
+          }
+        };
+
+        //! Classe per calcular el ratio entre l'area de la elipse i la de la taca
+        //! Class
+        class CBlobGetAreaElipseRatio : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            if (blob.Area() == 0.0) return 0.0;
+
+            CvBox2D elipse = blob.GetEllipse();
+            double ratioAreaElipseAreaTaca = ((elipse.size.width / 2.0)
+              *
+              (elipse.size.height / 2.0)
+              *CV_PI
+              )
+              /
+              blob.Area();
+
+            return ratioAreaElipseAreaTaca;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetAreaElipseRatio";
+          }
+        };
+
+        //! Classe per calcular la longitud de l'eix menor d'un blob
+        //! Class to calculate the length of the minor axis of the ellipse that fits the blob edges
+        class CBlobGetMinorAxisLength : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CvBox2D elipse = blob.GetEllipse();
+
+            return elipse.size.height;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetMinorAxisLength";
+          }
+        };
+
+        //! Classe per calcular l'orientació de l'ellipse del blob en radians
+        //! Class to calculate the orientation of the ellipse that fits the blob edges in radians
+        class CBlobGetOrientation : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CvBox2D elipse = blob.GetEllipse();
+
+            if (elipse.angle > 180.0)
+              return ((elipse.angle - 180.0)* DEGREE2RAD);
+            else
+              return (elipse.angle * DEGREE2RAD);
+
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetOrientation";
+          }
+        };
+
+        //! Classe per calcular el cosinus de l'orientació de l'ellipse del blob
+        //! Class to calculate the cosinus of the orientation of the ellipse that fits the blob edges
+        class CBlobGetOrientationCos : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CBlobGetOrientation getOrientation;
+            return fabs(cos(getOrientation(blob)));
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetOrientationCos";
+          }
+        };
+
+
+        //! Classe per calcular el ratio entre l'eix major i menor de la el·lipse
+        //! Class to calculate the ratio between both axes of the ellipse
+        class CBlobGetAxisRatio : public COperadorBlob
+        {
+        public:
+          double operator()(const CBlob &blob) const
+          {
+            CvBox2D elipse = blob.GetEllipse();
+
+            return elipse.size.height / elipse.size.width;
+          }
+          const char *GetNom() const
+          {
+            return "CBlobGetAxisRatio";
+          }
+        };
+
+
+        //! Classe per calcular si un punt cau dins del blob
+        //! Class to calculate whether a point is inside a blob
+        class CBlobGetXYInside : public COperadorBlob
+        {
+        public:
+          //! Constructor estàndard
+          //! Standard constructor
+          CBlobGetXYInside()
+          {
+            m_p = cvPoint(0, 0);
+          }
+          //! Constructor: indiquem el punt
+          //! Constructor: sets the point
+          CBlobGetXYInside(CvPoint p)
+          {
+            m_p = p;
+          };
+          double operator()(const CBlob &blob) const;
+          const char *GetNom() const
+          {
+            return "CBlobGetXYInside";
+          }
+
+        private:
+          //! punt que considerem
+          //! point to be considered
+          CvPoint m_p;
+        };
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/PAWCS.cpp b/src/algorithms/PAWCS.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aab37c7f239485bc1aa38923de494e4f3a4e7463
--- /dev/null
+++ b/src/algorithms/PAWCS.cpp
@@ -0,0 +1,67 @@
+#include "PAWCS.h"
+
+using namespace bgslibrary::algorithms;
+
+PAWCS::PAWCS() : 
+  IBGS(quote(PAWCS)),
+  pPAWCS(nullptr),
+  fRelLBSPThreshold(lbsp::BGSPAWCS_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
+  nDescDistThresholdOffset(lbsp::BGSPAWCS_DEFAULT_DESC_DIST_THRESHOLD_OFFSET),
+  nMinColorDistThreshold(lbsp::BGSPAWCS_DEFAULT_MIN_COLOR_DIST_THRESHOLD),
+  nMaxNbWords(lbsp::BGSPAWCS_DEFAULT_MAX_NB_WORDS),
+  nSamplesForMovingAvgs(lbsp::BGSPAWCS_DEFAULT_N_SAMPLES_FOR_MV_AVGS)
+{
+  debug_construction(PAWCS);
+  initLoadSaveConfig(algorithmName);
+}
+
+PAWCS::~PAWCS() {
+  debug_destruction(PAWCS);
+  if (pPAWCS)
+    delete pPAWCS;
+}
+
+void PAWCS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    pPAWCS = new lbsp::BackgroundSubtractorPAWCS(
+      fRelLBSPThreshold, nDescDistThresholdOffset, nMinColorDistThreshold,
+      nMaxNbWords, nSamplesForMovingAvgs);
+
+    pPAWCS->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
+    firstTime = false;
+  }
+
+  pPAWCS->apply(img_input, img_foreground);
+  pPAWCS->getBackgroundImage(img_background);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+}
+
+void PAWCS::save_config(cv::FileStorage &fs) {
+  fs << "fRelLBSPThreshold" << fRelLBSPThreshold;
+  fs << "nDescDistThresholdOffset" << nDescDistThresholdOffset;
+  fs << "nMinColorDistThreshold" << nMinColorDistThreshold;
+  fs << "nMaxNbWords" << nMaxNbWords;
+  fs << "nSamplesForMovingAvgs" << nSamplesForMovingAvgs;
+  fs << "showOutput" << showOutput;
+}
+
+void PAWCS::load_config(cv::FileStorage &fs) {
+  fs["fRelLBSPThreshold"] >> fRelLBSPThreshold;
+  fs["nDescDistThresholdOffset"] >> nDescDistThresholdOffset;
+  fs["nMinColorDistThreshold"] >> nMinColorDistThreshold;
+  fs["nMaxNbWords"] >> nMaxNbWords;
+  fs["nSamplesForMovingAvgs"] >> nSamplesForMovingAvgs;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/PAWCS.h b/src/algorithms/PAWCS.h
new file mode 100644
index 0000000000000000000000000000000000000000..737d5db961d1af9429013ad67faafad5b5ce1e99
--- /dev/null
+++ b/src/algorithms/PAWCS.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "IBGS.h"
+#include "LBSP/BackgroundSubtractorPAWCS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class PAWCS : public IBGS
+    {
+    private:
+      lbsp::BackgroundSubtractorPAWCS* pPAWCS;
+
+      float fRelLBSPThreshold;
+      int nDescDistThresholdOffset;
+      int nMinColorDistThreshold;
+      int nMaxNbWords;
+      int nSamplesForMovingAvgs;
+
+    public:
+      PAWCS();
+      ~PAWCS();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(PAWCS);
+  }
+}
diff --git a/package_bgs/PBAS/PBAS.cpp b/src/algorithms/PBAS/PBAS.cpp
similarity index 94%
rename from package_bgs/PBAS/PBAS.cpp
rename to src/algorithms/PBAS/PBAS.cpp
index bc3ad40178d1302ac29860e3ae61b202508a26c0..c024792d7117e58610e772dd741a1303c959019a 100644
--- a/package_bgs/PBAS/PBAS.cpp
+++ b/src/algorithms/PBAS/PBAS.cpp
@@ -1,25 +1,12 @@
-/*
-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 "PBAS.h"
 
-PBAS::PBAS(void) : N(20), R_lower(18), Raute_min(2), T_lower(2), T_upper(200), R_scale(5), R_incdec(0.05), T_dec(0.05), T_inc(1)
-{
-  std::cout << "PBAS()" << std::endl;
+using namespace bgslibrary::algorithms::pbas;
 
+PBAS::PBAS() : 
+  N(20), R_lower(18), Raute_min(2), 
+  T_lower(2), T_upper(200), R_scale(5), 
+  R_incdec(0.05), T_dec(0.05), T_inc(1)
+{
   //feature vector
   alpha = 7.0;
   beta = 1.0;
@@ -77,8 +64,6 @@ void PBAS::newInitialization()
 
 PBAS::~PBAS(void)
 {
-  std::cout << "~PBAS()" << std::endl;
-
   randomN.clear();
   randomX.clear();
   randomY.clear();
diff --git a/src/algorithms/PBAS/PBAS.h b/src/algorithms/PBAS/PBAS.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1c88310066bb82512fbc34b0a7ecf2ded8f589c
--- /dev/null
+++ b/src/algorithms/PBAS/PBAS.h
@@ -0,0 +1,157 @@
+#pragma once
+
+#include <iostream>
+#include <opencv2/opencv.hpp>
+//#include <highgui.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace pbas
+    {
+      class PBAS
+      {
+      public:
+        PBAS(void);
+        ~PBAS(void);
+        bool process(cv::Mat* input, cv::Mat* output);
+
+        void setN(int);
+        void setRaute_min(int);
+        void setR_lower(double);
+        void setR_incdec(double);
+        void setR_scale(double);
+        void setT_init(double);
+        void setT_lower(double);
+        void setT_upper(double);
+        void setT_dec(double);
+        void setT_inc(double);
+        void setAlpha(double);
+        void setBeta(double);
+
+        bool isMovement();
+
+      private:
+        void calculateFeatures(std::vector<cv::Mat>* feature, cv::Mat* inputImage);
+        void checkValid(int *x, int *y);
+        void decisionThresholdRegulator(float* pt, float* meanDistArr);
+        void learningRateRegulator(float* pt, float* meanDist, uchar* isFore);
+        void init(cv::Mat*);
+        void newInitialization();
+
+        cv::Mat meanMinDist;
+        float* meanMinDist_Pt;
+
+        int width, height;
+        int chans;
+
+        //balance of feature pixel value to conture value
+        double alpha, beta;
+        //##################################################################################
+
+        double formerMeanNorm;
+
+        //define value of foreground/background pixels
+        int foregroundValue, backgroundValue;
+
+        //##################################################################################
+        //random number parameters
+
+        //random number generator
+        cv::RNG randomGenerator;
+
+        //length of random array initialization
+        long countOfRandomNumb;
+
+        //pre - initialize the randomNumbers for better performance
+        std::vector<int> randomN, randomMinDist, randomX, randomY, randomT, randomTN;
+
+        //###################################################################################
+
+        //check if something is moving
+        bool isMove;
+
+        //for init, count number of runs
+        int runs;
+
+        cv::Mat* resultMap;
+        std::vector<cv::Mat> currentFeatures;
+
+        std::vector<float*> currentFeaturesM_Pt;
+        std::vector<uchar*> currentFeaturesC_Pt;
+        uchar* resultMap_Pt;
+
+        std::vector<std::vector<float*>>B_Mag_Pts;
+        std::vector<std::vector<uchar*>>B_Col_Pts;
+
+        double sumMagnitude;
+        double formerMeanMag;
+        //float formerDistanceBack;
+
+        //####################################################################################
+        //N - Number: Defining the size of the background-history-model
+        // number of samples per pixel
+        //size of background history B(x_i)
+        int N;
+        // background model
+        std::vector<std::vector<cv::Mat>> backgroundModel;
+        //####################################################################################
+        //####################################################################################
+        //R-Threshhold - Variables
+        //minimal Threshold for foreground and initial value of R(x_i)
+        // radius of the sphere -> lower border boundary
+        double R_lower;
+
+        //factor which defines new threshold of R(x_i) together with meanMinDist(x_i)
+        // scale for the sphere threshhold to define pixel-based Thresholds
+        double R_scale;
+
+        //decreasing / increasing factor of R(x_i)
+        // increasing/decreasing factor for the r-Threshold based on the result of rTreshScale * meanMinDistBackground
+        double R_incdec;
+
+        cv::Mat actualR;
+        float* actualR_Pt; //new pixel-based r-threshhold -> pointer to arrays
+        //#####################################################################################
+        //####################################################################################
+        //counter for minimal distance to background
+        // Defining the number of background-model-images, which have a lowerDIstance to the current Image than defined by the R-Thresholds, that are necessary
+        // to decide that this pixel is background
+        int Raute_min;
+        //#####################################################################################
+        //####################################################################################
+        //initial value of inverse update factor T(x_i)
+        // Initialize the background-model update rate
+        double T_init;
+
+        //increasing Factor of the update rate 1/T(x_i)
+        // scale that defines the increasing of the update rate of the background model, if the current pixel is background
+        //--> more frequently updates if pixel is background because, there shouln't be any change
+        double T_inc;
+
+        //upper boundary of T(x_i)
+        // defining an upper value, that nrSubsampling can achieve, thus it doesn't reach to an infinite value, where actually no update is possible
+        // at all
+        double T_upper;
+
+        //lower boundary of T(x_i)
+        // defining a minimum value for nrSubsampling --> base value 2.0
+        double T_lower;
+
+        //decreasing factor of the update rate 1/T(x_i)
+        // opposite scale to increasingRateScale, for decreasing the update rate of the background model, if the current pixel is foreground
+        //--> Thesis: Our Foreground is a real moving object -> thus the background-model is good, so don't update it
+        double T_dec;
+
+        //holds update rate of current pixel
+        cv::Mat actualT;
+        float* actualT_Pt;
+
+        //#####################################################################################
+
+        cv::Mat sobelX, sobelY;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/PixelBasedAdaptiveSegmenter.cpp b/src/algorithms/PixelBasedAdaptiveSegmenter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c03f734c5256bacee482ad96d38bba41b6cf610d
--- /dev/null
+++ b/src/algorithms/PixelBasedAdaptiveSegmenter.cpp
@@ -0,0 +1,95 @@
+#include "PixelBasedAdaptiveSegmenter.h"
+
+using namespace bgslibrary::algorithms;
+
+PixelBasedAdaptiveSegmenter::PixelBasedAdaptiveSegmenter() :
+  IBGS(quote(PixelBasedAdaptiveSegmenter)),
+  enableInputBlur(true), enableOutputBlur(true),
+  alpha(7.0), beta(1.0), N(20), Raute_min(2), R_incdec(0.05), R_lower(18),
+  R_scale(5), T_dec(0.05), T_inc(1), T_init(18), T_lower(2), T_upper(200)
+{
+  debug_construction(PixelBasedAdaptiveSegmenter);
+  initLoadSaveConfig(algorithmName);
+}
+
+PixelBasedAdaptiveSegmenter::~PixelBasedAdaptiveSegmenter() {
+  debug_destruction(PixelBasedAdaptiveSegmenter);
+}
+
+void PixelBasedAdaptiveSegmenter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    pbas.setAlpha(alpha);
+    pbas.setBeta(beta);
+    pbas.setN(N);
+    pbas.setRaute_min(Raute_min);
+    pbas.setR_incdec(R_incdec);
+    pbas.setR_lower(R_lower);
+    pbas.setR_scale(R_scale);
+    pbas.setT_dec(T_dec);
+    pbas.setT_inc(T_inc);
+    pbas.setT_init(T_init);
+    pbas.setT_lower(T_lower);
+    pbas.setT_upper(T_upper);
+  }
+
+  cv::Mat img_input_new;
+  if (enableInputBlur)
+    cv::GaussianBlur(img_input, img_input_new, cv::Size(5, 5), 1.5);
+  else
+    img_input.copyTo(img_input_new);
+
+  pbas.process(&img_input_new, &img_foreground);
+  img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+  if (enableOutputBlur)
+    cv::medianBlur(img_foreground, img_foreground, 5);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void PixelBasedAdaptiveSegmenter::save_config(cv::FileStorage &fs) {
+  fs << "enableInputBlur" << enableInputBlur;
+  fs << "enableOutputBlur" << enableOutputBlur;
+  fs << "alpha" << alpha;
+  fs << "beta" << beta;
+  fs << "N" << N;
+  fs << "Raute_min" << Raute_min;
+  fs << "R_incdec" << R_incdec;
+  fs << "R_lower" << R_lower;
+  fs << "R_scale" << R_scale;
+  fs << "T_dec" << T_dec;
+  fs << "T_inc" << T_inc;
+  fs << "T_init" << T_init;
+  fs << "T_lower" << T_lower;
+  fs << "T_upper" << T_upper;
+  fs << "showOutput" << showOutput;
+}
+
+void PixelBasedAdaptiveSegmenter::load_config(cv::FileStorage &fs) {
+  fs["enableInputBlur"] >> enableInputBlur;
+  fs["enableOutputBlur"] >> enableOutputBlur;
+  fs["alpha"] >> alpha;
+  fs["beta"] >> beta;
+  fs["N"] >> N;
+  fs["Raute_min"] >> Raute_min;
+  fs["R_incdec"] >> R_incdec;
+  fs["R_lower"] >> R_lower;
+  fs["R_scale"] >> R_scale;
+  fs["T_dec"] >> T_dec;
+  fs["T_inc"] >> T_inc;
+  fs["T_init"] >> T_init;
+  fs["T_lower"] >> T_lower;
+  fs["T_upper"] >> T_upper;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/PixelBasedAdaptiveSegmenter.h b/src/algorithms/PixelBasedAdaptiveSegmenter.h
new file mode 100644
index 0000000000000000000000000000000000000000..02687194013941b9c0dcea056404b9e5bbba45b5
--- /dev/null
+++ b/src/algorithms/PixelBasedAdaptiveSegmenter.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "IBGS.h"
+#include "PBAS/PBAS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class PixelBasedAdaptiveSegmenter : public IBGS
+    {
+    private:
+      pbas::PBAS pbas;
+
+      bool enableInputBlur;
+      bool enableOutputBlur;
+
+      float alpha;
+      float beta;
+      int N;
+      int Raute_min;
+      float R_incdec;
+      int R_lower;
+      int R_scale;
+      float T_dec;
+      int T_inc;
+      int T_init;
+      int T_lower;
+      int T_upper;
+
+    public:
+      PixelBasedAdaptiveSegmenter();
+      ~PixelBasedAdaptiveSegmenter();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(PixelBasedAdaptiveSegmenter);
+  }
+}
diff --git a/src/algorithms/SigmaDelta.cpp b/src/algorithms/SigmaDelta.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1e17b374c32d8eb0f6b65d4889412259471b7c1e
--- /dev/null
+++ b/src/algorithms/SigmaDelta.cpp
@@ -0,0 +1,71 @@
+#include "SigmaDelta.h"
+
+using namespace bgslibrary::algorithms;
+
+SigmaDelta::SigmaDelta() :
+  IBGS(quote(SigmaDelta)),
+  ampFactor(1), minVar(15), maxVar(255), 
+  algorithm(sigmadelta::sdLaMa091New())
+{
+  debug_construction(SigmaDelta);
+  initLoadSaveConfig(algorithmName);
+  applyParams();
+}
+
+SigmaDelta::~SigmaDelta() {
+  debug_destruction(SigmaDelta);
+  sigmadelta::sdLaMa091Free(algorithm);
+}
+
+void SigmaDelta::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    sigmadelta::sdLaMa091AllocInit_8u_C3R(algorithm, img_input.data, img_input.cols, img_input.rows, img_input.step);
+    img_foreground = cv::Mat(img_input.size(), CV_8UC1);
+    img_background = cv::Mat(img_input.size(), CV_8UC3);
+    firstTime = false;
+  }
+  else {
+    cv::Mat img_output_tmp(img_input.rows, img_input.cols, CV_8UC3);
+    sigmadelta::sdLaMa091Update_8u_C3R(algorithm, img_input.data, img_output_tmp.data);
+
+    unsigned char* tmpBuffer = (unsigned char*)img_output_tmp.data;
+    unsigned char* outBuffer = (unsigned char*)img_foreground.data;
+
+    for (size_t i = 0; i < img_foreground.total(); ++i) {
+      *outBuffer = *tmpBuffer;
+      ++outBuffer;
+      tmpBuffer += img_output_tmp.channels();
+    }
+  }
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+}
+
+void SigmaDelta::save_config(cv::FileStorage &fs) {
+  fs << "ampFactor" << ampFactor;
+  fs << "minVar" << minVar;
+  fs << "maxVar" << maxVar;
+  fs << "showOutput" << showOutput;
+}
+
+void SigmaDelta::load_config(cv::FileStorage &fs) {
+  fs["ampFactor"] >> ampFactor;
+  fs["minVar"] >> minVar;
+  fs["maxVar"] >> maxVar;
+  fs["showOutput"] >> showOutput;
+}
+
+void SigmaDelta::applyParams() {
+  sigmadelta::sdLaMa091SetAmplificationFactor(algorithm, ampFactor);
+  sigmadelta::sdLaMa091SetMinimalVariance(algorithm, minVar);
+  sigmadelta::sdLaMa091SetMaximalVariance(algorithm, maxVar);
+}
diff --git a/src/algorithms/SigmaDelta.h b/src/algorithms/SigmaDelta.h
new file mode 100644
index 0000000000000000000000000000000000000000..adb2a9a7a84d9574294f0f43df1a1473a1a45aca
--- /dev/null
+++ b/src/algorithms/SigmaDelta.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+
+//extern "C" {
+#include "SigmaDelta/sdLaMa091.h"
+//}
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class SigmaDelta : public IBGS
+    {
+    private:
+      int ampFactor;
+      int minVar;
+      int maxVar;
+      sigmadelta::sdLaMa091_t* algorithm;
+
+    public:
+      SigmaDelta();
+      ~SigmaDelta();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+      void applyParams();
+    };
+
+    bgs_register(SigmaDelta);
+  }
+}
diff --git a/src/algorithms/SigmaDelta/sdLaMa091.cpp b/src/algorithms/SigmaDelta/sdLaMa091.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..718bfa4107062ceef9d93f804a76a0e77126a7d6
--- /dev/null
+++ b/src/algorithms/SigmaDelta/sdLaMa091.cpp
@@ -0,0 +1,651 @@
+#include "sdLaMa091.h"
+
+//using namespace bgslibrary::algorithms::sigmadelta;
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace sigmadelta
+    {
+      const int DEFAULT_N  = 1;
+      const int DEFAULT_VMIN = 2;
+      const int DEFAULT_VMAX = 255;
+
+      const char* LIB = "sdLaMa091 - ";
+      //const int RED = 0;
+      //const int GREEN = 1;
+      const int BLUE = 2;
+      const int CHANNELS = 3;
+
+      typedef enum {
+        UNKNOWN,
+        C1R,
+        C3R
+      } image_t;
+
+      struct sdLaMa091 {
+        image_t  imageType;
+
+        uint32_t width;
+        uint32_t rgbWidth;
+        uint32_t height;
+        uint32_t stride;
+        uint32_t numBytes;
+        uint32_t unusedBytes;
+        uint32_t rgbUnusedBytes;
+
+        uint32_t N;
+        uint32_t Vmin;
+        uint32_t Vmax;
+
+        uint8_t* Mt;
+        uint8_t* Ot;
+        uint8_t* Vt;
+      };
+
+      #if defined(DEFENSIVE_ALLOC) || defined(DEFENSIVE_POINTER) || \
+        defined(DEFENSIVE_PARAM)
+      static inline void outputError(char* error);
+      #endif
+
+      static inline uint8_t absVal(int8_t num);
+      static inline uint8_t min(uint8_t a, uint8_t b);
+      static inline uint8_t max(uint8_t a, uint8_t b);
+
+      #if defined(DEFENSIVE_ALLOC) || defined(DEFENSIVE_POINTER) || \
+        defined(DEFENSIVE_PARAM)
+
+      static inline void outputError(char* error) {
+        fprintf(stderr, "%s%s\n", LIB, error);
+      }
+      #endif
+
+
+      static inline uint8_t absVal(int8_t num) {
+        return (num < 0) ? (uint8_t)-num : (uint8_t)num;
+      }
+
+      static inline uint8_t min(uint8_t a, uint8_t b) {
+        return (a < b) ? a : b;
+      }
+
+      static inline uint8_t max(uint8_t a, uint8_t b) {
+        return (a > b) ? a : b;
+      }
+
+      sdLaMa091_t* sdLaMa091New(void) {
+        sdLaMa091_t* sdLaMa091 = (sdLaMa091_t*)malloc(sizeof(*sdLaMa091));
+
+      #ifdef DEFENSIVE_ALLOC
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot allocate sdLaMa091 structure");
+          return NULL;
+        }
+      #endif
+
+        sdLaMa091->imageType = UNKNOWN;
+
+        sdLaMa091->width = 0;
+        sdLaMa091->rgbWidth = 0;
+        sdLaMa091->height = 0;
+        sdLaMa091->stride = 0;
+        sdLaMa091->numBytes = 0;
+        sdLaMa091->unusedBytes = 0;
+        sdLaMa091->rgbUnusedBytes = 0;
+
+        sdLaMa091->N = DEFAULT_N;
+        sdLaMa091->Vmin = DEFAULT_VMIN;
+        sdLaMa091->Vmax = DEFAULT_VMAX;
+
+        sdLaMa091->Mt = NULL;
+        sdLaMa091->Ot = NULL;
+        sdLaMa091->Vt = NULL;
+
+        return sdLaMa091;
+      }
+
+      int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        const uint32_t width,
+        const uint32_t height,
+        const uint32_t stride) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot initialize a NULL structure");
+          return EXIT_FAILURE;
+        }
+
+        if (image_data == NULL) {
+          outputError("Cannot allocate ressources for a NULL image");
+          return EXIT_FAILURE;
+        }
+      #endif
+
+      #ifdef DEFENSIVE_PARAM
+        if (width == 0 || height == 0 || stride == 0) {
+          outputError("Cannot allocate ressources for zero values");
+          return EXIT_FAILURE;
+        }
+
+        if (stride < width) {
+          outputError("Cannot allocate ressources for a stride lower than the width");
+          return EXIT_FAILURE;
+        }
+      #endif
+
+        sdLaMa091->imageType = C1R;
+
+        sdLaMa091->width = width;
+        sdLaMa091->height = height;
+        sdLaMa091->stride = stride;
+        sdLaMa091->numBytes = stride * height;
+        sdLaMa091->unusedBytes = stride - sdLaMa091->width;
+
+        sdLaMa091->Mt = (uint8_t*)malloc(sdLaMa091->numBytes);
+      #ifdef DEFENSIVE_ALLOC
+        if (sdLaMa091->Mt == NULL) {
+          outputError("Cannot allocate sdLaMa091->Mt table");
+          return EXIT_FAILURE;
+        }
+      #endif 
+        memcpy(sdLaMa091->Mt, image_data, sdLaMa091->numBytes);
+
+        sdLaMa091->Ot = (uint8_t*)malloc(sdLaMa091->numBytes);
+      #ifdef DEFENSIVE_ALLOC
+        if (sdLaMa091->Ot == NULL) {
+          outputError("Cannot allocate sdLaMa091->Ot table");
+          return EXIT_FAILURE;
+        }
+      #endif 
+        uint8_t* workOt = sdLaMa091->Ot;
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workOt)
+            *workOt = 0;
+
+
+          if (sdLaMa091->unusedBytes > 0)
+            workOt += sdLaMa091->unusedBytes;
+        }
+
+        sdLaMa091->Vt = (uint8_t*)malloc(sdLaMa091->numBytes);
+      #ifdef DEFENSIVE_ALLOC
+        if (sdLaMa091->Vt == NULL) {
+          outputError("Cannot allocate sdLaMa091->Vt table");
+          return EXIT_FAILURE;
+        }
+      #endif
+        uint8_t* workVt = sdLaMa091->Vt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workVt)
+            *workVt = sdLaMa091->Vmin;
+
+
+          if (sdLaMa091->unusedBytes > 0)
+            workVt += sdLaMa091->unusedBytes;
+        }
+
+        return EXIT_SUCCESS;
+      }
+
+      int32_t sdLaMa091AllocInit_8u_C3R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        const uint32_t width,
+        const uint32_t height,
+        const uint32_t stride) {
+        int32_t success = sdLaMa091AllocInit_8u_C1R(sdLaMa091, image_data, width,
+          height, stride);
+
+        if (success == EXIT_SUCCESS) {
+          sdLaMa091->imageType = C3R;
+          sdLaMa091->rgbWidth = sdLaMa091->width * CHANNELS;
+          sdLaMa091->rgbUnusedBytes = stride - sdLaMa091->rgbWidth;
+          sdLaMa091->width = 0;
+          sdLaMa091->unusedBytes = 0;
+        }
+
+        return success;
+      }
+
+      int32_t sdLaMa091SetAmplificationFactor(sdLaMa091_t* sdLaMa091,
+        const uint32_t amplificationFactor) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot set a parameter of a NULL structure");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+      #ifdef DEFENSIVE_PARAM
+        if (amplificationFactor == 0) {
+          outputError("Cannot set a parameter with a zero value");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+        sdLaMa091->N = amplificationFactor;
+
+        return EXIT_SUCCESS;
+      }
+
+      uint32_t sdLaMa091GetAmplificationFactor(const sdLaMa091_t* sdLaMa091) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot get a parameter of a NULL structure");
+          errno = ERROR_OCCURED;
+
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+        return sdLaMa091->N;
+      }
+
+      int32_t sdLaMa091SetMaximalVariance(sdLaMa091_t* sdLaMa091,
+        const uint32_t maximalVariance) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot set a parameter of a NULL structure");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+      #ifdef DEFENSIVE_PARAM
+        if (maximalVariance == 0) {
+          outputError("Cannot set a parameter with a zero value");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+        sdLaMa091->Vmax = maximalVariance;
+
+        return EXIT_SUCCESS;
+      }
+
+      uint32_t sdLaMa091GetMaximalVariance(const sdLaMa091_t* sdLaMa091) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot get a parameter of a NULL structure");
+          errno = ERROR_OCCURED;
+
+          return EXIT_FAILURE;
+        }
+      #endif
+
+        return sdLaMa091->Vmax;
+      }
+
+      int32_t sdLaMa091SetMinimalVariance(sdLaMa091_t* sdLaMa091,
+        const uint32_t minimalVariance) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot set a parameter of a NULL structure");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+        sdLaMa091->Vmin = minimalVariance;
+
+        return EXIT_SUCCESS;
+      }
+
+      uint32_t sdLaMa091GetMinimalVariance(const sdLaMa091_t* sdLaMa091) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot get a parameter of a NULL structure");
+          errno = ERROR_OCCURED;
+
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+        return sdLaMa091->Vmin;
+      }
+
+
+      int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        uint8_t* segmentation_map) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot update a NULL structure");
+          return EXIT_FAILURE;
+        }
+
+        if (image_data == NULL) {
+          outputError("Cannot update a structure with a NULL image");
+          return EXIT_FAILURE;
+        }
+
+        if (segmentation_map == NULL) {
+          outputError("Cannot update a structure with a NULL segmentation map");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Mt == NULL) {
+          outputError("Cannot update a structure with a NULL Mt table");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Ot == NULL) {
+          outputError("Cannot update a structure with a NULL Ot table");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Vt == NULL) {
+          outputError("Cannot update a structure with a NULL Vt table");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+      #ifdef DEFENSIVE_PARAM
+        if (sdLaMa091->imageType != C1R) {
+          outputError("Cannot update a structure which is not C1R");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->width == 0 || sdLaMa091->height == 0 ||
+          sdLaMa091->stride == 0) {
+          outputError("Cannot update a structure with zero values");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->stride < sdLaMa091->width) {
+          outputError("Cannot update a structure with a stride lower than the width");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Vmax < sdLaMa091->Vmin) {
+          outputError("Cannot update a structure with Vmax inferior to Vmin");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+
+        const uint8_t* workImage = image_data;
+        uint8_t* workMt = sdLaMa091->Mt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workImage, ++workMt) {
+            if (*workMt < *workImage)
+              ++(*workMt);
+            else if (*workMt > *workImage)
+              --(*workMt);
+          }
+
+
+          if (sdLaMa091->unusedBytes > 0) {
+            workImage += sdLaMa091->unusedBytes;
+            workMt += sdLaMa091->unusedBytes;
+          }
+        }
+
+        workImage = image_data;
+        workMt = sdLaMa091->Mt;
+        uint8_t* workOt = sdLaMa091->Ot;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workImage, ++workMt,
+            ++workOt)
+            *workOt = absVal(*workMt - *workImage);
+
+
+          if (sdLaMa091->unusedBytes > 0) {
+            workImage += sdLaMa091->unusedBytes;
+            workMt += sdLaMa091->unusedBytes;
+            workOt += sdLaMa091->unusedBytes;
+          }
+        }
+
+
+        workOt = sdLaMa091->Ot;
+        uint8_t* workVt = sdLaMa091->Vt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++workOt, ++workVt) {
+            uint32_t ampOt = sdLaMa091->N * *workOt;
+
+            if (*workVt < ampOt)
+              ++(*workVt);
+            else if (*workVt > ampOt)
+              --(*workVt);
+
+            *workVt = max(min(*workVt, sdLaMa091->Vmax), sdLaMa091->Vmin);
+          }
+
+
+          if (sdLaMa091->unusedBytes > 0) {
+            workOt += sdLaMa091->unusedBytes;
+            workVt += sdLaMa091->unusedBytes;
+          }
+        }
+
+
+        workOt = sdLaMa091->Ot;
+        workVt = sdLaMa091->Vt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->width; ++j, ++segmentation_map,
+            ++workOt, ++workVt) {
+
+            if (*workOt < *workVt)
+              *segmentation_map = BACKGROUND;
+            else
+              *segmentation_map = FOREGROUND;
+          }
+
+
+          if (sdLaMa091->unusedBytes > 0) {
+            segmentation_map += sdLaMa091->unusedBytes;
+            workOt += sdLaMa091->unusedBytes;
+            workVt += sdLaMa091->unusedBytes;
+          }
+        }
+
+        return EXIT_SUCCESS;
+      }
+
+      int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        uint8_t* segmentation_map) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot update a NULL structure");
+          return EXIT_FAILURE;
+        }
+
+        if (image_data == NULL) {
+          outputError("Cannot update a structure with a NULL image");
+          return EXIT_FAILURE;
+        }
+
+        if (segmentation_map == NULL) {
+          outputError("Cannot update a structure with a NULL segmentation map");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Mt == NULL) {
+          outputError("Cannot update a structure with a NULL Mt table");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Ot == NULL) {
+          outputError("Cannot update a structure with a NULL Ot table");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Vt == NULL) {
+          outputError("Cannot update a structure with a NULL Vt table");
+          return EXIT_FAILURE;
+        }
+      #endif
+
+      #ifdef DEFENSIVE_PARAM
+        if (sdLaMa091->imageType != C3R) {
+          outputError("Cannot update a structure which is not C3R");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->rgbWidth == 0 || sdLaMa091->height == 0 ||
+          sdLaMa091->stride == 0) {
+          outputError("Cannot update a structure with zero values");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->stride < sdLaMa091->rgbWidth) {
+          outputError("Cannot update a structure with a stride lower than the width");
+          return EXIT_FAILURE;
+        }
+
+        if (sdLaMa091->Vmax < sdLaMa091->Vmin) {
+          outputError("Cannot update a structure with Vmax inferior to Vmin");
+          return EXIT_FAILURE;
+        }
+      #endif 
+
+
+        const uint8_t* workImage = image_data;
+        uint8_t* workMt = sdLaMa091->Mt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workImage, ++workMt) {
+            if (*workMt < *workImage)
+              ++(*workMt);
+            else if (*workMt > *workImage)
+              --(*workMt);
+          }
+
+
+          if (sdLaMa091->rgbUnusedBytes > 0) {
+            workImage += sdLaMa091->rgbUnusedBytes;
+            workMt += sdLaMa091->rgbUnusedBytes;
+          }
+        }
+
+
+        workImage = image_data;
+        workMt = sdLaMa091->Mt;
+        uint8_t* workOt = sdLaMa091->Ot;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workImage, ++workMt,
+            ++workOt)
+            *workOt = absVal(*workMt - *workImage);
+
+
+          if (sdLaMa091->rgbUnusedBytes > 0) {
+            workImage += sdLaMa091->rgbUnusedBytes;
+            workMt += sdLaMa091->rgbUnusedBytes;
+            workOt += sdLaMa091->rgbUnusedBytes;
+          }
+        }
+
+        workOt = sdLaMa091->Ot;
+        uint8_t* workVt = sdLaMa091->Vt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workOt, ++workVt) {
+            uint32_t ampOt = sdLaMa091->N * *workOt;
+
+            if (*workVt < ampOt)
+              ++(*workVt);
+            else if (*workVt > ampOt)
+              --(*workVt);
+
+            *workVt = max(min(*workVt, sdLaMa091->Vmax), sdLaMa091->Vmin);
+          }
+
+
+          if (sdLaMa091->rgbUnusedBytes > 0) {
+            workOt += sdLaMa091->rgbUnusedBytes;
+            workVt += sdLaMa091->rgbUnusedBytes;
+          }
+        }
+
+        workOt = sdLaMa091->Ot;
+        workVt = sdLaMa091->Vt;
+
+
+        for (uint32_t i = 0; i < sdLaMa091->numBytes; i += sdLaMa091->stride) {
+
+          uint32_t numColor = 0;
+
+          bool isForeground = false;
+
+
+          for (uint32_t j = 0; j < sdLaMa091->rgbWidth; ++j, ++workOt, ++workVt) {
+            if (*workOt >= *workVt)
+              isForeground = true;
+
+
+            if (numColor == BLUE) {
+              if (isForeground) {
+                *segmentation_map = FOREGROUND;
+                *(++segmentation_map) = FOREGROUND;
+                *(++segmentation_map) = FOREGROUND;
+                ++segmentation_map;
+              }
+              else {
+                *segmentation_map = BACKGROUND;
+                *(++segmentation_map) = BACKGROUND;
+                *(++segmentation_map) = BACKGROUND;
+                ++segmentation_map;
+              }
+
+              isForeground = false;
+            }
+
+            numColor = (numColor + 1) % CHANNELS;
+          }
+
+
+          if (sdLaMa091->rgbUnusedBytes > 0) {
+            segmentation_map += sdLaMa091->rgbUnusedBytes;
+            workOt += sdLaMa091->rgbUnusedBytes;
+            workVt += sdLaMa091->rgbUnusedBytes;
+          }
+        }
+
+        return EXIT_SUCCESS;
+      }
+
+      int32_t sdLaMa091Free(sdLaMa091_t* sdLaMa091) {
+      #ifdef DEFENSIVE_POINTER
+        if (sdLaMa091 == NULL) {
+          outputError("Cannot free a NULL strucutre");
+          return EXIT_FAILURE;
+        }
+      #endif
+
+        if (sdLaMa091->Mt != NULL)
+          free(sdLaMa091->Mt);
+        if (sdLaMa091->Ot != NULL)
+          free(sdLaMa091->Ot);
+        if (sdLaMa091->Vt != NULL)
+          free(sdLaMa091->Vt);
+
+        free(sdLaMa091);
+
+        return EXIT_SUCCESS;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/SigmaDelta/sdLaMa091.h b/src/algorithms/SigmaDelta/sdLaMa091.h
new file mode 100644
index 0000000000000000000000000000000000000000..84eeecb82c725586a758e8b27055f46707dbe6b5
--- /dev/null
+++ b/src/algorithms/SigmaDelta/sdLaMa091.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace sigmadelta
+    {
+      const int BACKGROUND = 0;
+      const int FOREGROUND = 255;
+      const int ERROR_OCCURED = 1;
+
+      typedef struct sdLaMa091 sdLaMa091_t;
+
+      sdLaMa091_t* sdLaMa091New(void);
+
+      int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        const uint32_t width,
+        const uint32_t height,
+        const uint32_t stride);
+
+      int32_t sdLaMa091AllocInit_8u_C3R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        const uint32_t width,
+        const uint32_t height,
+        const uint32_t stride);
+
+      int32_t sdLaMa091SetAmplificationFactor(sdLaMa091_t* sdLaMa091,
+        const uint32_t amplificationFactor);
+
+      uint32_t sdLaMa091GetAmplificationFactor(const sdLaMa091_t* sdLaMa091);
+
+      int32_t sdLaMa091SetMaximalVariance(sdLaMa091_t* sdLaMa091,
+        const uint32_t maximalVariance);
+
+      uint32_t sdLaMa091GetMaximalVariance(const sdLaMa091_t* sdLaMa091);
+
+      int32_t sdLaMa091SetMinimalVariance(sdLaMa091_t* sdLaMa091,
+        const uint32_t minimalVariance);
+
+      uint32_t sdLaMa091GetMinimalVariance(const sdLaMa091_t* sdLaMa091);
+
+      int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        uint8_t* segmentation_map);
+
+      int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091,
+        const uint8_t* image_data,
+        uint8_t* segmentation_map);
+
+      int32_t sdLaMa091Free(sdLaMa091_t* sdLaMa091);
+    }
+  }
+}
diff --git a/src/algorithms/StaticFrameDifference.cpp b/src/algorithms/StaticFrameDifference.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..54dbc07411b5199176d605a989d9f69c267e161a
--- /dev/null
+++ b/src/algorithms/StaticFrameDifference.cpp
@@ -0,0 +1,53 @@
+#include "StaticFrameDifference.h"
+
+using namespace bgslibrary::algorithms;
+
+StaticFrameDifference::StaticFrameDifference() :
+  IBGS(quote(StaticFrameDifference)),
+  enableThreshold(true), threshold(15)
+{
+  debug_construction(StaticFrameDifference);
+  initLoadSaveConfig(algorithmName);
+}
+
+StaticFrameDifference::~StaticFrameDifference() {
+  debug_destruction(StaticFrameDifference);
+}
+
+void StaticFrameDifference::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (img_background.empty())
+    img_input.copyTo(img_background);
+
+  cv::absdiff(img_input, img_background, img_foreground);
+
+  if (img_foreground.channels() == 3)
+    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
+
+  if (enableThreshold)
+    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  firstTime = false;
+}
+
+void StaticFrameDifference::save_config(cv::FileStorage &fs) {
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void StaticFrameDifference::load_config(cv::FileStorage &fs) {
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/StaticFrameDifference.h b/src/algorithms/StaticFrameDifference.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3b62346ab5900eb8655aaa94688455c7a338779
--- /dev/null
+++ b/src/algorithms/StaticFrameDifference.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class StaticFrameDifference : public IBGS
+    {
+    private:
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      StaticFrameDifference();
+      ~StaticFrameDifference();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(StaticFrameDifference);
+  }
+}
diff --git a/src/algorithms/SuBSENSE.cpp b/src/algorithms/SuBSENSE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9429023ecc53f9e266ba959ca143192b2311258
--- /dev/null
+++ b/src/algorithms/SuBSENSE.cpp
@@ -0,0 +1,70 @@
+#include "SuBSENSE.h"
+
+using namespace bgslibrary::algorithms;
+
+SuBSENSE::SuBSENSE() :
+  IBGS(quote(SuBSENSE)),
+  pSubsense(0),
+  fRelLBSPThreshold(lbsp::BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD),
+  nDescDistThresholdOffset(lbsp::BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET),
+  nMinColorDistThreshold(lbsp::BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD),
+  nBGSamples(lbsp::BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES),
+  nRequiredBGSamples(lbsp::BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES),
+  nSamplesForMovingAvgs(lbsp::BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS)
+{
+  debug_construction(SuBSENSE);
+  initLoadSaveConfig(algorithmName);
+}
+
+SuBSENSE::~SuBSENSE() {
+  debug_destruction(SuBSENSE);
+  if (pSubsense)
+    delete pSubsense;
+}
+
+void SuBSENSE::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (firstTime) {
+    pSubsense = new lbsp::BackgroundSubtractorSuBSENSE(
+      fRelLBSPThreshold, nDescDistThresholdOffset, nMinColorDistThreshold,
+      nBGSamples, nRequiredBGSamples, nSamplesForMovingAvgs);
+
+    pSubsense->initialize(img_input, cv::Mat(img_input.size(), CV_8UC1, cv::Scalar_<uchar>(255)));
+    firstTime = false;
+  }
+
+  pSubsense->apply(img_input, img_foreground);
+  pSubsense->getBackgroundImage(img_background);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+}
+
+void SuBSENSE::save_config(cv::FileStorage &fs) {
+  fs << "fRelLBSPThreshold" << fRelLBSPThreshold;
+  fs << "nDescDistThresholdOffset" << nDescDistThresholdOffset;
+  fs << "nMinColorDistThreshold" << nMinColorDistThreshold;
+  fs << "nBGSamples" << nBGSamples;
+  fs << "nRequiredBGSamples" << nRequiredBGSamples;
+  fs << "nSamplesForMovingAvgs" << nSamplesForMovingAvgs;
+  fs << "showOutput" << showOutput;
+}
+
+void SuBSENSE::load_config(cv::FileStorage &fs) {
+  fs["fRelLBSPThreshold"] >> fRelLBSPThreshold;
+  fs["nDescDistThresholdOffset"] >> nDescDistThresholdOffset;
+  fs["nMinColorDistThreshold"] >> nMinColorDistThreshold;
+  fs["nBGSamples"] >> nBGSamples;
+  fs["nRequiredBGSamples"] >> nRequiredBGSamples;
+  fs["nSamplesForMovingAvgs"] >> nSamplesForMovingAvgs;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/SuBSENSE.h b/src/algorithms/SuBSENSE.h
new file mode 100644
index 0000000000000000000000000000000000000000..e309776da5a607d8f8c10ecf5fc4402a94b54526
--- /dev/null
+++ b/src/algorithms/SuBSENSE.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "IBGS.h"
+#include "LBSP/BackgroundSubtractorSuBSENSE.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class SuBSENSE : public IBGS
+    {
+    private:
+      lbsp::BackgroundSubtractorSuBSENSE* pSubsense;
+
+      float fRelLBSPThreshold;
+      int nDescDistThresholdOffset;
+      int nMinColorDistThreshold;
+      int nBGSamples;
+      int nRequiredBGSamples;
+      int nSamplesForMovingAvgs;
+
+    public:
+      SuBSENSE();
+      ~SuBSENSE();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(SuBSENSE);
+  }
+}
diff --git a/package_bgs/T2F/MRF.cpp b/src/algorithms/T2F/MRF.cpp
similarity index 90%
rename from package_bgs/T2F/MRF.cpp
rename to src/algorithms/T2F/MRF.cpp
index 291a84612f53b482317d1cc4eefae70c681d7de4..2d6d18b4f5c306de93922582c39bbf9a6daf6d69 100644
--- a/package_bgs/T2F/MRF.cpp
+++ b/src/algorithms/T2F/MRF.cpp
@@ -1,22 +1,8 @@
-/*
-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 "MRF.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 //init the basic MRF
 MRF::MRF()
@@ -336,3 +322,5 @@ void MRF_TC::ICM2()
     OnIterationOver2();
   } while (K < 2);
 }
+
+#endif
diff --git a/src/algorithms/T2F/MRF.h b/src/algorithms/T2F/MRF.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f773c86cb47311d0508e48bfece28c84ade9074
--- /dev/null
+++ b/src/algorithms/T2F/MRF.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "T2FMRF.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      // base class
+      class MRF
+      {
+      public:
+        IplImage *in_image, *out_image;
+        //image's width and height
+        int width, height;
+
+      public:
+        MRF();
+
+      protected:
+
+        //////////////////////////////////////////////////////////////////////////
+        //the number of labeling
+        int no_regions;
+        //potential of Space  Constraint
+        double beta;
+        //terminal condition when (deltaE < t)
+        double t;
+
+        //////////////////////////////////////////////////////////////////////////
+        //for gibbs
+        double T0;
+        //current temperature
+        double T;
+        double c;
+
+        //////////////////////////////////////////////////////////////////////////
+        // alpha value for MMD
+        double alpha;
+
+        //////////////////////////////////////////////////////////////////////////
+        //current global energy
+        double E;
+        //old global energy
+        double E_old;
+        //number of iteration
+        int K;
+
+        //////////////////////////////////////////////////////////////////////////
+        //labeling image
+        int **classes;
+        //input image
+        int **in_image_data;
+        //evidence
+        float ** local_evidence;
+      };
+
+      /************************************************************************/
+      /* the Markov Random Field with time constraints for T2FGMM   */
+      /************************************************************************/
+      class MRF_TC : public MRF
+      {
+      private:
+        double beta_time;
+
+      public:
+        IplImage *background2;
+        RgbImage background;
+        int **old_labeling;
+
+      public:
+        MRF_TC();
+        ~MRF_TC();
+        double TimeEnergy2(int i, int j, int label);
+        void OnIterationOver2(void);
+        void Build_Classes_OldLabeling_InImage_LocalEnergy();
+        void InitEvidence2(GMM *gmm, HMM *hmm, IplImage *labeling);
+        void CreateOutput2();
+        double CalculateEnergy2();
+        double LocalEnergy2(int i, int j, int label);
+        double Doubleton2(int i, int j, int label);
+
+        void Gibbs2();
+        void ICM2();
+        void Metropolis2(bool mmd);
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2F/T2FGMM.cpp b/src/algorithms/T2F/T2FGMM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d7b35e4f95d6e1a53258cefbf52c1e9b1d6d618
--- /dev/null
+++ b/src/algorithms/T2F/T2FGMM.cpp
@@ -0,0 +1,323 @@
+#include "T2FGMM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//using namespace bgslibrary::algorithms::dp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      int compareT2FGMM(const void* _gmm1, const void* _gmm2)
+      {
+        GMM gmm1 = *(GMM*)_gmm1;
+        GMM gmm2 = *(GMM*)_gmm2;
+
+        if (gmm1.significants < gmm2.significants)
+          return 1;
+        else if (gmm1.significants == gmm2.significants)
+          return 0;
+        else
+          return -1;
+      }
+
+      T2FGMM::T2FGMM()
+      {
+        m_modes = NULL;
+      }
+
+      T2FGMM::~T2FGMM()
+      {
+        delete[] m_modes;
+      }
+
+      void T2FGMM::Initalize(const BgsParams& param)
+      {
+        m_params = (T2FGMMParams&)param;
+
+        // Tbf - the threshold
+        m_bg_threshold = 0.75f;	// 1-cf from the paper
+
+        // Tgenerate - the threshold
+        m_variance = 36.0f;		// sigma for the new mode
+
+        // GMM for each pixel
+        m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
+
+        // used modes per pixel
+        m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
+
+        m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
+
+        // Factor control for the T2FGMM-UM [0,3]
+        //km = (float) 1.5;
+        km = (float)m_params.KM();
+
+        // Factor control for the T2FGMM-UV [0.3,1]
+        //kv = (float) 0.6;
+        kv = (float)m_params.KV();
+      }
+
+      RgbImage* T2FGMM::Background()
+      {
+        return &m_background;
+      }
+
+      void T2FGMM::InitModel(const RgbImage& data)
+      {
+        m_modes_per_pixel.Clear();
+
+        for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
+        {
+          m_modes[i].weight = 0;
+          m_modes[i].variance = 0;
+          m_modes[i].muR = 0;
+          m_modes[i].muG = 0;
+          m_modes[i].muB = 0;
+          m_modes[i].significants = 0;
+        }
+      }
+
+      void T2FGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
+      {
+        // it doesn't make sense to have conditional updates in the GMM framework
+      }
+
+      void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
+        unsigned char& low_threshold, unsigned char& high_threshold)
+      {
+        // calculate distances to the modes (+ sort???)
+        // here we need to go in descending order!!!
+        long pos;
+        bool bFitsPDF = false;
+        bool bBackgroundLow = false;
+        bool bBackgroundHigh = false;
+
+        float fOneMinAlpha = 1 - m_params.Alpha();
+        float totalWeight = 0.0f;
+
+        // calculate number of Gaussians to include in the background model
+        int backgroundGaussians = 0;
+        double sum = 0.0;
+        for (int i = 0; i < numModes; ++i)
+        {
+          if (sum < m_bg_threshold)
+          {
+            backgroundGaussians++;
+            sum += m_modes[posPixel + i].weight;
+          }
+          else
+            break;
+        }
+
+        // update all distributions and check for match with current pixel
+        for (int iModes = 0; iModes < numModes; iModes++)
+        {
+          pos = posPixel + iModes;
+          float weight = m_modes[pos].weight;
+
+          // fit not found yet
+          if (!bFitsPDF)
+          {
+            //check if it belongs to some of the modes
+            //calculate distance
+            float var = m_modes[pos].variance;
+            float muR = m_modes[pos].muR;
+            float muG = m_modes[pos].muG;
+            float muB = m_modes[pos].muB;
+
+            //float km = 2;
+            //float kv = 0.9;
+
+            float dR = fabs(muR - pixel(0));
+            float dG = fabs(muG - pixel(1));
+            float dB = fabs(muB - pixel(2));
+
+            // calculate the squared distance
+            float HR;
+            float HG;
+            float HB;
+
+            // T2FGMM-UM
+            if (m_params.Type() == TYPE_T2FGMM_UM)
+            {
+              if ((pixel(0) < muR - km*var) || (pixel(0) > muR + km*var))
+                HR = 2 * km*dR / var;
+              else
+                HR = dR*dR / (2 * var*var) + km*dR / var + km*km / 2;
+
+              if ((pixel(1) < muG - km*var) || (pixel(1) > muG + km*var))
+                HG = 2 * km*dG / var;
+              else
+                HG = dG*dG / (2 * var*var) + km*dG / var + km*km / 2;
+
+              if ((pixel(2) < muB - km*var) || (pixel(2) > muB + km*var))
+                HB = 2 * km*dB / var;
+              else
+                HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2;
+            }
+
+            // T2FGMM-UV
+            if (m_params.Type() == TYPE_T2FGMM_UV)
+            {
+              HR = (1 / (kv*kv) - kv*kv) * (pixel(0) - muR) * (pixel(0) - muR) / (2 * var);
+              HG = (1 / (kv*kv) - kv*kv) * (pixel(1) - muG) * (pixel(1) - muG) / (2 * var);
+              HB = (1 / (kv*kv) - kv*kv) * (pixel(2) - muB) * (pixel(2) - muB) / (2 * var);
+            }
+
+            // calculate the squared distance
+            float dist = (HR*HR + HG*HG + HB*HB);
+
+            if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
+              bBackgroundHigh = true;
+
+            // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
+            if (dist < m_params.LowThreshold()*var)
+            {
+              bFitsPDF = true;
+
+              // check if this Gaussian is part of the background model
+              if (iModes < backgroundGaussians)
+                bBackgroundLow = true;
+
+              //update distribution
+              float k = m_params.Alpha() / weight;
+              weight = fOneMinAlpha*weight + m_params.Alpha();
+              m_modes[pos].weight = weight;
+              m_modes[pos].muR = muR - k*(dR);
+              m_modes[pos].muG = muG - k*(dG);
+              m_modes[pos].muB = muB - k*(dB);
+
+              //limit the variance
+              float sigmanew = var + k*(dist - var);
+              m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+            else
+            {
+              weight = fOneMinAlpha*weight;
+              if (weight < 0.0)
+              {
+                weight = 0.0;
+                numModes--;
+              }
+
+              m_modes[pos].weight = weight;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+          }
+          else
+          {
+            weight = fOneMinAlpha*weight;
+            if (weight < 0.0)
+            {
+              weight = 0.0;
+              numModes--;
+            }
+            m_modes[pos].weight = weight;
+            m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+          }
+
+          totalWeight += weight;
+        }
+
+        // renormalize weights so they add to one
+        double invTotalWeight = 1.0 / totalWeight;
+        for (int iLocal = 0; iLocal < numModes; iLocal++)
+        {
+          m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
+          m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
+            / sqrt(m_modes[posPixel + iLocal].variance);
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&m_modes[posPixel], numModes, sizeof(GMM), compareT2FGMM);
+
+        // make new mode if needed and exit
+        if (!bFitsPDF)
+        {
+          if (numModes < m_params.MaxModes())
+            numModes++;
+          //else
+          // the weakest mode will be replaced
+
+          pos = posPixel + numModes - 1;
+
+          m_modes[pos].muR = pixel.ch[0];
+          m_modes[pos].muG = pixel.ch[1];
+          m_modes[pos].muB = pixel.ch[2];
+          m_modes[pos].variance = m_variance;
+          m_modes[pos].significants = 0;			// will be set below
+
+          if (numModes == 1)
+            m_modes[pos].weight = 1;
+          else
+            m_modes[pos].weight = m_params.Alpha();
+
+          //renormalize weights
+          int iLocal;
+          float sum = 0.0;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+            sum += m_modes[posPixel + iLocal].weight;
+
+          double invSum = 1.0 / sum;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+          {
+            m_modes[posPixel + iLocal].weight *= (float)invSum;
+            m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight / sqrt(m_modes[posPixel + iLocal].variance);
+          }
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareT2FGMM);
+
+        if (bBackgroundLow)
+          low_threshold = BACKGROUND;
+        else
+          low_threshold = FOREGROUND;
+
+        if (bBackgroundHigh)
+          high_threshold = BACKGROUND;
+        else
+          high_threshold = FOREGROUND;
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////
+      //Input:
+      //  data - a pointer to the data of a RGB image of the same size
+      //Output:
+      //  output - a pointer to the data of a gray value image of the same size 
+      //					(the memory should already be reserved) 
+      //					values: 255-foreground, 125-shadow, 0-background
+      ///////////////////////////////////////////////////////////////////////////////
+      void T2FGMM::Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask)
+      {
+        unsigned char low_threshold, high_threshold;
+        long posPixel;
+
+        // update each pixel of the image
+        for (unsigned int r = 0; r < m_params.Height(); ++r)
+        {
+          for (unsigned int c = 0; c < m_params.Width(); ++c)
+          {
+            // update model + background subtract
+            posPixel = (r*m_params.Width() + c) * m_params.MaxModes();
+
+            SubtractPixel(posPixel, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
+
+            low_threshold_mask(r, c) = low_threshold;
+            high_threshold_mask(r, c) = high_threshold;
+
+            m_background(r, c, 0) = (unsigned char)m_modes[posPixel].muR;
+            m_background(r, c, 1) = (unsigned char)m_modes[posPixel].muG;
+            m_background(r, c, 2) = (unsigned char)m_modes[posPixel].muB;
+          }
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2F/T2FGMM.h b/src/algorithms/T2F/T2FGMM.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a7cfc38414fec28e34deaf442d90910b6df2608
--- /dev/null
+++ b/src/algorithms/T2F/T2FGMM.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "../dp/Bgs.h"
+#include "../dp/GrimsonGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      const int TYPE_T2FGMM_UM = 0;
+      const int TYPE_T2FGMM_UV = 1;
+
+      // --- User adjustable parameters used by the T2F GMM BGS algorithm ---
+      class T2FGMMParams : public BgsParams
+      {
+      public:
+        float &LowThreshold() { return m_low_threshold; }
+        float &HighThreshold() { return m_high_threshold; }
+
+        float &Alpha() { return m_alpha; }
+        int &MaxModes() { return m_max_modes; }
+        int &Type() { return m_type; }
+        float &KM() { return m_km; }
+        float &KV() { return m_kv; }
+
+      private:
+        // Threshold on the squared dist. to decide when a sample is close to an existing
+        // components. If it is not close to any a new component will be generated.
+        // Smaller threshold values lead to more generated components and higher threshold values
+        // lead to a small number of components but they can grow too large.
+        //
+        // It is usual easiest to think of these thresholds as being the number of variances away
+        // from the mean of a pixel before it is considered to be from the foreground.
+        float m_low_threshold;
+        float m_high_threshold;
+
+        // alpha - speed of update - if the time interval you want to average over is T
+        // set alpha=1/T.
+        float m_alpha;
+
+        // Maximum number of modes (Gaussian components) that will be used per pixel
+        int m_max_modes;
+
+        // T2FGMM_UM / T2FGMM_UV
+        int m_type;
+
+        // Factor control for the T2FGMM-UM
+        float m_km;
+
+        // Factor control for the T2FGMM-UV
+        float m_kv;
+      };
+
+      // --- T2FGMM BGS algorithm ---
+      class T2FGMM : public Bgs
+      {
+      public:
+        T2FGMM();
+        ~T2FGMM();
+
+        void Initalize(const BgsParams& param);
+
+        void InitModel(const RgbImage& data);
+        void Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask);
+        void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
+
+        RgbImage* Background();
+
+      private:
+        void SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold);
+
+        // User adjustable parameters
+        T2FGMMParams m_params;
+
+        // Threshold when the component becomes significant enough to be included into
+        // the background model. It is the TB = 1-cf from the paper. So I use cf=0.1 => TB=0.9
+        // For alpha=0.001 it means that the mode should exist for approximately 105 frames before
+        // it is considered foreground
+        float m_bg_threshold; //1-cf from the paper
+
+        // Initial variance for the newly generated components.
+        // It will will influence the speed of adaptation. A good guess should be made.
+        // A simple way is to estimate the typical standard deviation from the images.
+        float m_variance;
+
+        // Dynamic array for the mixture of Gaussians
+        GMM* m_modes;
+
+        // Number of Gaussian components per pixel
+        BwImage m_modes_per_pixel;
+
+        // Current background model
+        RgbImage m_background;
+
+        // Factor control for the T2FGMM-UM
+        float km;
+
+        // Factor control for the T2FGMM-UV
+        float kv;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2F/T2FMRF.cpp b/src/algorithms/T2F/T2FMRF.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a264c14b88c8543f5d78fd97dcfc2703f5bd45c
--- /dev/null
+++ b/src/algorithms/T2F/T2FMRF.cpp
@@ -0,0 +1,414 @@
+#include "T2FMRF.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//using namespace bgslibrary::algorithms::dp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      int compareT2FMRF(const void* _gmm1, const void* _gmm2)
+      {
+        GMM gmm1 = *(GMM*)_gmm1;
+        GMM gmm2 = *(GMM*)_gmm2;
+
+        if (gmm1.significants < gmm2.significants)
+          return 1;
+        else if (gmm1.significants == gmm2.significants)
+          return 0;
+        else
+          return -1;
+      }
+
+      GMM* T2FMRF::gmm()
+      {
+        return m_modes;
+      }
+      HMM* T2FMRF::hmm()
+      {
+        return m_state;
+      }
+
+      T2FMRF::T2FMRF()
+      {
+        m_modes = NULL;
+      }
+
+      T2FMRF::~T2FMRF()
+      {
+        delete[] m_modes;
+      }
+
+      void T2FMRF::Initalize(const BgsParams& param)
+      {
+        m_params = (T2FMRFParams&)param;
+
+        // Tbf - the threshold
+        m_bg_threshold = 0.75f;	// 1-cf from the paper
+
+        // Tgenerate - the threshold
+        m_variance = 36.0f;		// sigma for the new mode
+
+        // GMM for each pixel
+        m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
+
+        //HMM for each pixel
+        m_state = new HMM[m_params.Size()];
+
+        // used modes per pixel
+        m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
+
+        m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
+
+        // Factor control for the T2FGMM-UM [0,3]
+        // km = (float) 2; //1.5;
+        km = (float)m_params.KM();
+
+        // Factor control for the T2FGMM-UV [0.3,1]
+        // kv = (float) 0.9; //0.6;
+        kv = (float)m_params.KV();
+      }
+
+      RgbImage* T2FMRF::Background()
+      {
+        return &m_background;
+      }
+
+      void T2FMRF::InitModel(const RgbImage& data)
+      {
+        m_modes_per_pixel.Clear();
+
+        for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
+        {
+          m_modes[i].weight = 0;
+          m_modes[i].variance = 0;
+          m_modes[i].muR = 0;
+          m_modes[i].muG = 0;
+          m_modes[i].muB = 0;
+          m_modes[i].significants = 0;
+        }
+
+        for (unsigned int j = 0; j < m_params.Size(); ++j)
+        {
+          m_state[j].State = background;
+          m_state[j].Ab2b = 0.7f;
+          m_state[j].Ab2f = 0.3f;
+          m_state[j].Af2b = 0.4f;
+          m_state[j].Af2f = 0.6f;
+          m_state[j].T = 0.7f;
+        }
+      }
+
+      void T2FMRF::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
+      {
+        // it doesn't make sense to have conditional updates in the GMM framework
+      }
+
+      void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, unsigned char& numModes,
+        unsigned char& low_threshold, unsigned char& high_threshold)
+      {
+        // calculate distances to the modes (+ sort???)
+        // here we need to go in descending order!!!
+        long pos;
+        bool bFitsPDF = false;
+        bool bBackgroundLow = false;
+        bool bBackgroundHigh = false;
+
+        HiddenState CurrentState = m_state[posPixel].State;
+        float Ab2b = m_state[posPixel].Ab2b;
+        float Ab2f = m_state[posPixel].Ab2f;
+        float Af2b = m_state[posPixel].Af2b;
+        float Af2f = m_state[posPixel].Af2f;
+        //float T = m_state[posPixel].T;
+
+        float fOneMinAlpha = 1 - m_params.Alpha();
+        float totalWeight = 0.0f;
+
+        // calculate number of Gaussians to include in the background model
+        int backgroundGaussians = 0;
+        double sum = 0.0;
+        for (int i = 0; i < numModes; ++i)
+        {
+          if (sum < m_bg_threshold)
+          {
+            backgroundGaussians++;
+            sum += m_modes[posGMode + i].weight;
+          }
+          else
+            break;
+        }
+
+        // update all distributions and check for match with current pixel
+        for (int iModes = 0; iModes < numModes; iModes++)
+        {
+          pos = posGMode + iModes;
+          float weight = m_modes[pos].weight;
+
+          // fit not found yet
+          if (!bFitsPDF)
+          {
+            //check if it belongs to some of the modes
+            //calculate distance
+            float var = m_modes[pos].variance;
+            float muR = m_modes[pos].muR;
+            float muG = m_modes[pos].muG;
+            float muB = m_modes[pos].muB;
+
+            //float km = 2;
+            //float kv = 0.9;
+
+            float dR = fabs(muR - pixel(0));
+            float dG = fabs(muG - pixel(1));
+            float dB = fabs(muB - pixel(2));
+
+            // calculate the squared distance
+            float HR;
+            float HG;
+            float HB;
+
+            // T2FMRF-UM
+            if (m_params.Type() == TYPE_T2FMRF_UM)
+            {
+              if ((pixel(0) < muR - km*var) || (pixel(0) > muR + km*var))
+                HR = 2 * km*dR / var;
+              else
+                HR = dR*dR / (2 * var*var) + km*dR / var + km*km / 2;
+
+              if ((pixel(1) < muG - km*var) || (pixel(1) > muG + km*var))
+                HG = 2 * km*dG / var;
+              else
+                HG = dG*dG / (2 * var*var) + km*dG / var + km*km / 2;
+
+              if ((pixel(2) < muB - km*var) || (pixel(2) > muB + km*var))
+                HB = 2 * km*dB / var;
+              else
+                HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2;
+            }
+
+            // T2FGMM-UV
+            if (m_params.Type() == TYPE_T2FMRF_UV)
+            {
+              HR = (1 / (kv*kv) - kv*kv) * (pixel(0) - muR) * (pixel(0) - muR) / (2 * var);
+              HG = (1 / (kv*kv) - kv*kv) * (pixel(1) - muG) * (pixel(1) - muG) / (2 * var);
+              HB = (1 / (kv*kv) - kv*kv) * (pixel(2) - muB) * (pixel(2) - muB) / (2 * var);
+            }
+
+            float ro;
+            if (CurrentState == background)
+            {
+              if (Ab2b != 0) ro = (Ab2f / Ab2b);
+              else ro = 10;
+            }
+            else
+            {
+              if (Af2b != 0) ro = (Af2f / Af2b);
+              else ro = 10;
+            }
+
+            // calculate the squared distance
+            float dist = (HR*HR + HG*HG + HB*HB);
+
+            if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
+              bBackgroundHigh = true;
+
+            // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
+            if (dist < m_params.LowThreshold()*var)
+            {
+              bFitsPDF = true;
+
+              // check if this Gaussian is part of the background model
+              if (iModes < backgroundGaussians)
+                bBackgroundLow = true;
+
+              //update distribution
+              float k = m_params.Alpha() / weight;
+              weight = fOneMinAlpha*weight + m_params.Alpha();
+              m_modes[pos].weight = weight;
+              m_modes[pos].muR = muR - k*(dR);
+              m_modes[pos].muG = muG - k*(dG);
+              m_modes[pos].muB = muB - k*(dB);
+
+              //limit the variance
+              float sigmanew = var + k*(dist - var);
+              m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+            else
+            {
+              weight = fOneMinAlpha*weight;
+              if (weight < 0.0)
+              {
+                weight = 0.0;
+                numModes--;
+              }
+
+              m_modes[pos].weight = weight;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+          }
+          else
+          {
+            weight = fOneMinAlpha*weight;
+            if (weight < 0.0)
+            {
+              weight = 0.0;
+              numModes--;
+            }
+            m_modes[pos].weight = weight;
+            m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+          }
+
+          totalWeight += weight;
+        }
+
+        // renormalize weights so they add to one
+        double invTotalWeight = 1.0 / totalWeight;
+        for (int iLocal = 0; iLocal < numModes; iLocal++)
+        {
+          m_modes[posGMode + iLocal].weight *= (float)invTotalWeight;
+          m_modes[posGMode + iLocal].significants = m_modes[posGMode + iLocal].weight / sqrt(m_modes[posGMode + iLocal].variance);
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&m_modes[posGMode], numModes, sizeof(GMM), compareT2FMRF);
+
+        // make new mode if needed and exit
+        if (!bFitsPDF)
+        {
+          if (numModes < m_params.MaxModes())
+            numModes++;
+          //else
+          // the weakest mode will be replaced
+
+          pos = posGMode + numModes - 1;
+
+          m_modes[pos].muR = pixel.ch[0];
+          m_modes[pos].muG = pixel.ch[1];
+          m_modes[pos].muB = pixel.ch[2];
+          m_modes[pos].variance = m_variance;
+          m_modes[pos].significants = 0;			// will be set below
+
+          if (numModes == 1)
+            m_modes[pos].weight = 1;
+          else
+            m_modes[pos].weight = m_params.Alpha();
+
+          //renormalize weights
+          int iLocal;
+          float sum = 0.0;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+            sum += m_modes[posGMode + iLocal].weight;
+
+          double invSum = 1.0 / sum;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+          {
+            m_modes[posGMode + iLocal].weight *= (float)invSum;
+            m_modes[posGMode + iLocal].significants = m_modes[posPixel + iLocal].weight / sqrt(m_modes[posGMode + iLocal].variance);
+          }
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&(m_modes[posGMode]), numModes, sizeof(GMM), compareT2FMRF);
+
+        if (bBackgroundLow)
+        {
+          low_threshold = BACKGROUND;
+          m_state[posPixel].State = background;
+
+          if (CurrentState == background)
+          {
+            float b2b = fOneMinAlpha*Ab2b + m_params.Alpha();
+            float b2f = fOneMinAlpha*Ab2f;
+
+            float b = b2b + b2f;
+            m_state[posPixel].Ab2b = b2b / b;
+            m_state[posPixel].Ab2f = b2f / b;
+            m_state[posPixel].T = m_state[posPixel].Ab2b;
+          }
+          else
+          {
+            float f2b = fOneMinAlpha*Af2b + m_params.Alpha();
+            float f2f = fOneMinAlpha*Af2f;
+
+            float f = f2b + f2f;
+            m_state[posPixel].Af2b = f2b / f;
+            m_state[posPixel].Af2f = f2f / f;
+            m_state[posPixel].T = m_state[posPixel].Af2b;
+          }
+        }
+        else
+        {
+          low_threshold = FOREGROUND;
+          m_state[posPixel].State = foreground;
+
+          if (CurrentState == background)
+          {
+            float b2b = fOneMinAlpha*Ab2b;
+            float b2f = fOneMinAlpha*Ab2f + m_params.Alpha();
+
+            float b = b2b + b2f;
+            m_state[posPixel].Ab2b = b2b / b;
+            m_state[posPixel].Ab2f = b2f / b;
+            m_state[posPixel].T = m_state[posPixel].Ab2b;
+          }
+          else
+          {
+            float f2b = fOneMinAlpha*Af2b;
+            float f2f = fOneMinAlpha*Af2f + m_params.Alpha();
+
+            float f = f2b + f2f;
+            m_state[posPixel].Af2b = f2b / f;
+            m_state[posPixel].Af2f = f2f / f;
+            m_state[posPixel].T = m_state[posPixel].Af2b;
+          }
+        }
+
+        if (bBackgroundHigh)
+          high_threshold = BACKGROUND;
+        else
+          high_threshold = FOREGROUND;
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////
+      //Input:
+      //  data - a pointer to the data of a RGB image of the same size
+      //Output:
+      //  output - a pointer to the data of a gray value image of the same size 
+      //					(the memory should already be reserved) 
+      //					values: 255-foreground, 125-shadow, 0-background
+      ///////////////////////////////////////////////////////////////////////////////
+      void T2FMRF::Subtract(int frame_num, const RgbImage& data,
+        BwImage& low_threshold_mask, BwImage& high_threshold_mask)
+      {
+        unsigned char low_threshold, high_threshold;
+        long posPixel;
+        long posGMode;
+
+        // update each pixel of the image
+        for (unsigned int r = 0; r < m_params.Height(); ++r)
+        {
+          for (unsigned int c = 0; c < m_params.Width(); ++c)
+          {
+            // update model + background subtract
+            posPixel = r*m_params.Width() + c;
+            posGMode = (r*m_params.Width() + c) * m_params.MaxModes();
+
+            SubtractPixel(posPixel, posGMode, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
+
+            low_threshold_mask(r, c) = low_threshold;
+            high_threshold_mask(r, c) = high_threshold;
+
+            m_background(r, c, 0) = (unsigned char)m_modes[posGMode].muR;
+            m_background(r, c, 1) = (unsigned char)m_modes[posGMode].muG;
+            m_background(r, c, 2) = (unsigned char)m_modes[posGMode].muB;
+          }
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2F/T2FMRF.h b/src/algorithms/T2F/T2FMRF.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f79e802634b7655041d2fb4f9dc1d3a198514b7
--- /dev/null
+++ b/src/algorithms/T2F/T2FMRF.h
@@ -0,0 +1,139 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "../dp/Bgs.h"
+#include "../dp/GrimsonGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      const int TYPE_T2FMRF_UM = 0;
+      const int TYPE_T2FMRF_UV = 1;
+
+      enum HiddenState { background, foreground };
+
+      typedef struct HMMState
+      {
+        float T;
+        //Hidden State
+        HiddenState State;
+        //transition probability
+        float Ab2b;
+        float Ab2f;
+        float Af2f;
+        float Af2b;
+      } HMM;
+
+      //typedef struct GMMGaussian
+      //{
+      //  float variance;
+      //  float muR;
+      //  float muG;
+      //  float muB;
+      //  float weight;
+      //  float significants; // this is equal to weight / standard deviation and is used to
+      //  // determine which Gaussians should be part of the background model
+      //} GMM;
+
+      // --- User adjustable parameters used by the T2F GMM BGS algorithm ---
+      class T2FMRFParams : public BgsParams
+      {
+      public:
+        float &LowThreshold() { return m_low_threshold; }
+        float &HighThreshold() { return m_high_threshold; }
+
+        float &Alpha() { return m_alpha; }
+        int &MaxModes() { return m_max_modes; }
+        int &Type() { return m_type; }
+        float &KM() { return m_km; }
+        float &KV() { return m_kv; }
+
+      private:
+        // Threshold on the squared dist. to decide when a sample is close to an existing
+        // components. If it is not close to any a new component will be generated.
+        // Smaller threshold values lead to more generated components and higher threshold values
+        // lead to a small number of components but they can grow too large.
+        //
+        // It is usual easiest to think of these thresholds as being the number of variances away
+        // from the mean of a pixel before it is considered to be from the foreground.
+        float m_low_threshold;
+        float m_high_threshold;
+
+        // alpha - speed of update - if the time interval you want to average over is T
+        // set alpha=1/T.
+        float m_alpha;
+
+        // Maximum number of modes (Gaussian components) that will be used per pixel
+        int m_max_modes;
+
+        // T2FMRF_UM / T2FMRF_UV
+        int m_type;
+
+        // Factor control for the T2FMRF-UM
+        float m_km;
+
+        // Factor control for the T2FMRF-UV
+        float m_kv;
+      };
+
+      // --- T2FGMM BGS algorithm ---
+      class T2FMRF : public Bgs
+      {
+      public:
+        T2FMRF();
+        ~T2FMRF();
+
+        void Initalize(const BgsParams& param);
+        void InitModel(const RgbImage& data);
+        void Subtract(int frame_num, const RgbImage& data, BwImage& low_threshold_mask, BwImage& high_threshold_mask);
+        void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
+
+        RgbImage* Background();
+
+        GMM *gmm(void);
+        HMM *hmm(void);
+
+      private:
+        void SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold);
+
+        // User adjustable parameters
+        T2FMRFParams m_params;
+
+        // Threshold when the component becomes significant enough to be included into
+        // the background model. It is the TB = 1-cf from the paper. So I use cf=0.1 => TB=0.9
+        // For alpha=0.001 it means that the mode should exist for approximately 105 frames before
+        // it is considered foreground
+        float m_bg_threshold; //1-cf from the paper
+
+        // Initial variance for the newly generated components.
+        // It will will influence the speed of adaptation. A good guess should be made.
+        // A simple way is to estimate the typical standard deviation from the images.
+        float m_variance;
+
+        // Dynamic array for the mixture of Gaussians
+        GMM* m_modes;
+
+        //Dynamic array for the hidden state
+        HMM* m_state;
+
+        // Number of Gaussian components per pixel
+        BwImage m_modes_per_pixel;
+
+        // Current background model
+        RgbImage m_background;
+
+        // Factor control for the T2FGMM-UM
+        float km;
+        // Factor control for the T2FGMM-UV
+        float kv;
+      };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2FGMM_UM.cpp b/src/algorithms/T2FGMM_UM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..808eea1dfb694cf4692403e4a582e1e09eb89105
--- /dev/null
+++ b/src/algorithms/T2FGMM_UM.cpp
@@ -0,0 +1,97 @@
+#include "T2FGMM_UM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+T2FGMM_UM::T2FGMM_UM() :
+  IBGS(quote(T2FGMM_UM)),
+  frameNumber(0), threshold(9.0), alpha(0.01), 
+  km(1.5f), kv(0.6f), gaussians(3)
+{
+  debug_construction(T2FGMM_UM);
+  initLoadSaveConfig(algorithmName);
+}
+
+T2FGMM_UM::~T2FGMM_UM() {
+  debug_destruction(T2FGMM_UM);
+}
+
+void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold;
+    params.HighThreshold() = 2 * params.LowThreshold();
+    params.Alpha() = alpha;
+    params.MaxModes() = gaussians;
+    params.Type() = dp::TYPE_T2FGMM_UM;
+    params.KM() = km; // Factor control for the T2FGMM-UM [0,3] default: 1.5
+    params.KV() = kv; // Factor control for the T2FGMM-UV [0.3,1] default: 0.6
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void T2FGMM_UM::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "km" << km;
+  fs << "kv" << kv;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
+}
+
+void T2FGMM_UM::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["km"] >> km;
+  fs["kv"] >> kv;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/T2FGMM_UM.h b/src/algorithms/T2FGMM_UM.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f3185a042faff634afa03d7661f050a4eea1b21
--- /dev/null
+++ b/src/algorithms/T2FGMM_UM.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "T2F/T2FGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class T2FGMM_UM : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      float km;
+      float kv;
+      int gaussians;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::T2FGMMParams params;
+      dp::T2FGMM bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      T2FGMM_UM();
+      ~T2FGMM_UM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(T2FGMM_UM);
+  }
+}
+
+#endif
diff --git a/src/algorithms/T2FGMM_UV.cpp b/src/algorithms/T2FGMM_UV.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7137a167b5be5f923bdc76da9dd4b8c2c667552
--- /dev/null
+++ b/src/algorithms/T2FGMM_UV.cpp
@@ -0,0 +1,97 @@
+#include "T2FGMM_UV.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+T2FGMM_UV::T2FGMM_UV() :
+  IBGS(quote(T2FGMM_UV)),
+  frameNumber(0), threshold(9.0), alpha(0.01), 
+  km(1.5f), kv(0.6f), gaussians(3)
+{
+  debug_construction(T2FGMM_UV);
+  initLoadSaveConfig(algorithmName);
+}
+
+T2FGMM_UV::~T2FGMM_UV() {
+  debug_destruction(T2FGMM_UV);
+}
+
+void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+  
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime)
+    frame_data.ReleaseMemory(false);
+  frame_data = frame;
+
+  if (firstTime) {
+    int width = img_input.size().width;
+    int height = img_input.size().height;
+
+    lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    lowThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    highThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
+    highThresholdMask.Ptr()->origin = IPL_ORIGIN_BL;
+
+    params.SetFrameSize(width, height);
+    params.LowThreshold() = threshold;
+    params.HighThreshold() = 2 * params.LowThreshold();
+    params.Alpha() = alpha;
+    params.MaxModes() = gaussians;
+    params.Type() = dp::TYPE_T2FGMM_UV;
+    params.KM() = km; // Factor control for the T2FGMM-UM [0,3] default: 1.5
+    params.KV() = kv; // Factor control for the T2FGMM-UV [0.3,1] default: 0.6
+
+    bgs.Initalize(params);
+    bgs.InitModel(frame_data);
+  }
+
+  bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask);
+  lowThresholdMask.Clear();
+  bgs.Update(frameNumber, frame_data, lowThresholdMask);
+
+  img_foreground = cv::cvarrToMat(highThresholdMask.Ptr());
+  img_background = cv::cvarrToMat(bgs.Background()->Ptr());
+  //img_background = cv::Mat::zeros(img_input.size(), img_input.type());
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_foreground);
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+  frameNumber++;
+}
+
+void T2FGMM_UV::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "km" << km;
+  fs << "kv" << kv;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
+}
+
+void T2FGMM_UV::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["km"] >> km;
+  fs["kv"] >> kv;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/T2FGMM_UV.h b/src/algorithms/T2FGMM_UV.h
new file mode 100644
index 0000000000000000000000000000000000000000..6c00688642637f9e66274058c393f51e26359661
--- /dev/null
+++ b/src/algorithms/T2FGMM_UV.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "T2F/T2FGMM.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class T2FGMM_UV : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      float km;
+      float kv;
+      int gaussians;
+      IplImage* frame;
+      dp::RgbImage frame_data;
+      dp::T2FGMMParams params;
+      dp::T2FGMM bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+
+    public:
+      T2FGMM_UV();
+      ~T2FGMM_UV();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(T2FGMM_UV);
+  }
+}
+
+#endif
diff --git a/package_bgs/T2FMRF_UM.cpp b/src/algorithms/T2FMRF_UM.cpp
similarity index 58%
rename from package_bgs/T2FMRF_UM.cpp
rename to src/algorithms/T2FMRF_UM.cpp
index e0e6dae44dc315f70e0c5b93ca817438f656da17..3b712f9fbbc1c5ec4c7ee4b727719c5448b0507f 100644
--- a/package_bgs/T2FMRF_UM.cpp
+++ b/src/algorithms/T2FMRF_UM.cpp
@@ -1,46 +1,38 @@
-/*
-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 "T2FMRF_UM.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 using namespace bgslibrary::algorithms;
 
 T2FMRF_UM::T2FMRF_UM() :
-  frameNumber(0), threshold(9.0), alpha(0.01), km(2.f), kv(0.9f), gaussians(3)
+  IBGS(quote(T2FMRF_UM)),
+  frameNumber(0), threshold(9.0), alpha(0.01), 
+  km(2.f), kv(0.9f), gaussians(3)
 {
-  std::cout << "T2FMRF_UM()" << std::endl;
-  setup("./config/DPMean.xml");
+  debug_construction(T2FMRF_UM);
+  initLoadSaveConfig(algorithmName);
 }
 
-T2FMRF_UM::~T2FMRF_UM()
-{
-  std::cout << "~T2FMRF_UM()" << std::endl;
+T2FMRF_UM::~T2FMRF_UM() {
+  debug_destruction(T2FMRF_UM);
 }
 
 void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
 {
   init(img_input, img_output, img_bgmodel);
+  
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
   frame = new IplImage(img_input);
+#endif
 
   if (firstTime)
     frame_data.ReleaseMemory(false);
   frame_data = frame;
 
-  if (firstTime)
-  {
+  if (firstTime) {
     int width = img_input.size().width;
     int height = img_input.size().height;
 
@@ -55,7 +47,7 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
     params.HighThreshold() = 2 * params.LowThreshold();
     params.Alpha() = alpha;
     params.MaxModes() = gaussians;
-    params.Type() = TYPE_T2FMRF_UM;
+    params.Type() = dp::TYPE_T2FMRF_UM;
     params.KM() = km; // Factor control for the T2FMRF-UM [0,3] default: 2
     params.KV() = kv; // Factor control for the T2FMRF-UV [0.3,1] default: 0.9
 
@@ -102,7 +94,7 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
 
 #ifndef MEX_COMPILE_FLAG
   if (showOutput)
-    cv::imshow("T2FMRF-UM", img_foreground);
+    cv::imshow(algorithmName + "_FG", img_foreground);
 #endif
 
   img_foreground.copyTo(img_output);
@@ -112,30 +104,22 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
   frameNumber++;
 }
 
-void T2FMRF_UM::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "km", km);
-  cvWriteReal(fs, "kv", kv);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void T2FMRF_UM::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "km" << km;
+  fs << "kv" << kv;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
 }
 
-void T2FMRF_UM::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 9.0);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.01);
-  km = cvReadRealByName(fs, nullptr, "km", 2);
-  kv = cvReadRealByName(fs, nullptr, "kv", 0.9);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void T2FMRF_UM::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["km"] >> km;
+  fs["kv"] >> kv;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
 }
+
+#endif
diff --git a/src/algorithms/T2FMRF_UM.h b/src/algorithms/T2FMRF_UM.h
new file mode 100644
index 0000000000000000000000000000000000000000..9761ae6b15025516f0773df390681922bff492e2
--- /dev/null
+++ b/src/algorithms/T2FMRF_UM.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "T2F/MRF.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class T2FMRF_UM : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      float km;
+      float kv;
+      int gaussians;
+      IplImage *frame;
+      IplImage *old_labeling;
+      IplImage *old;
+      dp::RgbImage frame_data;
+      dp::T2FMRFParams params;
+      dp::T2FMRF bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+      dp::MRF_TC mrf;
+      dp::GMM *gmm;
+      dp::HMM *hmm;
+
+    public:
+      T2FMRF_UM();
+      ~T2FMRF_UM();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(T2FMRF_UM);
+  }
+}
+
+#endif
diff --git a/package_bgs/T2FMRF_UV.cpp b/src/algorithms/T2FMRF_UV.cpp
similarity index 58%
rename from package_bgs/T2FMRF_UV.cpp
rename to src/algorithms/T2FMRF_UV.cpp
index 7f43c027541c7953b9aa91c2031ff0b256b8e729..f918c6f47b23fa6e423fc29bc6135fbc123ced2c 100644
--- a/package_bgs/T2FMRF_UV.cpp
+++ b/src/algorithms/T2FMRF_UV.cpp
@@ -1,46 +1,38 @@
-/*
-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 "T2FMRF_UV.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
 using namespace bgslibrary::algorithms;
 
 T2FMRF_UV::T2FMRF_UV() :
-  frameNumber(0), threshold(9.0), alpha(0.01), km(2.f), kv(0.9f), gaussians(3)
+  IBGS(quote(T2FMRF_UV)),
+  frameNumber(0), threshold(9.0), alpha(0.01), 
+  km(2.f), kv(0.9f), gaussians(3)
 {
-  std::cout << "T2FMRF_UV()" << std::endl;
-  setup("./config/T2FMRF_UV.xml");
+  debug_construction(T2FMRF_UV);
+  initLoadSaveConfig(algorithmName);
 }
 
-T2FMRF_UV::~T2FMRF_UV()
-{
-  std::cout << "~T2FMRF_UV()" << std::endl;
+T2FMRF_UV::~T2FMRF_UV() {
+  debug_destruction(T2FMRF_UV);
 }
 
 void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
 {
   init(img_input, img_output, img_bgmodel);
+  
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
   frame = new IplImage(img_input);
+#endif
 
   if (firstTime)
     frame_data.ReleaseMemory(false);
   frame_data = frame;
 
-  if (firstTime)
-  {
+  if (firstTime) {
     int width = img_input.size().width;
     int height = img_input.size().height;
 
@@ -55,7 +47,7 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
     params.HighThreshold() = 2 * params.LowThreshold();
     params.Alpha() = alpha;
     params.MaxModes() = gaussians;
-    params.Type() = TYPE_T2FMRF_UV;
+    params.Type() = dp::TYPE_T2FMRF_UV;
     params.KM() = km; // Factor control for the T2FMRF-UM [0,3] default: 2
     params.KV() = kv; // Factor control for the T2FMRF-UV [0.3,1] default: 0.9
 
@@ -102,7 +94,7 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
 
 #ifndef MEX_COMPILE_FLAG
   if (showOutput)
-    cv::imshow("T2FMRF-UV", img_foreground);
+    cv::imshow(algorithmName + "_FG", img_foreground);
 #endif
 
   img_foreground.copyTo(img_output);
@@ -112,30 +104,22 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &
   frameNumber++;
 }
 
-void T2FMRF_UV::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteReal(fs, "threshold", threshold);
-  cvWriteReal(fs, "alpha", alpha);
-  cvWriteReal(fs, "km", km);
-  cvWriteReal(fs, "kv", kv);
-  cvWriteInt(fs, "gaussians", gaussians);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void T2FMRF_UV::save_config(cv::FileStorage &fs) {
+  fs << "threshold" << threshold;
+  fs << "alpha" << alpha;
+  fs << "km" << km;
+  fs << "kv" << kv;
+  fs << "gaussians" << gaussians;
+  fs << "showOutput" << showOutput;
 }
 
-void T2FMRF_UV::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  threshold = cvReadRealByName(fs, nullptr, "threshold", 9.0);
-  alpha = cvReadRealByName(fs, nullptr, "alpha", 0.01);
-  km = cvReadRealByName(fs, nullptr, "km", 2);
-  kv = cvReadRealByName(fs, nullptr, "kv", 0.9);
-  gaussians = cvReadIntByName(fs, nullptr, "gaussians", 3);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void T2FMRF_UV::load_config(cv::FileStorage &fs) {
+  fs["threshold"] >> threshold;
+  fs["alpha"] >> alpha;
+  fs["km"] >> km;
+  fs["kv"] >> kv;
+  fs["gaussians"] >> gaussians;
+  fs["showOutput"] >> showOutput;
 }
+
+#endif
diff --git a/src/algorithms/T2FMRF_UV.h b/src/algorithms/T2FMRF_UV.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef2519b6d3f1db68e7b5f2caa4b844fd0540bd9d
--- /dev/null
+++ b/src/algorithms/T2FMRF_UV.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "T2F/MRF.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class T2FMRF_UV : public IBGS
+    {
+    private:
+      long frameNumber;
+      double threshold;
+      double alpha;
+      float km;
+      float kv;
+      int gaussians;
+      IplImage *frame;
+      IplImage *old_labeling;
+      IplImage *old;
+      dp::RgbImage frame_data;
+      dp::T2FMRFParams params;
+      dp::T2FMRF bgs;
+      dp::BwImage lowThresholdMask;
+      dp::BwImage highThresholdMask;
+      dp::MRF_TC mrf;
+      dp::GMM *gmm;
+      dp::HMM *hmm;
+
+    public:
+      T2FMRF_UV();
+      ~T2FMRF_UV();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(T2FMRF_UV);
+  }
+}
+
+#endif
diff --git a/src/algorithms/TwoPoints.cpp b/src/algorithms/TwoPoints.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b554ea8eb11d7feec1309f84885b848d558f3ab
--- /dev/null
+++ b/src/algorithms/TwoPoints.cpp
@@ -0,0 +1,81 @@
+#include "TwoPoints.h"
+
+using namespace bgslibrary::algorithms;
+
+TwoPoints::TwoPoints() :
+  IBGS(quote(TwoPoints)),
+  matchingThreshold(DEFAULT_MATCH_THRESH),
+  updateFactor(DEFAULT_UPDATE_FACTOR), model(nullptr)
+{
+  debug_construction(TwoPoints);
+  initLoadSaveConfig(algorithmName);
+  //model = static_cast<twopointsModel_t*>(libtwopointsModel_New());
+  model = twopoints::libtwopointsModel_New();
+}
+
+TwoPoints::~TwoPoints() {
+  debug_destruction(TwoPoints);
+  twopoints::libtwopointsModel_Free(model);
+}
+
+void TwoPoints::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (img_input.empty())
+    return;
+
+  cv::Mat updatingMask;
+  cv::Mat img_input_grayscale;
+
+  // Convert input image to a grayscale image
+  cvtColor(img_input, img_input_grayscale, CV_BGR2GRAY);
+
+  if (firstTime) {
+    // Create a buffer for the output image.
+    //img_output = Mat(img_input.rows, img_input.cols, CV_8UC1);
+
+    // Initialization of the ViBe model.
+    twopoints::libtwopointsModel_AllocInit_8u_C1R(model, img_input_grayscale.data, img_input.cols, img_input.rows);
+
+    // Sets default model values.
+    // twopoints::libvibeModel_Sequential_SetMatchingThreshold(model, matchingThreshold);
+    // twopoints::libvibeModel_Sequential_SetUpdateFactor(model, updateFactor);
+  }
+
+  twopoints::libtwopointsModel_Segmentation_8u_C1R(model, img_input_grayscale.data, img_output.data);
+
+  updatingMask = cv::Mat(img_input.rows, img_input.cols, CV_8UC1);
+  // Work on the output and define the updating mask
+  for (int i = 0; i < img_input.cols * img_input.rows; i++) {
+    if (img_output.data[i] == 0) { // Foreground pixel
+      updatingMask.data[i] = 0;
+      img_output.data[i] = 255;
+    }
+    else { // Background
+      updatingMask.data[i] = 255;
+      img_output.data[i] = 0;
+    }
+  }
+
+  twopoints::libtwopointsModel_Update_8u_C1R(model, img_input_grayscale.data, updatingMask.data);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_output);
+#endif
+
+  firstTime = false;
+}
+
+void TwoPoints::save_config(cv::FileStorage &fs) {
+  fs << "matchingThreshold" << matchingThreshold;
+  fs << "updateFactor" << updateFactor;
+  fs << "showOutput" << showOutput;
+}
+
+void TwoPoints::load_config(cv::FileStorage &fs) {
+  fs["matchingThreshold"] >> matchingThreshold;
+  fs["updateFactor"] >> updateFactor;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/TwoPoints.h b/src/algorithms/TwoPoints.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a1ef25a73c36ec63129a68856c7760442ce8a2d
--- /dev/null
+++ b/src/algorithms/TwoPoints.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "IBGS.h"
+#include "TwoPoints/two_points.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class TwoPoints : public IBGS
+    {
+    private:
+      static const int DEFAULT_MATCH_THRESH = 20;
+      static const int DEFAULT_UPDATE_FACTOR = 16;
+      int matchingThreshold;
+      int updateFactor;
+      twopoints::twopointsModel_t* model;
+
+    public:
+      TwoPoints();
+      ~TwoPoints();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(TwoPoints);
+  }
+}
diff --git a/src/algorithms/TwoPoints/two_points.cpp b/src/algorithms/TwoPoints/two_points.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ba29ed822d67411eb3ce8f3416431ce08a265b3
--- /dev/null
+++ b/src/algorithms/TwoPoints/two_points.cpp
@@ -0,0 +1,388 @@
+#include <assert.h>
+
+#include "two_points.h"
+
+//using namespace bgslibrary::algorithms::twopoints;
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace twopoints
+    {
+      static unsigned int abs_uint(const int i)
+      {
+        return (i >= 0) ? i : -i;
+      }
+
+      struct twopointsModel
+      {
+        /* Parameters. */
+        uint32_t width;
+        uint32_t height;
+        uint32_t numberOfSamples;
+        uint32_t matchingThreshold;
+        uint32_t matchingNumber;
+        uint32_t updateFactor;
+
+        /* Storage for the history. */
+        uint8_t *historyImage1;
+        uint8_t *historyImage2;
+
+        /* Buffers with random values. */
+        uint32_t *jump;
+        int *neighbor;
+      };
+
+      // -----------------------------------------------------------------------------
+      // Creates the data structure
+      // -----------------------------------------------------------------------------
+      twopointsModel_t *libtwopointsModel_New()
+      {
+        /* Model structure alloc. */
+        twopointsModel_t *model = NULL;
+        model = (twopointsModel_t*)calloc(1, sizeof(*model));
+        assert(model != NULL);
+
+        /* Default parameters values. */
+        model->matchingThreshold = 20;
+        model->updateFactor = 16;
+
+        /* Storage for the history. */
+        model->historyImage1 = NULL;
+        model->historyImage2 = NULL;
+
+        /* Buffers with random values. */
+        model->jump = NULL;
+        model->neighbor = NULL;
+
+        return(model);
+      }
+
+      // ----------------------------------------------------------------------------
+      // Frees the structure
+      // ----------------------------------------------------------------------------
+      int32_t libtwopointsModel_Free(twopointsModel_t *model)
+      {
+        if (model == NULL)
+          return(-1);
+
+        if (model->historyImage1 != NULL) {
+          free(model->historyImage1);
+          model->historyImage1 = NULL;
+        }
+        if (model->historyImage2 != NULL) {
+          free(model->historyImage2);
+          model->historyImage2 = NULL;
+        }
+        if (model->jump != NULL) {
+          free(model->jump);
+          model->jump = NULL;
+        }
+        if (model->neighbor != NULL) {
+          free(model->neighbor);
+          model->neighbor = NULL;
+        }
+        free(model);
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Allocates and initializes a C1R model structure
+      // -----------------------------------------------------------------------------
+      int32_t libtwopointsModel_AllocInit_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      )
+      {
+        // Some basic checks. */
+        assert((image_data != NULL) && (model != NULL));
+        assert((width > 0) && (height > 0));
+
+        /* Finish model alloc - parameters values cannot be changed anymore. */
+        model->width = width;
+        model->height = height;
+
+        /* Creates the historyImage structure. */
+        model->historyImage1 = NULL;
+        model->historyImage1 = (uint8_t*)malloc(width * height * sizeof(uint8_t));
+        model->historyImage2 = NULL;
+        model->historyImage2 = (uint8_t*)malloc(width * height * sizeof(uint8_t));
+
+        assert(model->historyImage1 != NULL);
+        assert(model->historyImage2 != NULL);
+
+        for (int index = width * height - 1; index >= 0; --index) {
+          uint8_t value = image_data[index];
+
+          int value_plus_noise = value - 10;
+          if (value_plus_noise < 0) { value_plus_noise = 0; }
+          if (value_plus_noise > 255) { value_plus_noise = 255; }
+          model->historyImage1[index] = value_plus_noise;
+
+          value_plus_noise = value + 10;
+          if (value_plus_noise < 0) { value_plus_noise = 0; }
+          if (value_plus_noise > 255) { value_plus_noise = 255; }
+          model->historyImage2[index] = value_plus_noise;
+
+          // Swaps the two values if needed
+          if (model->historyImage1[index] > model->historyImage2[index]) {
+            uint8_t val = model->historyImage1[index];
+            model->historyImage1[index] = model->historyImage2[index];
+            model->historyImage2[index] = val;
+          }
+        }
+
+        /* Fills the buffers with random values. */
+        int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
+
+        model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
+        assert(model->jump != NULL);
+
+        model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
+        assert(model->neighbor != NULL);
+
+
+        for (int i = 0; i < size; ++i) {
+          model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
+          model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { -width - 1, ... , width + 1 }.
+        }
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Segmentation of a C1R model
+      // -----------------------------------------------------------------------------
+      int32_t libtwopointsModel_Segmentation_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      )
+      {
+        assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert((model->jump != NULL) && (model->neighbor != NULL));
+
+        /* Some variables. */
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+        uint32_t matchingThreshold = model->matchingThreshold;
+
+        uint8_t *historyImage1 = model->historyImage1;
+        uint8_t *historyImage2 = model->historyImage2;
+
+        /* Segmentation. */
+        memset(segmentation_map, 0, width * height);
+
+        uint8_t *first = historyImage1;
+        for (int index = width * height - 1; index >= 0; --index) {
+          // We adapt the threshold
+          matchingThreshold = model->matchingThreshold;
+          if (matchingThreshold < abs_uint(historyImage2[index] - historyImage1[index])) {
+            matchingThreshold = abs_uint(historyImage2[index] - historyImage1[index]);
+          }
+          if (abs_uint(image_data[index] - first[index]) <= matchingThreshold)
+            segmentation_map[index]++;
+        }
+
+        first = historyImage2;
+        for (int index = width * height - 1; index >= 0; --index) {
+          // We adapt the threshold
+          matchingThreshold = model->matchingThreshold;
+          if (matchingThreshold < abs_uint(historyImage2[index] - historyImage1[index])) {
+            matchingThreshold = abs_uint(historyImage2[index] - historyImage1[index]);
+          }
+          if (abs_uint(image_data[index] - first[index]) <= matchingThreshold)
+            segmentation_map[index]++;
+        }
+
+        return(0);
+      }
+
+      // ----------------------------------------------------------------------------
+      // Update a C1R model
+      // ----------------------------------------------------------------------------
+      int doUpdate(const uint8_t value)
+      {
+        if (value == 0) return 0;
+        else return 1;
+      }
+
+
+      int32_t libtwopointsModel_Update_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      )
+      {
+        assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert((model->jump != NULL) && (model->neighbor != NULL));
+
+        // Some variables.
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+
+        uint8_t *historyImage1 = model->historyImage1;
+        uint8_t *historyImage2 = model->historyImage2;
+
+        // Updating.
+        uint32_t *jump = model->jump;
+        int *neighbor = model->neighbor;
+
+        // All the frame, except the border.
+        uint32_t shift, indX, indY;
+        unsigned int x, y;
+
+        for (y = 1; y < height - 1; ++y) {
+          shift = rand() % width;
+          indX = jump[shift]; // index_jump should never be zero (> 1).
+
+          while (indX < width - 1) {
+            int index = indX + y * width;
+
+            if (doUpdate(updating_mask[index])) {
+              uint8_t value = image_data[index];
+              // In-place substitution.
+              // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
+              if (rand() % 2 == 0) {
+                historyImage1[index] = value;
+              }
+              else {
+                historyImage2[index] = value;
+              }
+
+              // Propagation
+              int index_neighbor = index + neighbor[shift];
+              if (2 * value < (historyImage1[index_neighbor] + historyImage2[index_neighbor])) {
+                // if (rand()%2 == 0 ) {
+                historyImage1[index_neighbor] = value;
+              }
+              else {
+                historyImage2[index_neighbor] = value;
+              }
+            }
+
+            ++shift;
+            indX += jump[shift];
+          }
+        }
+
+        // First row.
+        y = 0;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          if (doUpdate(updating_mask[index])) {
+            uint8_t value = image_data[index];
+            // In-place substitution.
+            // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
+            if (rand() % 2 == 0) {
+              historyImage1[index] = value;
+            }
+            else {
+              historyImage2[index] = value;
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        // Last row.
+        y = height - 1;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          if (doUpdate(updating_mask[index])) {
+            uint8_t value = image_data[index];
+            // In-place substitution.
+            // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
+            if (rand() % 2 == 0) {
+              historyImage1[index] = value;
+            }
+            else {
+              historyImage2[index] = value;
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        // First column.
+        x = 0;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          if (doUpdate(updating_mask[index])) {
+            uint8_t value = image_data[index];
+            // In-place substitution.
+            // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
+            if (rand() % 2 == 0) {
+              historyImage1[index] = value;
+            }
+            else {
+              historyImage2[index] = value;
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        // Last column.
+        x = width - 1;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          if (doUpdate(updating_mask[index])) {
+            uint8_t value = image_data[index];
+            // In-place substitution.
+            // if (2*value < (historyImage1[index]+historyImage2[index]) ) {
+            if (rand() % 2 == 0) {
+              historyImage1[index] = value;
+            }
+            else {
+              historyImage2[index] = value;
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        // The first pixel!
+        if (rand() % model->updateFactor == 0) {
+          if (doUpdate(updating_mask[0])) {
+            uint8_t value = image_data[0];
+            // In-place substitution.
+            if (rand() % 2 == 0) {
+              historyImage1[0] = value;
+            }
+            else {
+              historyImage2[0] = value;
+            }
+          }
+        }
+
+        return(0);
+      }
+    }
+  }
+}
diff --git a/src/algorithms/TwoPoints/two_points.h b/src/algorithms/TwoPoints/two_points.h
new file mode 100644
index 0000000000000000000000000000000000000000..f249fd3dd60dfc1ed4d3a21c52564723cb9c0fd1
--- /dev/null
+++ b/src/algorithms/TwoPoints/two_points.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace twopoints
+    {
+      const int COLOR_BACKGROUND = 0; /*!< Default label for background pixels */
+      const int COLOR_FOREGROUND = 255; /*!< Default label for foreground pixels. Note that some authors chose any value different from 0 instead */
+
+      typedef struct twopointsModel twopointsModel_t;
+
+      twopointsModel_t *libtwopointsModel_New();
+
+      int32_t libtwopointsModel_Free(twopointsModel_t *model);
+
+      int32_t libtwopointsModel_AllocInit_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      );
+
+      int32_t libtwopointsModel_Segmentation_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      );
+
+      int32_t libtwopointsModel_Update_8u_C1R(
+        twopointsModel_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      );
+    }
+  }
+}
diff --git a/src/algorithms/ViBe.cpp b/src/algorithms/ViBe.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..460b92673f62ddca29df0b8830c7a1a4aaeb1497
--- /dev/null
+++ b/src/algorithms/ViBe.cpp
@@ -0,0 +1,71 @@
+#include "ViBe.h"
+
+using namespace bgslibrary::algorithms;
+//using namespace bgslibrary::algorithms::vibe;
+
+ViBe::ViBe() :
+  IBGS(quote(ViBe)),
+  //numberOfSamples(DEFAULT_NUM_SAMPLES),
+  matchingThreshold(DEFAULT_MATCH_THRESH),
+  matchingNumber(DEFAULT_MATCH_NUM),
+  updateFactor(DEFAULT_UPDATE_FACTOR),
+  model(nullptr)
+{
+  debug_construction(ViBe);
+  initLoadSaveConfig(algorithmName);
+  model = vibe::libvibeModel_Sequential_New();
+}
+
+ViBe::~ViBe() {
+  debug_destruction(ViBe);
+  vibe::libvibeModel_Sequential_Free(model);
+}
+
+void ViBe::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+  if (img_input.empty())
+    return;
+
+  if (firstTime) {
+    /* Create a buffer for the output image. */
+    //img_output = cv::Mat(img_input.rows, img_input.cols, CV_8UC1);
+
+    /* Initialization of the ViBe model. */
+    vibe::libvibeModel_Sequential_AllocInit_8u_C3R(model, img_input.data, img_input.cols, img_input.rows);
+
+    /* Sets default model values. */
+    //vibe::libvibeModel_Sequential_SetNumberOfSamples(model, numberOfSamples);
+    vibe::libvibeModel_Sequential_SetMatchingThreshold(model, matchingThreshold);
+    vibe::libvibeModel_Sequential_SetMatchingNumber(model, matchingNumber);
+    vibe::libvibeModel_Sequential_SetUpdateFactor(model, updateFactor);
+  }
+
+  vibe::libvibeModel_Sequential_Segmentation_8u_C3R(model, img_input.data, img_output.data);
+  //vibe::libvibeModel_Sequential_Update_8u_C3R(model, model_img_input.data, img_output.data);
+  vibe::libvibeModel_Sequential_Update_8u_C3R(model, img_input.data, img_output.data);
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput)
+    cv::imshow(algorithmName + "_FG", img_output);
+#endif
+
+  firstTime = false;
+}
+
+void ViBe::save_config(cv::FileStorage &fs) {
+  //fs << "numberOfSamples" << numberOfSamples;
+  fs << "matchingThreshold" << matchingThreshold;
+  fs << "matchingNumber" << matchingNumber;
+  fs << "updateFactor" << updateFactor;
+  fs << "showOutput" << showOutput;
+}
+
+void ViBe::load_config(cv::FileStorage &fs) {
+  //fs["numberOfSamples"] >> numberOfSamples;
+  fs["matchingThreshold"] >> matchingThreshold;
+  fs["matchingNumber"] >> matchingNumber;
+  fs["updateFactor"] >> updateFactor;
+  fs["showOutput"] >> showOutput;
+}
diff --git a/src/algorithms/ViBe.h b/src/algorithms/ViBe.h
new file mode 100644
index 0000000000000000000000000000000000000000..067d0834b11ec0dca559173a2603c6de1068d6a4
--- /dev/null
+++ b/src/algorithms/ViBe.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "IBGS.h"
+#include "ViBe/vibe-background-sequential.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class ViBe : public IBGS
+    {
+    private:
+      static const int DEFAULT_NUM_SAMPLES = 20;
+      static const int DEFAULT_MATCH_THRESH = 20;
+      static const int DEFAULT_MATCH_NUM = 2;
+      static const int DEFAULT_UPDATE_FACTOR = 16;
+
+    private:
+      //int numberOfSamples;
+      int matchingThreshold;
+      int matchingNumber;
+      int updateFactor;
+      vibe::vibeModel_Sequential_t* model;
+
+    public:
+      ViBe();
+      ~ViBe();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(ViBe);
+  }
+}
diff --git a/package_bgs/ViBe/LICENSE b/src/algorithms/ViBe/LICENSE
similarity index 100%
rename from package_bgs/ViBe/LICENSE
rename to src/algorithms/ViBe/LICENSE
diff --git a/src/algorithms/ViBe/vibe-background-sequential.cpp b/src/algorithms/ViBe/vibe-background-sequential.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4bec4e6d0b197ae2542b50fbf2e532b5e76c0950
--- /dev/null
+++ b/src/algorithms/ViBe/vibe-background-sequential.cpp
@@ -0,0 +1,915 @@
+#include <assert.h>
+#include <time.h>
+
+#include "vibe-background-sequential.h"
+
+//using namespace bgslibrary::algorithms::vibe;
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace vibe
+    {
+      uint32_t distance_Han2014Improved(uint8_t pixel, uint8_t bg)
+      {
+        uint8_t min, max;
+
+        // Computes R = 0.13 min{ max[bg,26], 230}
+        max = 26;
+        if (bg > max) { max = bg; }
+
+        min = 230;
+        if (min > max) { min = max; }
+
+        return (uint32_t)(0.13*min);
+      }
+
+      static int abs_uint(const int i)
+      {
+        return (i >= 0) ? i : -i;
+      }
+
+      static int32_t distance_is_close_8u_C3R(uint8_t r1, uint8_t g1, uint8_t b1, uint8_t r2, uint8_t g2, uint8_t b2, uint32_t threshold)
+      {
+        return (abs_uint(r1 - r2) + abs_uint(g1 - g2) + abs_uint(b1 - b2) <= 4.5 * threshold);
+      }
+
+      struct vibeModel_Sequential
+      {
+        /* Parameters. */
+        uint32_t width;
+        uint32_t height;
+        uint32_t numberOfSamples;
+        uint32_t matchingThreshold;
+        uint32_t matchingNumber;
+        uint32_t updateFactor;
+
+        /* Storage for the history. */
+        uint8_t *historyImage;
+        uint8_t *historyBuffer;
+        uint32_t lastHistoryImageSwapped;
+
+        /* Buffers with random values. */
+        uint32_t *jump;
+        int *neighbor;
+        uint32_t *position;
+      };
+
+      // -----------------------------------------------------------------------------
+      // Print parameters
+      // -----------------------------------------------------------------------------
+      uint32_t libvibeModel_Sequential_PrintParameters(const vibeModel_Sequential_t *model)
+      {
+        printf(
+          "Using ViBe background subtraction algorithm\n"
+          "  - Number of samples per pixel:       %03d\n"
+          "  - Number of matches needed:          %03d\n"
+          "  - Matching threshold:                %03d\n"
+          "  - Model update subsampling factor:   %03d\n",
+          libvibeModel_Sequential_GetNumberOfSamples(model),
+          libvibeModel_Sequential_GetMatchingNumber(model),
+          libvibeModel_Sequential_GetMatchingThreshold(model),
+          libvibeModel_Sequential_GetUpdateFactor(model)
+        );
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Creates the data structure
+      // -----------------------------------------------------------------------------
+      vibeModel_Sequential_t *libvibeModel_Sequential_New()
+      {
+        /* Model structure alloc. */
+        vibeModel_Sequential_t *model = NULL;
+        model = (vibeModel_Sequential_t*)calloc(1, sizeof(*model));
+        assert(model != NULL);
+
+        /* Default parameters values. */
+        model->numberOfSamples = 20;
+        model->matchingThreshold = 20;
+        model->matchingNumber = 2;
+        model->updateFactor = 16;
+
+        /* Storage for the history. */
+        model->historyImage = NULL;
+        model->historyBuffer = NULL;
+        model->lastHistoryImageSwapped = 0;
+
+        /* Buffers with random values. */
+        model->jump = NULL;
+        model->neighbor = NULL;
+        model->position = NULL;
+
+        return(model);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Some "Get-ers"
+      // -----------------------------------------------------------------------------
+      uint32_t libvibeModel_Sequential_GetNumberOfSamples(const vibeModel_Sequential_t *model)
+      {
+        assert(model != NULL); return(model->numberOfSamples);
+      }
+
+      uint32_t libvibeModel_Sequential_GetMatchingNumber(const vibeModel_Sequential_t *model)
+      {
+        assert(model != NULL); return(model->matchingNumber);
+      }
+
+      uint32_t libvibeModel_Sequential_GetMatchingThreshold(const vibeModel_Sequential_t *model)
+      {
+        assert(model != NULL); return(model->matchingThreshold);
+      }
+
+      uint32_t libvibeModel_Sequential_GetUpdateFactor(const vibeModel_Sequential_t *model)
+      {
+        assert(model != NULL); return(model->updateFactor);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Some "Set-ers"
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_SetMatchingThreshold(
+        vibeModel_Sequential_t *model,
+        const uint32_t matchingThreshold
+      ) {
+        assert(model != NULL);
+        assert(matchingThreshold > 0);
+
+        model->matchingThreshold = matchingThreshold;
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_SetMatchingNumber(
+        vibeModel_Sequential_t *model,
+        const uint32_t matchingNumber
+      ) {
+        assert(model != NULL);
+        assert(matchingNumber > 0);
+
+        model->matchingNumber = matchingNumber;
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_SetUpdateFactor(
+        vibeModel_Sequential_t *model,
+        const uint32_t updateFactor
+      ) {
+        assert(model != NULL);
+        assert(updateFactor > 0);
+
+        model->updateFactor = updateFactor;
+
+        /* We also need to change the values of the jump buffer ! */
+        assert(model->jump != NULL);
+
+        /* Shifts. */
+        int size = (model->width > model->height) ? 2 * model->width + 1 : 2 * model->height + 1;
+
+        for (int i = 0; i < size; ++i)
+          model->jump[i] = (updateFactor == 1) ? 1 : (rand() % (2 * model->updateFactor)) + 1; // 1 or values between 1 and 2 * updateFactor.
+
+        return(0);
+      }
+
+      // ----------------------------------------------------------------------------
+      // Frees the structure
+      // ----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_Free(vibeModel_Sequential_t *model)
+      {
+        if (model == NULL)
+          return(-1);
+
+        if (model->historyBuffer == NULL) {
+          free(model);
+          return(0);
+        }
+
+        free(model->historyImage);
+        free(model->historyBuffer);
+        free(model->jump);
+        free(model->neighbor);
+        free(model->position);
+        free(model);
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Allocates and initializes a C1R model structure
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_AllocInit_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      ) {
+        // Some basic checks. */
+        assert((image_data != NULL) && (model != NULL));
+        assert((width > 0) && (height > 0));
+
+        /* Finish model alloc - parameters values cannot be changed anymore. */
+        model->width = width;
+        model->height = height;
+
+        /* Creates the historyImage structure. */
+        model->historyImage = NULL;
+        model->historyImage = (uint8_t*)malloc(NUMBER_OF_HISTORY_IMAGES * width * height * sizeof(*(model->historyImage)));
+
+        assert(model->historyImage != NULL);
+
+        for (int i = 0; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
+          for (int index = width * height - 1; index >= 0; --index)
+            model->historyImage[i * width * height + index] = image_data[index];
+        }
+
+        /* Now creates and fills the history buffer. */
+        model->historyBuffer = (uint8_t*)malloc(width * height * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) * sizeof(uint8_t));
+        assert(model->historyBuffer != NULL);
+
+        for (int index = width * height - 1; index >= 0; --index) {
+          uint8_t value = image_data[index];
+
+          for (int x = 0; x < model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES; ++x) {
+            int value_plus_noise = value + rand() % 20 - 10;
+
+            if (value_plus_noise < 0) { value_plus_noise = 0; }
+            if (value_plus_noise > 255) { value_plus_noise = 255; }
+
+            model->historyBuffer[index * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) + x] = value_plus_noise;
+          }
+        }
+
+        /* Fills the buffers with random values. */
+        int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
+
+        model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
+        assert(model->jump != NULL);
+
+        model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
+        assert(model->neighbor != NULL);
+
+        model->position = (uint32_t*)malloc(size * sizeof(*(model->position)));
+        assert(model->position != NULL);
+
+        for (int i = 0; i < size; ++i) {
+          model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
+          model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { -width - 1, ... , width + 1 }.
+          model->position[i] = rand() % (model->numberOfSamples);               // Values between 0 and numberOfSamples - 1.
+        }
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Segmentation of a C1R model
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_Segmentation_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      ) {
+        /* Basic checks. */
+        assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert(model->historyBuffer != NULL);
+        assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
+
+        /* Some variables. */
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+        uint32_t matchingNumber = model->matchingNumber;
+        //uint32_t matchingThreshold = model->matchingThreshold;
+
+        uint8_t *historyImage = model->historyImage;
+        uint8_t *historyBuffer = model->historyBuffer;
+
+        /* Segmentation. */
+        memset(segmentation_map, matchingNumber - 1, width * height);
+
+        /* First history Image structure. */
+        for (int index = width * height - 1; index >= 0; --index) {
+          //if (abs_uint(image_data[index] - historyImage[index]) > matchingThreshold)
+          if (abs_uint(image_data[index] - historyImage[index]) > distance_Han2014Improved(image_data[index], historyImage[index]))
+            segmentation_map[index] = matchingNumber;
+        }
+
+        /* Next historyImages. */
+        for (int i = 1; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
+          uint8_t *pels = historyImage + i * width * height;
+
+          for (int index = width * height - 1; index >= 0; --index) {
+            // if (abs_uint(image_data[index] - pels[index]) <= matchingThreshold)
+            if (abs_uint(image_data[index] - pels[index]) <= distance_Han2014Improved(image_data[index], pels[index]))
+              --segmentation_map[index];
+          }
+        }
+
+        /* For swapping. */
+        model->lastHistoryImageSwapped = (model->lastHistoryImageSwapped + 1) % NUMBER_OF_HISTORY_IMAGES;
+        uint8_t *swappingImageBuffer = historyImage + (model->lastHistoryImageSwapped) * width * height;
+
+        /* Now, we move in the buffer and leave the historyImages. */
+        int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
+
+        for (int index = width * height - 1; index >= 0; --index) {
+          if (segmentation_map[index] > 0) {
+            /* We need to check the full border and swap values with the first or second historyImage.
+             * We still need to find a match before we can stop our search.
+             */
+            uint32_t indexHistoryBuffer = index * numberOfTests;
+            uint8_t currentValue = image_data[index];
+
+            for (int i = numberOfTests; i > 0; --i, ++indexHistoryBuffer) {
+              // if (abs_uint(currentValue - historyBuffer[indexHistoryBuffer]) <= matchingThreshold) {
+              if (abs_uint(currentValue - historyBuffer[indexHistoryBuffer]) <= distance_Han2014Improved(currentValue, historyBuffer[indexHistoryBuffer])) {
+                --segmentation_map[index];
+
+                /* Swaping: Putting found value in history image buffer. */
+                uint8_t temp = swappingImageBuffer[index];
+                swappingImageBuffer[index] = historyBuffer[indexHistoryBuffer];
+                historyBuffer[indexHistoryBuffer] = temp;
+
+                /* Exit inner loop. */
+                if (segmentation_map[index] <= 0) break;
+              }
+            } // for
+          } // if
+        } // for
+
+        /* Produces the output. Note that this step is application-dependent. */
+        for (uint8_t *mask = segmentation_map; mask < segmentation_map + (width * height); ++mask)
+          if (*mask > 0) *mask = COLOR_FOREGROUND;
+
+        return(0);
+      }
+
+      // ----------------------------------------------------------------------------
+      // Update a C1R model
+      // ----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_Update_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      ) {
+        /* Basic checks . */
+        assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert(model->historyBuffer != NULL);
+        assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
+
+        /* Some variables. */
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+
+        uint8_t *historyImage = model->historyImage;
+        uint8_t *historyBuffer = model->historyBuffer;
+
+        /* Some utility variable. */
+        int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
+
+        /* Updating. */
+        uint32_t *jump = model->jump;
+        int *neighbor = model->neighbor;
+        uint32_t *position = model->position;
+
+        /* All the frame, except the border. */
+        uint32_t shift, indX, indY;
+        unsigned int x, y;
+
+        for (y = 1; y < height - 1; ++y) {
+          shift = rand() % width;
+          indX = jump[shift]; // index_jump should never be zero (> 1).
+
+          while (indX < width - 1) {
+            int index = indX + y * width;
+
+            if (updating_mask[index] == COLOR_BACKGROUND) {
+              /* In-place substitution. */
+              uint8_t value = image_data[index];
+              int index_neighbor = index + neighbor[shift];
+
+              if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+                historyImage[index + position[shift] * width * height] = value;
+                historyImage[index_neighbor + position[shift] * width * height] = value;
+              }
+              else {
+                int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+                historyBuffer[index * numberOfTests + pos] = value;
+                historyBuffer[index_neighbor * numberOfTests + pos] = value;
+              }
+            }
+
+            ++shift;
+            indX += jump[shift];
+          }
+        }
+
+        /* First row. */
+        y = 0;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
+              historyImage[index + position[shift] * width * height] = image_data[index];
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[index * numberOfTests + pos] = image_data[index];
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        /* Last row. */
+        y = height - 1;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
+              historyImage[index + position[shift] * width * height] = image_data[index];
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[index * numberOfTests + pos] = image_data[index];
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        /* First column. */
+        x = 0;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
+              historyImage[index + position[shift] * width * height] = image_data[index];
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[index * numberOfTests + pos] = image_data[index];
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        /* Last column. */
+        x = width - 1;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES)
+              historyImage[index + position[shift] * width * height] = image_data[index];
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[index * numberOfTests + pos] = image_data[index];
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        /* The first pixel! */
+        if (rand() % model->updateFactor == 0) {
+          if (updating_mask[0] == 0) {
+            int position = rand() % model->numberOfSamples;
+
+            if (position < NUMBER_OF_HISTORY_IMAGES)
+              historyImage[position * width * height] = image_data[0];
+            else {
+              int pos = position - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[pos] = image_data[0];
+            }
+          }
+        }
+
+        return(0);
+      }
+
+      // ----------------------------------------------------------------------------
+      // -------------------------- The same for C3R models -------------------------
+      // ----------------------------------------------------------------------------
+
+      // -----------------------------------------------------------------------------
+      // Allocates and initializes a C3R model structure
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_AllocInit_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      ) {
+        /* Some basic checks. */
+        assert((image_data != NULL) && (model != NULL));
+        assert((width > 0) && (height > 0));
+
+        /* Finish model alloc - parameters values cannot be changed anymore. */
+        model->width = width;
+        model->height = height;
+
+        /* Creates the historyImage structure. */
+        model->historyImage = NULL;
+        model->historyImage = (uint8_t*)malloc(NUMBER_OF_HISTORY_IMAGES * (3 * width) * height * sizeof(uint8_t));
+        assert(model->historyImage != NULL);
+
+        for (int i = 0; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
+          for (int index = (3 * width) * height - 1; index >= 0; --index)
+            model->historyImage[i * (3 * width) * height + index] = image_data[index];
+        }
+
+        assert(model->historyImage != NULL);
+
+        /* Now creates and fills the history buffer. */
+        model->historyBuffer = (uint8_t *)malloc((3 * width) * height * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) * sizeof(uint8_t));
+        assert(model->historyBuffer != NULL);
+
+        for (int index = (3 * width) * height - 1; index >= 0; --index) {
+          uint8_t value = image_data[index];
+
+          for (int x = 0; x < model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES; ++x) {
+            int value_plus_noise = value + rand() % 20 - 10;
+
+            if (value_plus_noise < 0) { value_plus_noise = 0; }
+            if (value_plus_noise > 255) { value_plus_noise = 255; }
+
+            model->historyBuffer[index * (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES) + x] = value_plus_noise;
+          }
+        }
+
+        /* Fills the buffers with random values. */
+        int size = (width > height) ? 2 * width + 1 : 2 * height + 1;
+
+        model->jump = (uint32_t*)malloc(size * sizeof(*(model->jump)));
+        assert(model->jump != NULL);
+
+        model->neighbor = (int*)malloc(size * sizeof(*(model->neighbor)));
+        assert(model->neighbor != NULL);
+
+        model->position = (uint32_t*)malloc(size * sizeof(*(model->position)));
+        assert(model->position != NULL);
+
+        for (int i = 0; i < size; ++i) {
+          model->jump[i] = (rand() % (2 * model->updateFactor)) + 1;            // Values between 1 and 2 * updateFactor.
+          model->neighbor[i] = ((rand() % 3) - 1) + ((rand() % 3) - 1) * width; // Values between { width - 1, ... , width + 1 }.
+          model->position[i] = rand() % (model->numberOfSamples);               // Values between 0 and numberOfSamples - 1.
+        }
+
+        return(0);
+      }
+
+      // -----------------------------------------------------------------------------
+      // Segmentation of a C3R model
+      // -----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_Segmentation_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      ) {
+        /* Basic checks. */
+        assert((image_data != NULL) && (model != NULL) && (segmentation_map != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert(model->historyBuffer != NULL);
+        assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
+
+        /* Some variables. */
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+        uint32_t matchingNumber = model->matchingNumber;
+        uint32_t matchingThreshold = model->matchingThreshold;
+
+        uint8_t *historyImage = model->historyImage;
+        uint8_t *historyBuffer = model->historyBuffer;
+
+        /* Segmentation. */
+        memset(segmentation_map, matchingNumber - 1, width * height);
+
+        /* First history Image structure. */
+        uint8_t *first = historyImage;
+
+        for (int index = width * height - 1; index >= 0; --index) {
+          if (
+            !distance_is_close_8u_C3R(
+              image_data[3 * index], image_data[3 * index + 1], image_data[3 * index + 2],
+              first[3 * index], first[3 * index + 1], first[3 * index + 2], matchingThreshold
+            )
+            )
+            segmentation_map[index] = matchingNumber;
+        }
+
+        /* Next historyImages. */
+        for (int i = 1; i < NUMBER_OF_HISTORY_IMAGES; ++i) {
+          uint8_t *pels = historyImage + i * (3 * width) * height;
+
+          for (int index = width * height - 1; index >= 0; --index) {
+            if (
+              distance_is_close_8u_C3R(
+                image_data[3 * index], image_data[3 * index + 1], image_data[3 * index + 2],
+                pels[3 * index], pels[3 * index + 1], pels[3 * index + 2], matchingThreshold
+              )
+              )
+              --segmentation_map[index];
+          }
+        }
+
+        // For swapping
+        model->lastHistoryImageSwapped = (model->lastHistoryImageSwapped + 1) % NUMBER_OF_HISTORY_IMAGES;
+        uint8_t *swappingImageBuffer = historyImage + (model->lastHistoryImageSwapped) * (3 * width) * height;
+
+        // Now, we move in the buffer and leave the historyImages
+        int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
+
+        for (int index = width * height - 1; index >= 0; --index) {
+          if (segmentation_map[index] > 0) {
+            /* We need to check the full border and swap values with the first or second historyImage.
+             * We still need to find a match before we can stop our search.
+             */
+            uint32_t indexHistoryBuffer = (3 * index) * numberOfTests;
+
+            for (int i = numberOfTests; i > 0; --i, indexHistoryBuffer += 3) {
+              if (
+                distance_is_close_8u_C3R(
+                  image_data[(3 * index)], image_data[(3 * index) + 1], image_data[(3 * index) + 2],
+                  historyBuffer[indexHistoryBuffer], historyBuffer[indexHistoryBuffer + 1], historyBuffer[indexHistoryBuffer + 2],
+                  matchingThreshold
+                )
+                )
+                --segmentation_map[index];
+
+              /* Swaping: Putting found value in history image buffer. */
+              uint8_t temp_r = swappingImageBuffer[(3 * index)];
+              uint8_t temp_g = swappingImageBuffer[(3 * index) + 1];
+              uint8_t temp_b = swappingImageBuffer[(3 * index) + 2];
+
+              swappingImageBuffer[(3 * index)] = historyBuffer[indexHistoryBuffer];
+              swappingImageBuffer[(3 * index) + 1] = historyBuffer[indexHistoryBuffer + 1];
+              swappingImageBuffer[(3 * index) + 2] = historyBuffer[indexHistoryBuffer + 2];
+
+              historyBuffer[indexHistoryBuffer] = temp_r;
+              historyBuffer[indexHistoryBuffer + 1] = temp_g;
+              historyBuffer[indexHistoryBuffer + 2] = temp_b;
+
+              /* Exit inner loop. */
+              if (segmentation_map[index] <= 0) break;
+            } // for
+          } // if
+        } // for
+
+        /* Produces the output. Note that this step is application-dependent. */
+        for (uint8_t *mask = segmentation_map; mask < segmentation_map + (width * height); ++mask)
+          if (*mask > 0) *mask = COLOR_FOREGROUND;
+
+        return(0);
+      }
+
+      // ----------------------------------------------------------------------------
+      // Update a C3R model
+      // ----------------------------------------------------------------------------
+      int32_t libvibeModel_Sequential_Update_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      ) {
+        /* Basic checks. */
+        assert((image_data != NULL) && (model != NULL) && (updating_mask != NULL));
+        assert((model->width > 0) && (model->height > 0));
+        assert(model->historyBuffer != NULL);
+        assert((model->jump != NULL) && (model->neighbor != NULL) && (model->position != NULL));
+
+        /* Some variables. */
+        uint32_t width = model->width;
+        uint32_t height = model->height;
+
+        uint8_t *historyImage = model->historyImage;
+        uint8_t *historyBuffer = model->historyBuffer;
+
+        /* Some utility variable. */
+        int numberOfTests = (model->numberOfSamples - NUMBER_OF_HISTORY_IMAGES);
+
+        /* Updating. */
+        uint32_t *jump = model->jump;
+        int *neighbor = model->neighbor;
+        uint32_t *position = model->position;
+
+        /* All the frame, except the border. */
+        uint32_t shift, indX, indY;
+        int x, y;
+
+        for (y = 1; y < height - 1; ++y) {
+          shift = rand() % width;
+          indX = jump[shift]; // index_jump should never be zero (> 1).
+
+          while (indX < width - 1) {
+            int index = indX + y * width;
+
+            if (updating_mask[index] == COLOR_BACKGROUND) {
+              /* In-place substitution. */
+              uint8_t r = image_data[3 * index];
+              uint8_t g = image_data[3 * index + 1];
+              uint8_t b = image_data[3 * index + 2];
+
+              int index_neighbor = 3 * (index + neighbor[shift]);
+
+              if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+                historyImage[3 * index + position[shift] * (3 * width) * height] = r;
+                historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
+                historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
+
+                historyImage[index_neighbor + position[shift] * (3 * width) * height] = r;
+                historyImage[index_neighbor + position[shift] * (3 * width) * height + 1] = g;
+                historyImage[index_neighbor + position[shift] * (3 * width) * height + 2] = b;
+              }
+              else {
+                int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+
+                historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
+                historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
+                historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
+
+                historyBuffer[index_neighbor * numberOfTests + 3 * pos] = r;
+                historyBuffer[index_neighbor * numberOfTests + 3 * pos + 1] = g;
+                historyBuffer[index_neighbor * numberOfTests + 3 * pos + 2] = b;
+              }
+            }
+
+            ++shift;
+            indX += jump[shift];
+          }
+        }
+
+        /* First row. */
+        y = 0;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          uint8_t r = image_data[3 * index];
+          uint8_t g = image_data[3 * index + 1];
+          uint8_t b = image_data[3 * index + 2];
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+              historyImage[3 * index + position[shift] * (3 * width) * height] = r;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
+            }
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        /* Last row. */
+        y = height - 1;
+        shift = rand() % width;
+        indX = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indX <= width - 1) {
+          int index = indX + y * width;
+
+          uint8_t r = image_data[3 * index];
+          uint8_t g = image_data[3 * index + 1];
+          uint8_t b = image_data[3 * index + 2];
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+              historyImage[3 * index + position[shift] * (3 * width) * height] = r;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
+            }
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
+            }
+          }
+
+          ++shift;
+          indX += jump[shift];
+        }
+
+        /* First column. */
+        x = 0;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          uint8_t r = image_data[3 * index];
+          uint8_t g = image_data[3 * index + 1];
+          uint8_t b = image_data[3 * index + 2];
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+              historyImage[3 * index + position[shift] * (3 * width) * height] = r;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
+            }
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        /* Last column. */
+        x = width - 1;
+        shift = rand() % height;
+        indY = jump[shift]; // index_jump should never be zero (> 1).
+
+        while (indY <= height - 1) {
+          int index = x + indY * width;
+
+          uint8_t r = image_data[3 * index];
+          uint8_t g = image_data[3 * index + 1];
+          uint8_t b = image_data[3 * index + 2];
+
+          if (updating_mask[index] == COLOR_BACKGROUND) {
+            if (position[shift] < NUMBER_OF_HISTORY_IMAGES) {
+              historyImage[3 * index + position[shift] * (3 * width) * height] = r;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 1] = g;
+              historyImage[3 * index + position[shift] * (3 * width) * height + 2] = b;
+            }
+            else {
+              int pos = position[shift] - NUMBER_OF_HISTORY_IMAGES;
+
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos] = r;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 1] = g;
+              historyBuffer[(3 * index) * numberOfTests + 3 * pos + 2] = b;
+            }
+          }
+
+          ++shift;
+          indY += jump[shift];
+        }
+
+        /* The first pixel! */
+        if (rand() % model->updateFactor == 0) {
+          if (updating_mask[0] == 0) {
+            int position = rand() % model->numberOfSamples;
+
+            uint8_t r = image_data[0];
+            uint8_t g = image_data[1];
+            uint8_t b = image_data[2];
+
+            if (position < NUMBER_OF_HISTORY_IMAGES) {
+              historyImage[position * (3 * width) * height] = r;
+              historyImage[position * (3 * width) * height + 1] = g;
+              historyImage[position * (3 * width) * height + 2] = b;
+            }
+            else {
+              int pos = position - NUMBER_OF_HISTORY_IMAGES;
+
+              historyBuffer[3 * pos] = r;
+              historyBuffer[3 * pos + 1] = g;
+              historyBuffer[3 * pos + 2] = b;
+            }
+          }
+        }
+
+        return(0);
+      }
+    }
+  }
+}
diff --git a/src/algorithms/ViBe/vibe-background-sequential.h b/src/algorithms/ViBe/vibe-background-sequential.h
new file mode 100644
index 0000000000000000000000000000000000000000..e68ba0aecaf3c845262ee82dd7d2ce451c115a98
--- /dev/null
+++ b/src/algorithms/ViBe/vibe-background-sequential.h
@@ -0,0 +1,253 @@
+#pragma once
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace vibe
+    {
+      const int COLOR_BACKGROUND = 0; // Default label for background pixels
+      const int COLOR_FOREGROUND = 255; // Default label for foreground pixels. Note that some authors chose any value different from 0 instead
+      const int NUMBER_OF_HISTORY_IMAGES = 2;
+
+      /**
+       * \typedef struct vibeModel_Sequential_t
+       * \brief Data structure for the background subtraction model.
+       *
+       * This data structure contains the background model as well as some paramaters value.
+       * The code is designed to hide all the implementation details to the user to ease its use.
+       */
+      typedef struct vibeModel_Sequential vibeModel_Sequential_t;
+
+      /**
+       * Allocation of a new data structure where the background model will be stored.
+       * Please note that this function only creates the structure to host the data.
+       * This data structures will only be filled with a call to \ref libvibeModel_Sequential_AllocInit_8u_C1R.
+       *
+       * \result A pointer to a newly allocated \ref vibeModel_Sequential_t
+       * structure, or <tt>NULL</tt> in the case of an error.
+       */
+      vibeModel_Sequential_t *libvibeModel_Sequential_New();
+
+      /**
+       * ViBe uses several parameters.
+       * You can print and change some of them if you want. However, default
+       * value should meet your needs for most videos.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      uint32_t libvibeModel_Sequential_PrintParameters(const vibeModel_Sequential_t *model);
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param numberOfSamples
+       * @return
+       */
+      int32_t libvibeModel_Sequential_SetNumberOfSamples(
+        vibeModel_Sequential_t *model,
+        const uint32_t numberOfSamples
+      );
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      uint32_t libvibeModel_Sequential_GetNumberOfSamples(const vibeModel_Sequential_t *model);
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param matchingThreshold
+       * @return
+       */
+      int32_t libvibeModel_Sequential_SetMatchingThreshold(
+        vibeModel_Sequential_t *model,
+        const uint32_t matchingThreshold
+      );
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      uint32_t libvibeModel_Sequential_GetMatchingThreshold(const vibeModel_Sequential_t *model);
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param matchingNumber
+       * @return
+       */
+      int32_t libvibeModel_Sequential_SetMatchingNumber(
+        vibeModel_Sequential_t *model,
+        const uint32_t matchingNumber
+      );
+
+      /**
+       * Setter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param updateFactor New value for the update factor. Please note that the update factor is to be understood as a probability of updating. More specifically, an update factor of 16 means that 1 out of every 16 background pixels is updated. Likewise, an update factor of 1 means that every background pixel is updated.
+       * @return
+       */
+      int32_t libvibeModel_Sequential_SetUpdateFactor(
+        vibeModel_Sequential_t *model,
+        const uint32_t updateFactor
+      );
+
+      /**
+       * Getter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      uint32_t libvibeModel_Sequential_GetMatchingNumber(const vibeModel_Sequential_t *model);
+
+
+      /**
+       * Getter.
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      uint32_t libvibeModel_Sequential_GetUpdateFactor(const vibeModel_Sequential_t *model);
+
+      /**
+       * \brief Frees all the memory used by the <tt>model</tt> and deallocates the structure.
+       *
+       * This function frees all the memory allocated by \ref libvibeModel_SequentialNew and
+       * \ref libvibeModel_Sequential_AllocInit_8u_C1R or \ref libvibeModel_Sequential_AllocInit_8u_C3R.
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @return
+       */
+      int32_t libvibeModel_Sequential_Free(vibeModel_Sequential_t *model);
+
+      /**
+       * The two following functions allocate the required memory according to the
+       * model parameters and the dimensions of the input images.
+       * You must use the "C1R" function for grayscale images and the "C3R" for color
+       * images.
+       * These 2 functions also initialize the background model using the content
+       * of *image_data which is the pixel buffer of the first image of your stream.
+       */
+      // -------------------------  Single channel images ----------------------------
+      /**
+        *
+        * @param model The data structure with ViBe's background subtraction model and parameters.
+        * @param image_data
+        * @param width
+        * @param height
+        * @return
+        */
+      int32_t libvibeModel_Sequential_AllocInit_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      );
+
+      /* These 2 functions perform 2 operations:
+      *   - they classify the pixels *image_data using the provided model and store
+      *     the results in *segmentation_map.
+      *   - they update *model according to these results and the content of
+      *     *image_data.
+      * You must use the "C1R" function for grayscale images and the "C3R" for color
+      * images.
+      */
+      /**
+        *
+        * @param model The data structure with ViBe's background subtraction model and parameters.
+        * @param image_data
+        * @param segmentation_map
+        * @return
+        */
+      int32_t libvibeModel_Sequential_Segmentation_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      );
+
+      /**
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param image_data
+       * @param updating_mask
+       * @return
+       */
+      int32_t libvibeModel_Sequential_Update_8u_C1R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      );
+
+      // -------------------------  Three channel images -----------------------------
+      /**
+       * The pixel values of color images are arranged in the following order
+       * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param image_data
+       * @param width
+       * @param height
+       * @return
+       */
+      int32_t libvibeModel_Sequential_AllocInit_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        const uint32_t width,
+        const uint32_t height
+      );
+
+      /* These 2 functions perform 2 operations:
+      *   - they classify the pixels *image_data using the provided model and store
+      *     the results in *segmentation_map.
+      *   - they update *model according to these results and the content of
+      *     *image_data.
+      * You must use the "C1R" function for grayscale images and the "C3R" for color
+      * images.
+      */
+      /**
+        * The pixel values of color images are arranged in the following order
+        * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
+        *
+        * @param model The data structure with ViBe's background subtraction model and parameters.
+        * @param image_data
+        * @param segmentation_map
+        * @return
+        */
+      int32_t libvibeModel_Sequential_Segmentation_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *segmentation_map
+      );
+
+      /**
+       * The pixel values of color images are arranged in the following order
+       * RGBRGBRGB... (or HSVHSVHSVHSVHSVHSV...)
+       *
+       * @param model The data structure with ViBe's background subtraction model and parameters.
+       * @param image_data
+       * @param updating_mask
+       * @return
+       */
+      int32_t libvibeModel_Sequential_Update_8u_C3R(
+        vibeModel_Sequential_t *model,
+        const uint8_t *image_data,
+        uint8_t *updating_mask
+      );
+    }
+  }
+}
diff --git a/src/algorithms/VuMeter.cpp b/src/algorithms/VuMeter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f42c3455dce5733967257c5323ae0ed03620d022
--- /dev/null
+++ b/src/algorithms/VuMeter.cpp
@@ -0,0 +1,90 @@
+#include "VuMeter.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms;
+
+VuMeter::VuMeter() :
+  IBGS(quote(VuMeter)),
+  enableFilter(true), binSize(8), 
+  alpha(0.995), threshold(0.03)
+{
+  debug_construction(VuMeter);
+  initLoadSaveConfig(algorithmName);
+}
+
+VuMeter::~VuMeter() {
+  debug_destruction(VuMeter);
+  cvReleaseImage(&mask);
+  cvReleaseImage(&background);
+  cvReleaseImage(&gray);
+}
+
+void VuMeter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
+{
+  init(img_input, img_output, img_bgmodel);
+
+#if CV_MAJOR_VERSION > 3 || (CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9)
+  IplImage _frame = cvIplImage(img_input);
+  frame = &_frame;
+#else
+  frame = new IplImage(img_input);
+#endif
+
+  if (firstTime) {
+    bgs.SetAlpha(alpha);
+    bgs.SetBinSize(binSize);
+    bgs.SetThreshold(threshold);
+
+    gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
+    cvCvtColor(frame, gray, CV_RGB2GRAY);
+
+    background = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1);
+    cvCopy(gray, background);
+
+    mask = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1);
+    cvZero(mask);
+  }
+  else
+    cvCvtColor(frame, gray, CV_RGB2GRAY);
+
+  bgs.UpdateBackground(gray, background, mask);
+  img_foreground = cv::cvarrToMat(mask);
+  img_background = cv::cvarrToMat(background);
+
+  if (enableFilter) {
+    cv::erode(img_foreground, img_foreground, cv::Mat());
+    cv::medianBlur(img_foreground, img_foreground, 5);
+  }
+
+#ifndef MEX_COMPILE_FLAG
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
+  }
+#endif
+
+  img_foreground.copyTo(img_output);
+  img_background.copyTo(img_bgmodel);
+
+  delete frame;
+  firstTime = false;
+}
+
+void VuMeter::save_config(cv::FileStorage &fs) {
+  fs << "enableFilter" << enableFilter;
+  fs << "binSize" << binSize;
+  fs << "alpha" << alpha;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
+}
+
+void VuMeter::load_config(cv::FileStorage &fs) {
+  fs["enableFilter"] >> enableFilter;
+  fs["binSize"] >> binSize;
+  fs["alpha"] >> alpha;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
+}
+
+#endif
diff --git a/src/algorithms/VuMeter.h b/src/algorithms/VuMeter.h
new file mode 100644
index 0000000000000000000000000000000000000000..50f62382940346b47852384654c2519b906e369a
--- /dev/null
+++ b/src/algorithms/VuMeter.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "IBGS.h"
+#include "VuMeter/TBackgroundVuMeter.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class VuMeter : public IBGS
+    {
+    private:
+      vumeter::TBackgroundVuMeter bgs;
+      IplImage *frame;
+      IplImage *gray;
+      IplImage *background;
+      IplImage *mask;
+      bool enableFilter;
+      int binSize;
+      double alpha;
+      double threshold;
+
+    public:
+      VuMeter();
+      ~VuMeter();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(VuMeter);
+  }
+}
+
+#endif
diff --git a/package_bgs/VuMeter/TBackground.cpp b/src/algorithms/VuMeter/TBackground.cpp
similarity index 68%
rename from package_bgs/VuMeter/TBackground.cpp
rename to src/algorithms/VuMeter/TBackground.cpp
index 4e93729fa376894c1406a94314e74e5b8a15cec1..19f26f8ee7b9c8f10cfa247056f46778ca19fa47 100644
--- a/package_bgs/VuMeter/TBackground.cpp
+++ b/src/algorithms/VuMeter/TBackground.cpp
@@ -1,70 +1,37 @@
-/*
-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/>.
-*/
-/*
-*  TBackground.cpp
-*  Framework
-*
-*  Created by Robinault Lionel on 07/12/11.
-*
-*/
-
 #include "TBackground.h"
 
-TBackground::TBackground(void)
-{
+using namespace bgslibrary::algorithms::vumeter;
+
+TBackground::TBackground(){
   std::cout << "TBackground()" << std::endl;
 }
 
-TBackground::~TBackground(void)
-{
+TBackground::~TBackground(){
   Clear();
   std::cout << "~TBackground()" << std::endl;
 }
 
-void TBackground::Clear(void)
-{
-}
+void TBackground::Clear(){}
 
-void TBackground::Reset(void)
-{
-}
+void TBackground::Reset(){}
 
-int TBackground::GetParameterCount(void)
-{
+int TBackground::GetParameterCount(void){
   return 0;
 }
 
-std::string TBackground::GetParameterName(int nInd)
-{
+std::string TBackground::GetParameterName(int nInd){
   return "";
 }
 
-std::string TBackground::GetParameterValue(int nInd)
-{
+std::string TBackground::GetParameterValue(int nInd){
   return "";
 }
 
-int TBackground::SetParameterValue(int nInd, std::string csNew)
-{
+int TBackground::SetParameterValue(int nInd, std::string csNew){
   return 0;
 }
 
-int TBackground::Init(IplImage * pSource)
-{
+int TBackground::Init(IplImage * pSource){
   return 0;
 }
 
@@ -91,8 +58,7 @@ bool TBackground::isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *
   return bResult;
 }
 
-int TBackground::UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask)
-{
+int TBackground::UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask){
   return 0;
 }
 
diff --git a/src/algorithms/VuMeter/TBackground.h b/src/algorithms/VuMeter/TBackground.h
new file mode 100644
index 0000000000000000000000000000000000000000..612060da9ca22ab744b1f654261d72271fd6e518
--- /dev/null
+++ b/src/algorithms/VuMeter/TBackground.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <iostream>
+#include <opencv2/opencv.hpp>
+// opencv legacy includes
+#include <opencv2/core/core_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace vumeter
+    {
+      class TBackground
+      {
+      public:
+        TBackground();
+        virtual ~TBackground();
+
+        virtual void Clear();
+        virtual void Reset();
+
+        virtual int UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
+        virtual int UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd);
+        virtual IplImage *CreateTestImg();
+
+        virtual int GetParameterCount();
+        virtual std::string GetParameterName(int nInd);
+        virtual std::string GetParameterValue(int nInd);
+        virtual int SetParameterValue(int nInd, std::string csNew);
+
+      protected:
+        virtual int Init(IplImage * pSource);
+        virtual bool isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
+      };
+    }
+  }
+}
diff --git a/src/algorithms/VuMeter/TBackgroundVuMeter.cpp b/src/algorithms/VuMeter/TBackgroundVuMeter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..627d73fdcdb740415fa394342aa48709791f9e0f
--- /dev/null
+++ b/src/algorithms/VuMeter/TBackgroundVuMeter.cpp
@@ -0,0 +1,360 @@
+#include "TBackgroundVuMeter.h"
+
+//using namespace bgslibrary::algorithms::vumeter;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace vumeter
+    {
+      const int PROCESS_PAR_COUNT = 3;
+
+      TBackgroundVuMeter::TBackgroundVuMeter(void)
+        : m_pHist(NULL)
+        , m_nBinCount(0)
+        , m_nBinSize(8)
+        , m_nCount(0)
+        , m_fAlpha(0.995)
+        , m_fThreshold(0.03)
+      {
+        std::cout << "TBackgroundVuMeter()" << std::endl;
+      }
+
+      TBackgroundVuMeter::~TBackgroundVuMeter(void)
+      {
+        Clear();
+        std::cout << "~TBackgroundVuMeter()" << std::endl;
+      }
+
+      void TBackgroundVuMeter::Clear(void)
+      {
+        TBackground::Clear();
+
+        if (m_pHist != NULL)
+        {
+          for (int i = 0; i < m_nBinCount; ++i)
+          {
+            if (m_pHist[i] != NULL)
+              cvReleaseImage(&m_pHist[i]);
+          }
+
+          delete[] m_pHist;
+          m_pHist = NULL;
+          m_nBinCount = 0;
+        }
+
+        m_nCount = 0;
+      }
+
+      void TBackgroundVuMeter::Reset(void)
+      {
+        float fVal = 0.0;
+
+        TBackground::Reset();
+
+        if (m_pHist != NULL)
+        {
+          //		fVal = (m_nBinCount != 0) ? (float)(1.0 / (double)m_nBinCount) : (float)0.0;
+          fVal = 0.0;
+
+          for (int i = 0; i < m_nBinCount; ++i)
+          {
+            if (m_pHist[i] != NULL)
+            {
+              cvSetZero(m_pHist[i]);
+              cvAddS(m_pHist[i], cvScalar(fVal), m_pHist[i]);
+            }
+          }
+        }
+
+        m_nCount = 0;
+      }
+
+      int TBackgroundVuMeter::GetParameterCount(void)
+      {
+        return TBackground::GetParameterCount() + PROCESS_PAR_COUNT;
+      }
+
+      std::string TBackgroundVuMeter::GetParameterName(int nInd)
+      {
+        std::string csResult;
+        int nNb;
+
+        nNb = TBackground::GetParameterCount();
+
+        if (nInd >= nNb)
+        {
+          nInd -= nNb;
+
+          switch (nInd)
+          {
+          case 0: csResult = "Bin size"; break;
+          case 1: csResult = "Alpha"; break;
+          case 2: csResult = "Threshold"; break;
+          }
+        }
+        else
+          csResult = TBackground::GetParameterName(nInd);
+
+        return csResult;
+      }
+
+      std::string TBackgroundVuMeter::GetParameterValue(int nInd)
+      {
+        std::string csResult;
+        int nNb;
+
+        nNb = TBackground::GetParameterCount();
+
+        if (nInd >= nNb)
+        {
+          nInd -= nNb;
+
+          char buff[100];
+
+          switch (nInd)
+          {
+          case 0: sprintf(buff, "%d", m_nBinSize); break;
+          case 1: sprintf(buff, "%.3f", m_fAlpha); break;
+          case 2: sprintf(buff, "%.2f", m_fThreshold); break;
+          }
+
+          csResult = buff;
+        }
+        else
+          csResult = TBackground::GetParameterValue(nInd);
+
+        return csResult;
+      }
+
+      int TBackgroundVuMeter::SetParameterValue(int nInd, std::string csNew)
+      {
+        int nErr = 0;
+
+        int nNb;
+
+        nNb = TBackground::GetParameterCount();
+
+        if (nInd >= nNb)
+        {
+          nInd -= nNb;
+
+          switch (nInd)
+          {
+          case 0: SetBinSize(atoi(csNew.c_str())); break;
+          case 1: SetAlpha(atof(csNew.c_str())); break;
+          case 2: SetThreshold(atof(csNew.c_str())); break;
+          default: nErr = 1;
+          }
+        }
+        else
+          nErr = TBackground::SetParameterValue(nInd, csNew);
+
+        return nErr;
+      }
+
+      int TBackgroundVuMeter::Init(IplImage * pSource)
+      {
+        int nErr = 0;
+        int nbl, nbc;
+
+        Clear();
+
+        nErr = TBackground::Init(pSource);
+
+        if (pSource == NULL)
+          nErr = 1;
+
+        // calcul le nb de bin
+        if (!nErr)
+        {
+          nbl = pSource->height;
+          nbc = pSource->width;
+          m_nBinCount = (m_nBinSize != 0) ? 256 / m_nBinSize : 0;
+
+          if (m_nBinCount <= 0 || m_nBinCount > 256)
+            nErr = 1;
+        }
+
+        // creation du tableau de pointeur
+        if (!nErr)
+        {
+          m_pHist = new IplImage *[m_nBinCount];
+
+          if (m_pHist == NULL)
+            nErr = 1;
+        }
+
+        // creation des images
+        if (!nErr)
+        {
+          for (int i = 0; i < m_nBinCount; ++i)
+          {
+            m_pHist[i] = cvCreateImage(cvSize(nbc, nbl), IPL_DEPTH_32F, 1);
+
+            if (m_pHist[i] == NULL)
+              nErr = 1;
+          }
+        }
+
+        if (!nErr)
+          Reset();
+        else
+          Clear();
+
+        return nErr;
+      }
+
+      bool TBackgroundVuMeter::isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask)
+      {
+        bool bResult = true;
+        int i;
+
+        bResult = TBackground::isInitOk(pSource, pBackground, pMotionMask);
+
+        if (pSource == NULL)
+          bResult = false;
+
+        if (m_nBinSize == 0)
+          bResult = false;
+
+        if (bResult)
+        {
+          i = (m_nBinSize != 0) ? 256 / m_nBinSize : 0;
+
+          if (i != m_nBinCount || m_pHist == NULL)
+            bResult = false;
+        }
+
+        if (bResult)
+        {
+          int nbl = pSource->height;
+          int nbc = pSource->width;
+
+          for (i = 0; i < m_nBinCount; ++i)
+          {
+            if (m_pHist[i] == NULL || m_pHist[i]->width != nbc || m_pHist[i]->height != nbl)
+              bResult = false;
+          }
+        }
+
+        return bResult;
+      }
+
+      int TBackgroundVuMeter::UpdateBackground(IplImage *pSource, IplImage *pBackground, IplImage *pMotionMask)
+      {
+        int nErr = 0;
+        unsigned char *ptrs, *ptrb, *ptrm;
+        float *ptr1, *ptr2;
+
+        if (!isInitOk(pSource, pBackground, pMotionMask))
+          nErr = Init(pSource);
+
+        if (!nErr)
+        {
+          m_nCount++;
+          int nbc = pSource->width;
+          int nbl = pSource->height;
+          unsigned char v = m_nBinSize;
+
+          // multiplie tout par alpha
+          for (int i = 0; i < m_nBinCount; ++i)
+            cvConvertScale(m_pHist[i], m_pHist[i], m_fAlpha, 0.0);
+
+          for (int l = 0; l < nbl; ++l)
+          {
+            ptrs = (unsigned char *)(pSource->imageData + pSource->widthStep * l);
+            ptrm = (unsigned char *)(pMotionMask->imageData + pMotionMask->widthStep * l);
+            ptrb = (unsigned char *)(pBackground->imageData + pBackground->widthStep * l);
+
+            for (int c = 0; c < nbc; ++c, ptrs++, ptrb++, ptrm++)
+            {
+              // recherche le bin à augmenter
+              int i = *ptrs / v;
+
+              if (i < 0 || i >= m_nBinCount)
+                i = 0;
+
+              ptr1 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l);
+              ptr1 += c;
+
+              *ptr1 += (float)(1.0 - m_fAlpha);
+              *ptrm = (*ptr1 < m_fThreshold) ? 255 : 0;
+
+              // recherche le bin du fond actuel
+              i = *ptrb / v;
+
+              if (i < 0 || i >= m_nBinCount)
+                i = 0;
+
+              ptr2 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l);
+              ptr2 += c;
+
+              if (*ptr2 < *ptr1)
+                *ptrb = *ptrs;
+            }
+          }
+
+          if (m_nCount < 5)
+            cvSetZero(pMotionMask);
+        }
+
+        return nErr;
+      }
+
+      IplImage *TBackgroundVuMeter::CreateTestImg()
+      {
+        IplImage *pImage = NULL;
+
+        if (m_nBinCount > 0)
+          pImage = cvCreateImage(cvSize(m_nBinCount, 100), IPL_DEPTH_8U, 3);
+
+        if (pImage != NULL)
+          cvSetZero(pImage);
+
+        return pImage;
+      }
+
+      int TBackgroundVuMeter::UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd)
+      {
+        int nErr = 0;
+        float *ptrf;
+
+        if (pTest == NULL || !isInitOk(pSource, pBackground, pSource))
+          nErr = 1;
+
+        if (!nErr)
+        {
+          int nbl = pTest->height;
+          int nbc = pTest->width;
+
+          if (nbl != 100 || nbc != m_nBinCount)
+            nErr = 1;
+
+          if (nX < 0 || nX >= pSource->width || nY < 0 || nY >= pSource->height)
+            nErr = 1;
+        }
+
+        if (!nErr)
+        {
+          cvSetZero(pTest);
+
+          for (int i = 0; i < m_nBinCount; ++i)
+          {
+            ptrf = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * nY);
+            ptrf += nX;
+
+            if (*ptrf >= 0 || *ptrf <= 1.0) {
+              cvLine(pTest, cvPoint(i, 100), cvPoint(i, (int)(100.0 * (1.0 - *ptrf))), cvScalar(0, 255, 0));
+            }
+          }
+
+          cvLine(pTest, cvPoint(0, (int)(100.0 * (1.0 - m_fThreshold))), cvPoint(m_nBinCount, (int)(100.0 * (1.0 - m_fThreshold))), cvScalar(0, 128, 0));
+        }
+
+        return nErr;
+      }
+    }
+  }
+}
diff --git a/src/algorithms/VuMeter/TBackgroundVuMeter.h b/src/algorithms/VuMeter/TBackgroundVuMeter.h
new file mode 100644
index 0000000000000000000000000000000000000000..89cfc22351d9659d7c6697cd97aca4d6a5174eaa
--- /dev/null
+++ b/src/algorithms/VuMeter/TBackgroundVuMeter.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "TBackground.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace vumeter
+    {
+      class TBackgroundVuMeter : public TBackground
+      {
+      public:
+        TBackgroundVuMeter(void);
+        virtual ~TBackgroundVuMeter(void);
+
+        virtual void Clear(void);
+        virtual void Reset(void);
+
+        virtual int UpdateBackground(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
+
+        virtual IplImage *CreateTestImg();
+        virtual int UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage *pTest, int nX, int nY, int nInd);
+
+        virtual int GetParameterCount(void);
+        virtual std::string GetParameterName(int nInd);
+        virtual std::string GetParameterValue(int nInd);
+        virtual int SetParameterValue(int nInd, std::string csNew);
+
+        inline void SetBinSize(int nNew) { m_nBinSize = (nNew > 0 && nNew < 255) ? nNew : 8; }
+        inline double GetBinSize() { return m_nBinSize; }
+
+        inline void SetAlpha(double fNew) { m_fAlpha = (fNew > 0.0 && fNew < 1.0) ? fNew : 0.995; }
+        inline double GetAlpha() { return m_fAlpha; }
+
+        inline void SetThreshold(double fNew) { m_fThreshold = (fNew > 0.0 && fNew < 1.0) ? fNew : 0.03; }
+        inline double GetThreshold() { return m_fThreshold; }
+
+      protected:
+        IplImage **m_pHist;
+
+        int m_nBinCount;
+        int m_nBinSize;
+        int m_nCount;
+        double m_fAlpha;
+        double m_fThreshold;
+
+        virtual int Init(IplImage * pSource);
+        virtual bool isInitOk(IplImage * pSource, IplImage *pBackground, IplImage *pMotionMask);
+      };
+    }
+  }
+}
diff --git a/package_bgs/WeightedMovingMean.cpp b/src/algorithms/WeightedMovingMean.cpp
similarity index 51%
rename from package_bgs/WeightedMovingMean.cpp
rename to src/algorithms/WeightedMovingMean.cpp
index 3a427fc0e6926b721f809fca66a86b05841a29fd..3d7d961523d589ff3a697fec37d6364f12220278 100644
--- a/package_bgs/WeightedMovingMean.cpp
+++ b/src/algorithms/WeightedMovingMean.cpp
@@ -1,33 +1,17 @@
-/*
-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 "WeightedMovingMean.h"
 
 using namespace bgslibrary::algorithms;
 
 WeightedMovingMean::WeightedMovingMean() :
+  IBGS(quote(WeightedMovingMean)),
   enableWeight(true), enableThreshold(true), threshold(15)
 {
-  std::cout << "WeightedMovingMean()" << std::endl;
-  setup("./config/WeightedMovingMean.xml");
+  debug_construction(WeightedMovingMean);
+  initLoadSaveConfig(algorithmName);
 }
 
-WeightedMovingMean::~WeightedMovingMean()
-{
-  std::cout << "~WeightedMovingMean()" << std::endl;
+WeightedMovingMean::~WeightedMovingMean() {
+  debug_destruction(WeightedMovingMean);
 }
 
 void WeightedMovingMean::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
@@ -74,10 +58,9 @@ void WeightedMovingMean::process(const cv::Mat &img_input, cv::Mat &img_output,
     cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
 
 #ifndef MEX_COMPILE_FLAG
-  if (showOutput)
-  {
-    cv::imshow("W Moving Mean FG Mask", img_foreground);
-    cv::imshow("W Moving Mean BG Model", img_background);
+  if (showOutput) {
+    cv::imshow(algorithmName + "_FG", img_foreground);
+    cv::imshow(algorithmName + "_BG", img_background);
   }
 #endif
 
@@ -90,26 +73,16 @@ void WeightedMovingMean::process(const cv::Mat &img_input, cv::Mat &img_output,
   firstTime = false;
 }
 
-void WeightedMovingMean::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableWeight", enableWeight);
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void WeightedMovingMean::save_config(cv::FileStorage &fs) {
+  fs << "enableWeight" << enableWeight;
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
 }
 
-void WeightedMovingMean::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableWeight = cvReadIntByName(fs, nullptr, "enableWeight", true);
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void WeightedMovingMean::load_config(cv::FileStorage &fs) {
+  fs["enableWeight"] >> enableWeight;
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
 }
diff --git a/src/algorithms/WeightedMovingMean.h b/src/algorithms/WeightedMovingMean.h
new file mode 100644
index 0000000000000000000000000000000000000000..f31905c65c9ac5426560396dc44afc6c73c1fa20
--- /dev/null
+++ b/src/algorithms/WeightedMovingMean.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class WeightedMovingMean : public IBGS
+    {
+    private:
+      cv::Mat img_input_prev_1;
+      cv::Mat img_input_prev_2;
+      bool enableWeight;
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      WeightedMovingMean();
+      ~WeightedMovingMean();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(WeightedMovingMean);
+  }
+}
diff --git a/package_bgs/WeightedMovingVariance.cpp b/src/algorithms/WeightedMovingVariance.cpp
similarity index 66%
rename from package_bgs/WeightedMovingVariance.cpp
rename to src/algorithms/WeightedMovingVariance.cpp
index 2855a92629094c5e6314b351181d9d7cb806032d..d9273c88ae8cb05e32938ca3263646ffe50b7cf1 100644
--- a/package_bgs/WeightedMovingVariance.cpp
+++ b/src/algorithms/WeightedMovingVariance.cpp
@@ -1,33 +1,17 @@
-/*
-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 "WeightedMovingVariance.h"
 
 using namespace bgslibrary::algorithms;
 
 WeightedMovingVariance::WeightedMovingVariance() :
+  IBGS(quote(WeightedMovingVariance)),
   enableWeight(true), enableThreshold(true), threshold(15)
 {
-  std::cout << "WeightedMovingVariance()" << std::endl;
-  setup("./config/WeightedMovingVariance.xml");
+  debug_construction(WeightedMovingVariance);
+  initLoadSaveConfig(algorithmName);
 }
 
-WeightedMovingVariance::~WeightedMovingVariance()
-{
-  std::cout << "~WeightedMovingVariance()" << std::endl;
+WeightedMovingVariance::~WeightedMovingVariance() {
+  debug_destruction(WeightedMovingVariance);
 }
 
 void WeightedMovingVariance::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
@@ -100,7 +84,7 @@ void WeightedMovingVariance::process(const cv::Mat &img_input, cv::Mat &img_outp
 
 #ifndef MEX_COMPILE_FLAG
   if (showOutput)
-    cv::imshow("W Moving Variance", img_foreground);
+    cv::imshow(algorithmName + "_FG", img_foreground);
 #endif
 
   img_foreground.copyTo(img_output);
@@ -127,26 +111,16 @@ cv::Mat WeightedMovingVariance::computeWeightedVariance(const cv::Mat &img_input
   return img_f;
 }
 
-void WeightedMovingVariance::saveConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE);
-
-  cvWriteInt(fs, "enableWeight", enableWeight);
-  cvWriteInt(fs, "enableThreshold", enableThreshold);
-  cvWriteInt(fs, "threshold", threshold);
-  cvWriteInt(fs, "showOutput", showOutput);
-
-  cvReleaseFileStorage(&fs);
+void WeightedMovingVariance::save_config(cv::FileStorage &fs) {
+  fs << "enableWeight" << enableWeight;
+  fs << "enableThreshold" << enableThreshold;
+  fs << "threshold" << threshold;
+  fs << "showOutput" << showOutput;
 }
 
-void WeightedMovingVariance::loadConfig()
-{
-  CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ);
-
-  enableWeight = cvReadIntByName(fs, nullptr, "enableWeight", true);
-  enableThreshold = cvReadIntByName(fs, nullptr, "enableThreshold", true);
-  threshold = cvReadIntByName(fs, nullptr, "threshold", 15);
-  showOutput = cvReadIntByName(fs, nullptr, "showOutput", true);
-
-  cvReleaseFileStorage(&fs);
+void WeightedMovingVariance::load_config(cv::FileStorage &fs) {
+  fs["enableWeight"] >> enableWeight;
+  fs["enableThreshold"] >> enableThreshold;
+  fs["threshold"] >> threshold;
+  fs["showOutput"] >> showOutput;
 }
diff --git a/src/algorithms/WeightedMovingVariance.h b/src/algorithms/WeightedMovingVariance.h
new file mode 100644
index 0000000000000000000000000000000000000000..e53bdfd6e1c9e50179dcc31e3fb8ac8e0fa28b94
--- /dev/null
+++ b/src/algorithms/WeightedMovingVariance.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "IBGS.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    class WeightedMovingVariance : public IBGS
+    {
+    private:
+      cv::Mat img_input_prev_1;
+      cv::Mat img_input_prev_2;
+      bool enableWeight;
+      bool enableThreshold;
+      int threshold;
+
+    public:
+      WeightedMovingVariance();
+      ~WeightedMovingVariance();
+
+      void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
+      cv::Mat computeWeightedVariance(const cv::Mat &img_input_f, const cv::Mat &img_mean_f, const double weight);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+
+    bgs_register(WeightedMovingVariance);
+  }
+}
diff --git a/src/algorithms/algorithms.cpp b/src/algorithms/algorithms.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5955368f44f381dc6693ad615b38ee68162648ba
--- /dev/null
+++ b/src/algorithms/algorithms.cpp
@@ -0,0 +1 @@
+#include "algorithms.h"
diff --git a/package_bgs/bgslibrary.h b/src/algorithms/algorithms.h
similarity index 63%
rename from package_bgs/bgslibrary.h
rename to src/algorithms/algorithms.h
index 3895ba85b6f9e646e76965506563f3a0c635eb26..0db7953baeb2624b1ad48b86c3065dbe97b03a6a 100644
--- a/package_bgs/bgslibrary.h
+++ b/src/algorithms/algorithms.h
@@ -1,26 +1,10 @@
-/*
-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
 
 #include "FrameDifference.h"
 #include "StaticFrameDifference.h"
 #include "WeightedMovingMean.h"
 #include "WeightedMovingVariance.h"
-#include "MixtureOfGaussianV1.h" // Only for OpenCV >= 2
+#include "MixtureOfGaussianV1.h" // Only for OpenCV == 2
 #include "MixtureOfGaussianV2.h"
 #include "AdaptiveBackgroundLearning.h"
 #include "AdaptiveSelectiveBackgroundLearning.h"
@@ -58,8 +42,8 @@ along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
 #include "PAWCS.h"
 #include "TwoPoints.h"
 #include "ViBe.h"
+#include "CodeBook.h"
 
 //#include "_template_/MyBGS.h"
-//#include "_template_/Amber.h"
 
 using namespace bgslibrary::algorithms;
diff --git a/package_bgs/dp/AdaptiveMedianBGS.cpp b/src/algorithms/dp/AdaptiveMedianBGS.cpp
similarity index 70%
rename from package_bgs/dp/AdaptiveMedianBGS.cpp
rename to src/algorithms/dp/AdaptiveMedianBGS.cpp
index da1add9124b0e3488df2fb2a57f4a2704f992c5c..53c1e3de579f3158ba3ccc14003422f6a188dac3 100644
--- a/package_bgs/dp/AdaptiveMedianBGS.cpp
+++ b/src/algorithms/dp/AdaptiveMedianBGS.cpp
@@ -1,46 +1,19 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* AdaptiveMedianBGS.cpp
-*
-* Purpose: Implementation of the simple adaptive median background
-*		  		 subtraction algorithm described in:
-*	  			 "Segmentation and tracking of piglets in images"
-* 						by McFarlane and Schofield
-*
-* Author: Donovan Parks, September 2007
-*
-******************************************************************************/
+#include "AdaptiveMedianBGS.h"
 
-#include <iostream>
-#include <stdlib.h>
-#include <cmath>
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
 
-#include "AdaptiveMedianBGS.h"
+//#if CV_MAJOR_VERSION == 3 && CV_SUBMINOR_VERSION >= 9
+//#define CV_RGB(r, g, b) cvScalar((b), (g), (r), 0)
+//#endif
+#define CV_RGB_LEGACY(r, g, b) cvScalar((b), (g), (r), 0)
 
-using namespace Algorithms::BackgroundSubtraction;
+using namespace bgslibrary::algorithms::dp;
 
 void AdaptiveMedianBGS::Initalize(const BgsParams& param)
 {
   m_params = (AdaptiveMedianParams&)param;
-
   m_median = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
-  cvSet(m_median.Ptr(), CV_RGB(BACKGROUND, BACKGROUND, BACKGROUND));
+  cvSet(m_median.Ptr(), CV_RGB_LEGACY(BACKGROUND, BACKGROUND, BACKGROUND));
 }
 
 RgbImage* AdaptiveMedianBGS::Background()
@@ -138,3 +111,4 @@ void AdaptiveMedianBGS::Subtract(int frame_num, const RgbImage& data,
   }
 }
 
+#endif
diff --git a/src/algorithms/dp/AdaptiveMedianBGS.h b/src/algorithms/dp/AdaptiveMedianBGS.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a9d1c7f2fff306ac1fb6534ed70de9d27506120
--- /dev/null
+++ b/src/algorithms/dp/AdaptiveMedianBGS.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include <iostream>
+#include <stdlib.h>
+#include <cmath>
+
+#include "Bgs.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+    // --- Parameters used by the Adaptive Median BGS algorithm ---
+    class AdaptiveMedianParams : public BgsParams
+    {
+    public:
+      unsigned char &LowThreshold() { return m_low_threshold; }
+      unsigned char &HighThreshold() { return m_high_threshold; }
+
+      int &SamplingRate() { return m_samplingRate; }
+      int &LearningFrames() { return m_learning_frames; }
+
+    private:
+      unsigned char m_low_threshold;
+      unsigned char m_high_threshold;
+
+      int m_samplingRate;
+      int m_learning_frames;
+    };
+
+
+    // --- Adaptive Median BGS algorithm ---
+    class AdaptiveMedianBGS : public Bgs
+    {
+    public:
+      virtual ~AdaptiveMedianBGS() {}
+
+      void Initalize(const BgsParams& param);
+
+      void InitModel(const RgbImage& data);
+      void Subtract(int frame_num, const RgbImage& data,
+        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
+      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
+
+      RgbImage* Background();
+
+    private:
+      void SubtractPixel(int r, int c, const RgbPixel& pixel,
+        unsigned char& low_threshold, unsigned char& high_threshold);
+
+      AdaptiveMedianParams m_params;
+
+      RgbImage m_median;
+    };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/dp/Bgs.h b/src/algorithms/dp/Bgs.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f1c1ea93be7b7e361f54cecab64407df5ce5ff3
--- /dev/null
+++ b/src/algorithms/dp/Bgs.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "Image.h"
+#include "BgsParams.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+    class Bgs
+    {
+    public:
+      static const int BACKGROUND = 0;
+      static const int FOREGROUND = 255;
+
+      virtual ~Bgs() {}
+
+      // Initialize any data required by the BGS algorithm. Should be called once before calling
+      // any of the following functions.
+      virtual void Initalize(const BgsParams& param) = 0;
+
+      // Initialize the background model. Typically, the background model is initialized using the first
+      // frame of the incoming video stream, but alternatives are possible.
+      virtual void InitModel(const RgbImage& data) = 0;
+
+      // Subtract the current frame from the background model and produce a binary foreground mask using
+      // both a low and high threshold value.
+      virtual void Subtract(int frame_num, const RgbImage& data,
+                            BwImage& low_threshold_mask, BwImage& high_threshold_mask) = 0;
+
+      // Update the background model. Only pixels set to background in update_mask are updated.
+      virtual void Update(int frame_num, const RgbImage& data,  const BwImage& update_mask) = 0;
+
+      // Return the current background model.
+      virtual RgbImage *Background() = 0;
+    };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/dp/BgsParams.h b/src/algorithms/dp/BgsParams.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f1ed6b0960fbfd82405ef7a540a52d789952d63
--- /dev/null
+++ b/src/algorithms/dp/BgsParams.h
@@ -0,0 +1,32 @@
+#pragma once
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+    class BgsParams
+    {
+    public:
+      virtual ~BgsParams() {}
+
+      virtual void SetFrameSize(unsigned int width, unsigned int height)
+      {
+        m_width = width;
+        m_height = height;
+        m_size = width*height;
+      }
+
+      unsigned int &Width() { return m_width; }
+      unsigned int &Height() { return m_height; }
+      unsigned int &Size() { return m_size; }
+
+    protected:
+      unsigned int m_width;
+      unsigned int m_height;
+      unsigned int m_size;
+    };
+    }
+  }
+}
diff --git a/package_bgs/dp/Eigenbackground.cpp b/src/algorithms/dp/Eigenbackground.cpp
similarity index 79%
rename from package_bgs/dp/Eigenbackground.cpp
rename to src/algorithms/dp/Eigenbackground.cpp
index dceb4cd2c4442d53703bf21ea957ed341535fd64..e8c3aea034baed42b7a65a8402b35c7f08335fb6 100644
--- a/package_bgs/dp/Eigenbackground.cpp
+++ b/src/algorithms/dp/Eigenbackground.cpp
@@ -1,36 +1,8 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* Eigenbackground.cpp
-*
-* Purpose: Implementation of the Eigenbackground background subtraction
-*					 algorithm developed by Oliver et al.
-*
-* Author: Donovan Parks, September 2007
-*
-* "A Bayesian Computer Vision System for Modeling Human Interactions"
-*   Nuria Oliver, Barbara Rosario, Alex P. Pentland 2000
-*
-******************************************************************************/
-
 #include "Eigenbackground.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 Eigenbackground::Eigenbackground()
 {
@@ -188,3 +160,5 @@ void Eigenbackground::UpdateHistory(int frame_num, const RgbImage& new_frame)
     cvCopy(new_frame.Ptr(), &src_row);
   }
 }
+
+#endif
diff --git a/src/algorithms/dp/Eigenbackground.h b/src/algorithms/dp/Eigenbackground.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f44e42846b3d33aa6d0b6e505bae27120d7a6e9
--- /dev/null
+++ b/src/algorithms/dp/Eigenbackground.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include "opencv2/core/version.hpp"
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+#include "Bgs.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+    // --- Parameters used by the Mean BGS algorithm ---
+    class EigenbackgroundParams : public BgsParams
+    {
+    public:
+      float &LowThreshold() { return m_low_threshold; }
+      float &HighThreshold() { return m_high_threshold; }
+
+      int &HistorySize() { return m_history_size; }
+      int &EmbeddedDim() { return m_dim; }
+
+    private:
+      // A pixel will be classified as foreground if the squared distance of any
+      // color channel is greater than the specified threshold
+      float m_low_threshold;
+      float m_high_threshold;
+
+      int m_history_size;			// number frames used to create eigenspace
+      int m_dim;							// eigenspace dimensionality
+    };
+
+    // --- Eigenbackground BGS algorithm ---
+    class Eigenbackground : public Bgs
+    {
+    public:
+      Eigenbackground();
+      ~Eigenbackground();
+
+      void Initalize(const BgsParams& param);
+
+      void InitModel(const RgbImage& data);
+      void Subtract(int frame_num, const RgbImage& data,
+        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
+      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
+
+      RgbImage* Background() { return &m_background; }
+
+    private:
+      void UpdateHistory(int frameNum, const RgbImage& newFrame);
+
+      EigenbackgroundParams m_params;
+
+      CvMat* m_pcaData;
+      CvMat* m_pcaAvg;
+      CvMat* m_eigenValues;
+      CvMat* m_eigenVectors;
+
+      RgbImage m_background;
+    };
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/dp/Error.cpp b/src/algorithms/dp/Error.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f2958cd91ae1863c767106f2ff2c067c6c445578
--- /dev/null
+++ b/src/algorithms/dp/Error.cpp
@@ -0,0 +1,39 @@
+#include <iostream> 
+#include <fstream>
+
+#include "Error.h"
+
+//using namespace bgslibrary::algorithms::dp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      std::ofstream traceFile;
+
+      bool Error(const char* msg, const char* code, int data)
+      {
+        std::cerr << code << ": " << msg << std::endl;
+        return false;
+      }
+
+      bool TraceInit(const char* filename)
+      {
+        traceFile.open(filename);
+        return traceFile.is_open();
+      }
+
+      void Trace(const char* msg)
+      {
+        traceFile << msg << std::endl;
+      }
+
+      void TraceClose()
+      {
+        traceFile.close();
+      }
+    }
+  }
+}
diff --git a/src/algorithms/dp/Error.h b/src/algorithms/dp/Error.h
new file mode 100644
index 0000000000000000000000000000000000000000..3695f8e0410a74ddf519d2e4ee88cc0e6fd9d345
--- /dev/null
+++ b/src/algorithms/dp/Error.h
@@ -0,0 +1,15 @@
+#pragma once
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      bool Error(const char* msg, const char* code, int data);
+      bool TraceInit(const char* filename);
+      void Trace(const char* msg);
+      void TraceClose();
+    }
+  }
+}
diff --git a/src/algorithms/dp/GrimsonGMM.cpp b/src/algorithms/dp/GrimsonGMM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc6111fcbc41779f9c5990aac0c775c79e70ddac
--- /dev/null
+++ b/src/algorithms/dp/GrimsonGMM.cpp
@@ -0,0 +1,300 @@
+#include "GrimsonGMM.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//using namespace bgslibrary::algorithms::dp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      int compareGMM(const void* _gmm1, const void* _gmm2)
+      {
+        GMM gmm1 = *(GMM*)_gmm1;
+        GMM gmm2 = *(GMM*)_gmm2;
+
+        if (gmm1.significants < gmm2.significants)
+          return 1;
+        else if (gmm1.significants == gmm2.significants)
+          return 0;
+        else
+          return -1;
+      }
+
+      GrimsonGMM::GrimsonGMM()
+      {
+        m_modes = NULL;
+      }
+
+      GrimsonGMM::~GrimsonGMM()
+      {
+        delete[] m_modes;
+      }
+
+      void GrimsonGMM::Initalize(const BgsParams& param)
+      {
+        m_params = (GrimsonParams&)param;
+
+        // Tbf - the threshold
+        m_bg_threshold = 0.75f;	// 1-cf from the paper
+
+        // Tgenerate - the threshold
+        m_variance = 36.0f;		// sigma for the new mode
+
+        // GMM for each pixel
+        m_modes = new GMM[m_params.Size()*m_params.MaxModes()];
+
+        // used modes per pixel
+        m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);
+
+        m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
+      }
+
+      RgbImage* GrimsonGMM::Background()
+      {
+        return &m_background;
+      }
+
+      void GrimsonGMM::InitModel(const RgbImage& data)
+      {
+        m_modes_per_pixel.Clear();
+
+        for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
+        {
+          m_modes[i].weight = 0;
+          m_modes[i].variance = 0;
+          m_modes[i].muR = 0;
+          m_modes[i].muG = 0;
+          m_modes[i].muB = 0;
+          m_modes[i].significants = 0;
+        }
+      }
+
+      void GrimsonGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask)
+      {
+        // it doesn't make sense to have conditional updates in the GMM framework
+      }
+
+      void GrimsonGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
+        unsigned char& low_threshold, unsigned char& high_threshold)
+      {
+        // calculate distances to the modes (+ sort???)
+        // here we need to go in descending order!!!
+        long pos;
+        bool bFitsPDF = false;
+        bool bBackgroundLow = false;
+        bool bBackgroundHigh = false;
+
+        float fOneMinAlpha = 1 - m_params.Alpha();
+
+        float totalWeight = 0.0f;
+
+        // calculate number of Gaussians to include in the background model
+        int backgroundGaussians = 0;
+        double sum = 0.0;
+        for (int i = 0; i < numModes; ++i)
+        {
+          if (sum < m_bg_threshold)
+          {
+            backgroundGaussians++;
+            sum += m_modes[posPixel + i].weight;
+          }
+          else
+          {
+            break;
+          }
+        }
+
+        // update all distributions and check for match with current pixel
+        for (int iModes = 0; iModes < numModes; iModes++)
+        {
+          pos = posPixel + iModes;
+          float weight = m_modes[pos].weight;
+
+          // fit not found yet
+          if (!bFitsPDF)
+          {
+            //check if it belongs to some of the modes
+            //calculate distance
+            float var = m_modes[pos].variance;
+            float muR = m_modes[pos].muR;
+            float muG = m_modes[pos].muG;
+            float muB = m_modes[pos].muB;
+
+            float dR = muR - pixel(0);
+            float dG = muG - pixel(1);
+            float dB = muB - pixel(2);
+
+            // calculate the squared distance
+            float dist = (dR*dR + dG*dG + dB*dB);
+
+            if (dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
+              bBackgroundHigh = true;
+
+            // a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
+            if (dist < m_params.LowThreshold()*var)
+            {
+              bFitsPDF = true;
+
+              // check if this Gaussian is part of the background model
+              if (iModes < backgroundGaussians)
+                bBackgroundLow = true;
+
+              //update distribution
+              float k = m_params.Alpha() / weight;
+              weight = fOneMinAlpha*weight + m_params.Alpha();
+              m_modes[pos].weight = weight;
+              m_modes[pos].muR = muR - k*(dR);
+              m_modes[pos].muG = muG - k*(dG);
+              m_modes[pos].muB = muB - k*(dB);
+
+              //limit the variance
+              float sigmanew = var + k*(dist - var);
+              m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+            else
+            {
+              weight = fOneMinAlpha*weight;
+              if (weight < 0.0)
+              {
+                weight = 0.0;
+                numModes--;
+              }
+
+              m_modes[pos].weight = weight;
+              m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+            }
+          }
+          else
+          {
+            weight = fOneMinAlpha*weight;
+            if (weight < 0.0)
+            {
+              weight = 0.0;
+              numModes--;
+            }
+            m_modes[pos].weight = weight;
+            m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
+          }
+
+          totalWeight += weight;
+        }
+
+        // renormalize weights so they add to one
+        double invTotalWeight = 1.0 / totalWeight;
+        for (int iLocal = 0; iLocal < numModes; iLocal++)
+        {
+          m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
+          m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
+            / sqrt(m_modes[posPixel + iLocal].variance);
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&m_modes[posPixel], numModes, sizeof(GMM), compareGMM);
+
+        // make new mode if needed and exit
+        if (!bFitsPDF)
+        {
+          if (numModes < m_params.MaxModes())
+          {
+            numModes++;
+          }
+          else
+          {
+            // the weakest mode will be replaced
+          }
+
+          pos = posPixel + numModes - 1;
+
+          m_modes[pos].muR = pixel.ch[0];
+          m_modes[pos].muG = pixel.ch[1];
+          m_modes[pos].muB = pixel.ch[2];
+          m_modes[pos].variance = m_variance;
+          m_modes[pos].significants = 0;			// will be set below
+
+          if (numModes == 1)
+            m_modes[pos].weight = 1;
+          else
+            m_modes[pos].weight = m_params.Alpha();
+
+          //renormalize weights
+          int iLocal;
+          float sum = 0.0;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+          {
+            sum += m_modes[posPixel + iLocal].weight;
+          }
+
+          double invSum = 1.0 / sum;
+          for (iLocal = 0; iLocal < numModes; iLocal++)
+          {
+            m_modes[posPixel + iLocal].weight *= (float)invSum;
+            m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
+              / sqrt(m_modes[posPixel + iLocal].variance);
+
+          }
+        }
+
+        // Sort significance values so they are in desending order.
+        qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareGMM);
+
+        if (bBackgroundLow)
+        {
+          low_threshold = BACKGROUND;
+        }
+        else
+        {
+          low_threshold = FOREGROUND;
+        }
+
+        if (bBackgroundHigh)
+        {
+          high_threshold = BACKGROUND;
+        }
+        else
+        {
+          high_threshold = FOREGROUND;
+        }
+      }
+
+      ///////////////////////////////////////////////////////////////////////////////
+      //Input:
+      //  data - a pointer to the data of a RGB image of the same size
+      //Output:
+      //  output - a pointer to the data of a gray value image of the same size 
+      //					(the memory should already be reserved) 
+      //					values: 255-foreground, 125-shadow, 0-background
+      ///////////////////////////////////////////////////////////////////////////////
+      void GrimsonGMM::Subtract(int frame_num, const RgbImage& data,
+        BwImage& low_threshold_mask, BwImage& high_threshold_mask)
+      {
+        unsigned char low_threshold, high_threshold;
+        long posPixel;
+
+        // update each pixel of the image
+        for (unsigned int r = 0; r < m_params.Height(); ++r)
+        {
+          for (unsigned int c = 0; c < m_params.Width(); ++c)
+          {
+            // update model + background subtract
+            posPixel = (r*m_params.Width() + c)*m_params.MaxModes();
+
+            SubtractPixel(posPixel, data(r, c), m_modes_per_pixel(r, c), low_threshold, high_threshold);
+
+            low_threshold_mask(r, c) = low_threshold;
+            high_threshold_mask(r, c) = high_threshold;
+
+            m_background(r, c, 0) = (unsigned char)m_modes[posPixel].muR;
+            m_background(r, c, 1) = (unsigned char)m_modes[posPixel].muG;
+            m_background(r, c, 2) = (unsigned char)m_modes[posPixel].muB;
+          }
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/dp/GrimsonGMM.h b/src/algorithms/dp/GrimsonGMM.h
similarity index 60%
rename from package_bgs/dp/GrimsonGMM.h
rename to src/algorithms/dp/GrimsonGMM.h
index 2c0f77232801d24f14d7b8b8b04d2af536565a1e..a89a0eacfef97edfdac3f62a26a9510fe4868aea 100644
--- a/package_bgs/dp/GrimsonGMM.h
+++ b/src/algorithms/dp/GrimsonGMM.h
@@ -1,64 +1,15 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* GrimsonGMM.cpp
-*
-* Purpose: Implementation of the Gaussian mixture model (GMM) background
-*		  		 subtraction described in:
-*	  			 "Adaptive background mixture models for real-time tracking"
-* 						by Chris Stauffer and W.E.L Grimson
-*
-* Author: Donovan Parks, September 2007
-*
-* This code is based on code by Z. Zivkovic's written for his enhanced GMM
-* background subtraction algorithm:
-*
-*	"Improved adaptive Gausian mixture model for background subtraction"
-*		Z.Zivkovic
-*		International Conference Pattern Recognition, UK, August, 2004
-*
-*
-* "Efficient Adaptive Density Estimapion per Image Pixel for the
-*			Task of Background Subtraction"
-*		Z.Zivkovic, F. van der Heijden
-*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-
-Example:
-    Algorithms::BackgroundSubtraction::GrimsonParams params;
-    params.SetFrameSize(width, height);
-    params.LowThreshold() = 3.0f*3.0f;
-    params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-    params.Alpha() = 0.001f;
-    params.MaxModes() = 3;
-
-    Algorithms::BackgroundSubtraction::GrimsonGMM bgs;
-    bgs.Initalize(params);
-******************************************************************************/
 #pragma once
 
 #include "Bgs.h"
 
-namespace Algorithms
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
 {
-  namespace BackgroundSubtraction
+  namespace algorithms
   {
+    namespace dp
+    {
     typedef struct GMMGaussian
     {
       float variance;
@@ -142,5 +93,8 @@ namespace Algorithms
       // Current background model
       RgbImage m_background;
     };
+    }
   }
 }
+
+#endif
diff --git a/src/algorithms/dp/Image.cpp b/src/algorithms/dp/Image.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8089ef42cb73062e8fee5f20e9bae778199e22d3
--- /dev/null
+++ b/src/algorithms/dp/Image.cpp
@@ -0,0 +1,62 @@
+#include "Image.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+//using namespace bgslibrary::algorithms::dp;
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      ImageBase::~ImageBase()
+      {
+        if (imgp != NULL && m_bReleaseMemory)
+          cvReleaseImage(&imgp);
+        imgp = NULL;
+      }
+
+      void DensityFilter(BwImage& image, BwImage& filtered, int minDensity, unsigned char fgValue)
+      {
+        for (int r = 1; r < image.Ptr()->height - 1; ++r)
+        {
+          for (int c = 1; c < image.Ptr()->width - 1; ++c)
+          {
+            int count = 0;
+            if (image(r, c) == fgValue)
+            {
+              if (image(r - 1, c - 1) == fgValue)
+                count++;
+              if (image(r - 1, c) == fgValue)
+                count++;
+              if (image(r - 1, c + 1) == fgValue)
+                count++;
+              if (image(r, c - 1) == fgValue)
+                count++;
+              if (image(r, c + 1) == fgValue)
+                count++;
+              if (image(r + 1, c - 1) == fgValue)
+                count++;
+              if (image(r + 1, c) == fgValue)
+                count++;
+              if (image(r + 1, c + 1) == fgValue)
+                count++;
+
+              if (count < minDensity)
+                filtered(r, c) = 0;
+              else
+                filtered(r, c) = fgValue;
+            }
+            else
+            {
+              filtered(r, c) = 0;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+#endif
diff --git a/src/algorithms/dp/Image.h b/src/algorithms/dp/Image.h
new file mode 100644
index 0000000000000000000000000000000000000000..f923cbd4ca46b11bd56594d6b4ebab5efa6cdd10
--- /dev/null
+++ b/src/algorithms/dp/Image.h
@@ -0,0 +1,341 @@
+#pragma once
+
+#include <opencv2/opencv.hpp>
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      template <class T>
+      class ImageIterator
+      {
+      public:
+        ImageIterator(IplImage* image, int x = 0, int y = 0, int dx = 0, int dy = 0) :
+          i(x), j(y), i0(0)
+        {
+          data = reinterpret_cast<T*>(image->imageData);
+          step = image->widthStep / sizeof(T);
+
+          nl = image->height;
+          if ((y + dy) > 0 && (y + dy) < nl)
+            nl = y + dy;
+
+          if (y < 0)
+            j = 0;
+
+          data += step*j;
+
+          nc = image->width;
+          if ((x + dx) > 0 && (x + dx) < nc)
+            nc = x + dx;
+
+          nc *= image->nChannels;
+          if (x > 0)
+            i0 = x*image->nChannels;
+          i = i0;
+
+          nch = image->nChannels;
+        }
+
+        /* has next ? */
+        bool operator!() const { return j < nl; }
+
+        /* next pixel */
+        ImageIterator& operator++()
+        {
+          i++;
+          if (i >= nc)
+          {
+            i = i0;
+            j++;
+            data += step;
+          }
+          return *this;
+        }
+
+        ImageIterator& operator+=(int s)
+        {
+          i += s;
+          if (i >= nc)
+          {
+            i = i0;
+            j++;
+            data += step;
+          }
+          return *this;
+        }
+
+        /* pixel access */
+        T& operator*() { return data[i]; }
+
+        const T operator*() const { return data[i]; }
+
+        const T neighbor(int dx, int dy) const
+        {
+          return *(data + dy*step + i + dx);
+        }
+
+        T* operator&() const { return data + i; }
+
+        /* current pixel coordinates */
+        int column() const { return i / nch; }
+        int line() const { return j; }
+
+      private:
+        int i, i0, j;
+        T* data;
+        int step;
+        int nl, nc;
+        int nch;
+      };
+
+      // --- Constants --------------------------------------------------------------
+
+      const unsigned char NUM_CHANNELS = 3;
+
+      // --- Pixel Types ------------------------------------------------------------
+
+      class RgbPixel
+      {
+      public:
+        RgbPixel() { ; }
+        RgbPixel(unsigned char _r, unsigned char _g, unsigned char _b)
+        {
+          ch[0] = _r; ch[1] = _g; ch[2] = _b;
+        }
+
+        RgbPixel& operator=(const RgbPixel& rhs)
+        {
+          ch[0] = rhs.ch[0]; ch[1] = rhs.ch[1]; ch[2] = rhs.ch[2];
+          return *this;
+        }
+
+        inline unsigned char& operator()(const int _ch)
+        {
+          return ch[_ch];
+        }
+
+        inline unsigned char operator()(const int _ch) const
+        {
+          return ch[_ch];
+        }
+
+        unsigned char ch[3];
+      };
+
+      class RgbPixelFloat
+      {
+      public:
+        RgbPixelFloat() { ; }
+        RgbPixelFloat(float _r, float _g, float _b)
+        {
+          ch[0] = _r; ch[1] = _g; ch[2] = _b;
+        }
+
+        RgbPixelFloat& operator=(const RgbPixelFloat& rhs)
+        {
+          ch[0] = rhs.ch[0]; ch[1] = rhs.ch[1]; ch[2] = rhs.ch[2];
+          return *this;
+        }
+
+        inline float& operator()(const int _ch)
+        {
+          return ch[_ch];
+        }
+
+        inline float operator()(const int _ch) const
+        {
+          return ch[_ch];
+        }
+
+        float ch[3];
+      };
+
+      // --- Image Types ------------------------------------------------------------
+
+      class ImageBase
+      {
+      public:
+        ImageBase(IplImage* img = NULL) { imgp = img; m_bReleaseMemory = true; }
+        ~ImageBase();
+
+        void ReleaseMemory(bool b) { m_bReleaseMemory = b; }
+
+        IplImage* Ptr() { return imgp; }
+        const IplImage* Ptr() const { return imgp; }
+
+        void ReleaseImage()
+        {
+          cvReleaseImage(&imgp);
+        }
+
+        void operator=(IplImage* img)
+        {
+          imgp = img;
+        }
+
+        // copy-constructor
+        ImageBase(const ImageBase& rhs)
+        {
+          // it is very inefficent if this copy-constructor is called
+          assert(false);
+        }
+
+        // assignment operator
+        ImageBase& operator=(const ImageBase& rhs)
+        {
+          // it is very inefficent if operator= is called
+          assert(false);
+
+          return *this;
+        }
+
+        virtual void Clear() = 0;
+
+      protected:
+        IplImage* imgp;
+        bool m_bReleaseMemory;
+      };
+
+      class RgbImage : public ImageBase
+      {
+      public:
+        RgbImage(IplImage* img = NULL) : ImageBase(img) { ; }
+
+        virtual void Clear()
+        {
+          cvZero(imgp);
+        }
+
+        void operator=(IplImage* img)
+        {
+          imgp = img;
+        }
+
+        // channel-level access using image(row, col, channel)
+        inline unsigned char& operator()(const int r, const int c, const int ch)
+        {
+          return (unsigned char &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels + ch];
+        }
+
+        inline const unsigned char& operator()(const int r, const int c, const int ch) const
+        {
+          return (unsigned char &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels + ch];
+        }
+
+        // RGB pixel-level access using image(row, col)
+        inline RgbPixel& operator()(const int r, const int c)
+        {
+          return (RgbPixel &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels];
+        }
+
+        inline const RgbPixel& operator()(const int r, const int c) const
+        {
+          return (RgbPixel &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels];
+        }
+      };
+
+      class RgbImageFloat : public ImageBase
+      {
+      public:
+        RgbImageFloat(IplImage* img = NULL) : ImageBase(img) { ; }
+
+        virtual void Clear()
+        {
+          cvZero(imgp);
+        }
+
+        void operator=(IplImage* img)
+        {
+          imgp = img;
+        }
+
+        // channel-level access using image(row, col, channel)
+        inline float& operator()(const int r, const int c, const int ch)
+        {
+          return (float &)imgp->imageData[r*imgp->widthStep + (c*imgp->nChannels + ch) * sizeof(float)];
+        }
+
+        inline float operator()(const int r, const int c, const int ch) const
+        {
+          return (float)imgp->imageData[r*imgp->widthStep + (c*imgp->nChannels + ch) * sizeof(float)];
+        }
+
+        // RGB pixel-level access using image(row, col)
+        inline RgbPixelFloat& operator()(const int r, const int c)
+        {
+          return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels * sizeof(float)];
+        }
+
+        inline const RgbPixelFloat& operator()(const int r, const int c) const
+        {
+          return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels * sizeof(float)];
+        }
+      };
+
+      class BwImage : public ImageBase
+      {
+      public:
+        BwImage(IplImage* img = NULL) : ImageBase(img) { ; }
+
+        virtual void Clear()
+        {
+          cvZero(imgp);
+        }
+
+        void operator=(IplImage* img)
+        {
+          imgp = img;
+        }
+
+        // pixel-level access using image(row, col)
+        inline unsigned char& operator()(const int r, const int c)
+        {
+          return (unsigned char &)imgp->imageData[r*imgp->widthStep + c];
+        }
+
+        inline unsigned char operator()(const int r, const int c) const
+        {
+          return (unsigned char)imgp->imageData[r*imgp->widthStep + c];
+        }
+      };
+
+      class BwImageFloat : public ImageBase
+      {
+      public:
+        BwImageFloat(IplImage* img = NULL) : ImageBase(img) { ; }
+
+        virtual void Clear()
+        {
+          cvZero(imgp);
+        }
+
+        void operator=(IplImage* img)
+        {
+          imgp = img;
+        }
+
+        // pixel-level access using image(row, col)
+        inline float& operator()(const int r, const int c)
+        {
+          return (float &)imgp->imageData[r*imgp->widthStep + c * sizeof(float)];
+        }
+
+        inline float operator()(const int r, const int c) const
+        {
+          return (float)imgp->imageData[r*imgp->widthStep + c * sizeof(float)];
+        }
+      };
+
+      // --- Image Functions --------------------------------------------------------
+
+      //void DensityFilter(BwImage& image, BwImage& filtered, int minDensity, unsigned char fgValue);
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/dp/MeanBGS.cpp b/src/algorithms/dp/MeanBGS.cpp
similarity index 74%
rename from package_bgs/dp/MeanBGS.cpp
rename to src/algorithms/dp/MeanBGS.cpp
index 51781588671b3714278c9614cecd8cfef5f5baa0..8b419b0d3de93496af764e55a6749c1e1c22f063 100644
--- a/package_bgs/dp/MeanBGS.cpp
+++ b/src/algorithms/dp/MeanBGS.cpp
@@ -1,33 +1,8 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* MeanBGS.h
-*
-* Purpose: Implementation of a simple temporal mean background
-*		  		 subtraction algorithm.
-*
-* Author: Donovan Parks, September 2007
-*
-******************************************************************************/
-
 #include "MeanBGS.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 void MeanBGS::Initalize(const BgsParams& param)
 {
@@ -125,3 +100,5 @@ void MeanBGS::Subtract(int frame_num, const RgbImage& data,
     }
   }
 }
+
+#endif
diff --git a/package_bgs/dp/MeanBGS.h b/src/algorithms/dp/MeanBGS.h
similarity index 50%
rename from package_bgs/dp/MeanBGS.h
rename to src/algorithms/dp/MeanBGS.h
index 306af1a8083dba5d34354354f6093f42661846b1..11238353497f3e9a216b597cfc2ce49e3a967b58 100644
--- a/package_bgs/dp/MeanBGS.h
+++ b/src/algorithms/dp/MeanBGS.h
@@ -1,49 +1,15 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* MeanBGS.hpp
-*
-* Purpose: Implementation of a simple temporal mean background
-*		  		 subtraction algorithm.
-*
-* Author: Donovan Parks, September 2007
-*
-
-Example:
-Algorithms::BackgroundSubtraction::MeanParams params;
-params.SetFrameSize(width, height);
-params.LowThreshold() = 3*30*30;
-params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-params.Alpha() = 1e-6f;
-params.LearningFrames() = 30;
-
-Algorithms::BackgroundSubtraction::MeanBGS bgs;
-bgs.Initalize(params);
-******************************************************************************/
 #pragma once
 
 #include "Bgs.h"
 
-namespace Algorithms
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
 {
-  namespace BackgroundSubtraction
+  namespace algorithms
   {
-
+    namespace dp
+    {
     // --- Parameters used by the Mean BGS algorithm ---
     class MeanParams : public BgsParams
     {
@@ -89,6 +55,8 @@ namespace Algorithms
       RgbImageFloat m_mean;
       RgbImage m_background;
     };
-
+    }
   }
 }
+
+#endif
diff --git a/package_bgs/dp/PratiMediodBGS.cpp b/src/algorithms/dp/PratiMediodBGS.cpp
similarity index 84%
rename from package_bgs/dp/PratiMediodBGS.cpp
rename to src/algorithms/dp/PratiMediodBGS.cpp
index 5a15cec302737468bbc2b5376cd3286af4871c00..8c9ee81e522da8073c3de684434739bd33dc0edf 100644
--- a/package_bgs/dp/PratiMediodBGS.cpp
+++ b/src/algorithms/dp/PratiMediodBGS.cpp
@@ -1,42 +1,8 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* PratiMediodBGS.h
-*
-* Purpose: Implementation of the temporal median background
-*		  		 subtraction algorithm described in:
-*
-* [1] "Detecting Moving Objects, Shosts, and Shadows in Video Stream"
-* 			by R. Cucchiara et al (2003)
-*
-* [2] "Reliable Background Suppression for Complex Scenes"
-*				by S. Calderara et al (2006)
-*
-* Author: Donovan Parks, September 2007
-*
-* Please note that this is not an implementation of the complete system
-* given in the above papers. It simply implements the temporal media background
-* subtraction algorithm.
-******************************************************************************/
-
 #include "PratiMediodBGS.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 PratiMediodBGS::PratiMediodBGS()
 {
@@ -270,6 +236,4 @@ void PratiMediodBGS::Subtract(int frame_num, const RgbImage& data,
   Combine(m_mask_low_threshold, m_mask_high_threshold, high_threshold_mark);
 }
 
-
-
-
+#endif
diff --git a/package_bgs/dp/PratiMediodBGS.h b/src/algorithms/dp/PratiMediodBGS.h
similarity index 60%
rename from package_bgs/dp/PratiMediodBGS.h
rename to src/algorithms/dp/PratiMediodBGS.h
index 6bc8f922411e1fbfabb322248fca0d4c295fb58e..203746f5075ba82b832e6ce4a64876a73649637e 100644
--- a/package_bgs/dp/PratiMediodBGS.h
+++ b/src/algorithms/dp/PratiMediodBGS.h
@@ -1,59 +1,16 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* PratiMediodBGS.hpp
-*
-* Purpose: Implementation of the temporal median background
-*		  		 subtraction algorithm described in:
-*
-* [1] "Detecting Moving Objects, Shosts, and Shadows in Video Stream"
-* 			by R. Cucchiara et al (2003)
-*
-* [2] "Reliable Background Suppression for Complex Scenes"
-*				by S. Calderara et al (2006)
-*
-* Author: Donovan Parks, September 2007
-*
-* Please note that this is not an implementation of the complete system
-* given in the above papers. It simply implements the temporal media background
-* subtraction algorithm.
-
-Example:
-Algorithms::BackgroundSubtraction::PratiParams params;
-params.SetFrameSize(width, height);
-params.LowThreshold() = 30;
-params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-params.SamplingRate() = 5;
-params.HistorySize() = 16;
-params.Weight() = 5;
-
-Algorithms::BackgroundSubtraction::PratiMediodBGS bgs;
-bgs.Initalize(params);
-******************************************************************************/
 #pragma once
 
 #include <vector>
 #include "Bgs.h"
 
-namespace Algorithms
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
 {
-  namespace BackgroundSubtraction
+  namespace algorithms
   {
+    namespace dp
+    {
     // --- Parameters used by the Prati Mediod BGS algorithm ---
     class PratiParams : public BgsParams
     {
@@ -127,6 +84,8 @@ namespace Algorithms
       BwImage m_mask_low_threshold;
       BwImage m_mask_high_threshold;
     };
-
+    }
   }
 }
+
+#endif
diff --git a/package_bgs/dp/TextureBGS.cpp b/src/algorithms/dp/TextureBGS.cpp
similarity index 86%
rename from package_bgs/dp/TextureBGS.cpp
rename to src/algorithms/dp/TextureBGS.cpp
index 920f140eecbf302c3e9b4faeecfb08d22c5c9fbd..b0adc222207e7c397b9882c1ca1f8bd9db13fdd6 100644
--- a/package_bgs/dp/TextureBGS.cpp
+++ b/src/algorithms/dp/TextureBGS.cpp
@@ -1,21 +1,9 @@
-/*
-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 "TextureBGS.h"
 
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
+
 TextureBGS::TextureBGS() {}
 TextureBGS::~TextureBGS() {}
 
@@ -151,3 +139,5 @@ void TextureBGS::UpdateModel(BwImage& fgMask, TextureArray* bgModel,
     }
   }
 }
+
+#endif
diff --git a/src/algorithms/dp/TextureBGS.h b/src/algorithms/dp/TextureBGS.h
new file mode 100644
index 0000000000000000000000000000000000000000..da850fdad30083496f2ccfd7c0c9a316221a7c9f
--- /dev/null
+++ b/src/algorithms/dp/TextureBGS.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <math.h>
+#include "Image.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+      const int REGION_R = 5;			// Note: the code currently assumes this value is <= 7
+      const int TEXTURE_POINTS = 6;	// Note: the code currently assumes this value is 6
+      const int TEXTURE_R = 2;		// Note: the code currently assumes this value is 2
+      const int NUM_BINS = 64;		// 2^TEXTURE_POINTS
+      const int HYSTERSIS = 3;
+      const double ALPHA = 0.05f;
+      const double THRESHOLD = 0.5*(REGION_R + REGION_R + 1)*(REGION_R + REGION_R + 1)*NUM_CHANNELS;
+      const int NUM_MODES = 1;		// The paper describes how multiple modes can be maintained,
+      // but this implementation does not fully support more than one
+
+      struct TextureHistogram
+      {
+        unsigned char r[NUM_BINS];	// histogram for red channel
+        unsigned char g[NUM_BINS];	// histogram for green channel
+        unsigned char b[NUM_BINS];	// histogram for blue channel
+      };
+
+      struct TextureArray
+      {
+        TextureHistogram mode[NUM_MODES];
+      };
+
+      class TextureBGS
+      {
+      public:
+        TextureBGS();
+        ~TextureBGS();
+
+        void LBP(RgbImage& image, RgbImage& texture);
+        void Histogram(RgbImage& texture, TextureHistogram* curTextureHist);
+        int ProximityMeasure(TextureHistogram& bgTexture, TextureHistogram& curTextureHist);
+        void BgsCompare(TextureArray* bgModel, TextureHistogram* curTextureHist,
+          unsigned char* modeArray, float threshold, BwImage& fgMask);
+        void UpdateModel(BwImage& fgMask, TextureArray* bgModel,
+          TextureHistogram* curTextureHist, unsigned char* modeArray);
+      };
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/dp/WrenGA.cpp b/src/algorithms/dp/WrenGA.cpp
similarity index 74%
rename from package_bgs/dp/WrenGA.cpp
rename to src/algorithms/dp/WrenGA.cpp
index 80a9e27e746cf14789f7001f412b50adafa87f0d..d29b2061d8ddab3c0c95e75d4f4261b7af7af46c 100644
--- a/package_bgs/dp/WrenGA.cpp
+++ b/src/algorithms/dp/WrenGA.cpp
@@ -1,38 +1,8 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* WrenGA.h
-*
-* Purpose: Implementation of the running Gaussian average background
-*		  		 subtraction algorithm described in:
-*	  			 "Pfinder: real-time tracking of the human body"
-* 						by C. Wren et al (1997)
-*
-* Author: Donovan Parks, September 2007
-*
-* Please note that this is not an implementation of Pfinder. It implements
-* a simple background subtraction algorithm where each pixel is represented
-* by a single Gaussian and update using a simple weighting function.
-******************************************************************************/
-
 #include "WrenGA.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 WrenGA::WrenGA()
 {
@@ -171,3 +141,4 @@ void WrenGA::Subtract(int frame_num, const RgbImage& data,
   }
 }
 
+#endif
diff --git a/src/algorithms/dp/WrenGA.h b/src/algorithms/dp/WrenGA.h
new file mode 100644
index 0000000000000000000000000000000000000000..ede4cf5cbce4fd9de1c01345781f48ef1565d469
--- /dev/null
+++ b/src/algorithms/dp/WrenGA.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "Bgs.h"
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace dp
+    {
+    // --- Parameters used by the Mean BGS algorithm ---
+    class WrenParams : public BgsParams
+    {
+    public:
+      float &LowThreshold() { return m_low_threshold; }
+      float &HighThreshold() { return m_high_threshold; }
+
+      float &Alpha() { return m_alpha; }
+      int &LearningFrames() { return m_learning_frames; }
+
+    private:
+      // The threshold indicates the number of variances (not standard deviations) away
+      // from the mean before a pixel is considered to be from the foreground.
+      float m_low_threshold;
+      float m_high_threshold;
+
+      float m_alpha;
+      int m_learning_frames;
+    };
+
+    // --- Mean BGS algorithm ---
+    class WrenGA : public Bgs
+    {
+    private:
+      struct GAUSSIAN
+      {
+        float mu[NUM_CHANNELS];
+        float var[NUM_CHANNELS];
+      };
+
+    public:
+      WrenGA();
+      ~WrenGA();
+
+      void Initalize(const BgsParams& param);
+
+      void InitModel(const RgbImage& data);
+      void Subtract(int frame_num, const RgbImage& data,
+        BwImage& low_threshold_mask, BwImage& high_threshold_mask);
+      void Update(int frame_num, const RgbImage& data, const BwImage& update_mask);
+
+      RgbImage* Background() { return &m_background; }
+
+    private:
+      void SubtractPixel(int r, int c, const RgbPixel& pixel,
+        unsigned char& lowThreshold, unsigned char& highThreshold);
+
+      WrenParams m_params;
+
+      // Initial variance for the newly generated components.
+      float m_variance;
+
+      // dynamic array for the mixture of Gaussians
+      GAUSSIAN* m_gaussian;
+
+      RgbImage m_background;
+    };
+    }
+  }
+}
+
+#endif
diff --git a/package_bgs/dp/ZivkovicAGMM.cpp b/src/algorithms/dp/ZivkovicAGMM.cpp
similarity index 85%
rename from package_bgs/dp/ZivkovicAGMM.cpp
rename to src/algorithms/dp/ZivkovicAGMM.cpp
index f73d5a145b80710cff510063b1762c260b9c333f..382fbb330c84fe7495a0afdf05cc79c880071eae 100644
--- a/package_bgs/dp/ZivkovicAGMM.cpp
+++ b/src/algorithms/dp/ZivkovicAGMM.cpp
@@ -1,48 +1,8 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* ZivkovicAGMM.cpp
-*
-* Purpose: Implementation of the Gaussian mixture model (GMM) background
-*		  		 subtraction algorithm developed by Z. Zivkovic.
-*
-* Author: Donovan Parks, September 2007
-*
-* This code is based on code by Z. Zivkovic's. I have changed it from a pure
-* C implementation to a cleaner (IMHO) C++ implementation. It is based on the
-* following papers:
-*
-*	"Improved adaptive Gausian mixture model for background subtraction"
-*		Z.Zivkovic
-*		International Conference Pattern Recognition, UK, August, 2004
-*
-*
-* "Efficient Adaptive Density Estimapion per Image Pixel for the
-*			Task of Background Subtraction"
-*		Z.Zivkovic, F. van der Heijden
-*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-******************************************************************************/
-
 #include "ZivkovicAGMM.h"
 
-using namespace Algorithms::BackgroundSubtraction;
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+using namespace bgslibrary::algorithms::dp;
 
 ZivkovicAGMM::ZivkovicAGMM()
 {
@@ -406,3 +366,4 @@ void ZivkovicAGMM::Subtract(int frame_num, const RgbImage& data,
   }
 }
 
+#endif
diff --git a/package_bgs/dp/ZivkovicAGMM.h b/src/algorithms/dp/ZivkovicAGMM.h
similarity index 61%
rename from package_bgs/dp/ZivkovicAGMM.h
rename to src/algorithms/dp/ZivkovicAGMM.h
index 07da9c340edc612e69ee7d6dc1ead7a7f4062b44..b06293531ad1b0df43390227eb7764c9e51419f0 100644
--- a/package_bgs/dp/ZivkovicAGMM.h
+++ b/src/algorithms/dp/ZivkovicAGMM.h
@@ -1,63 +1,15 @@
-/*
-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/>.
-*/
-/****************************************************************************
-*
-* ZivkovicAGMM.hpp
-*
-* Purpose: Implementation of the Gaussian mixture model (GMM) background
-*		  		 subtraction algorithm developed by Z. Zivkovic.
-*
-* Author: Donovan Parks, September 2007
-*
-* This code is based on code by Z. Zivkovic's. I have changed it from a pure
-* C implementation to a cleaner (IMHO) C++ implementation. It is based on the
-* following papers:
-*
-*	"Improved adaptive Gausian mixture model for background subtraction"
-*		Z.Zivkovic
-*		International Conference Pattern Recognition, UK, August, 2004
-*
-*
-* "Efficient Adaptive Density Estimapion per Image Pixel for the
-*			Task of Background Subtraction"
-*		Z.Zivkovic, F. van der Heijden
-*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
-*
-* Zivkovic's code can be obtained at: www.zoranz.net
-
-Example:
-Algorithms::BackgroundSubtraction::ZivkovicParams params;
-params.SetFrameSize(width, height);
-params.LowThreshold() = 5.0f*5.0f;
-params.HighThreshold() = 2*params.LowThreshold();	// Note: high threshold is used by post-processing
-params.Alpha() = 0.001f;
-params.MaxModes() = 3;
-
-Algorithms::BackgroundSubtraction::ZivkovicAGMM bgs;
-bgs.Initalize(params);
-******************************************************************************/
 #pragma once
 
 #include "Bgs.h"
 
-namespace Algorithms
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+
+namespace bgslibrary
 {
-  namespace BackgroundSubtraction
+  namespace algorithms
   {
+    namespace dp
+    {
     // --- User adjustable parameters used by the Grimson GMM BGS algorithm ---
     class ZivkovicParams : public BgsParams
     {
@@ -146,5 +98,8 @@ namespace Algorithms
       //number of Gaussian components per pixel
       unsigned char* m_modes_per_pixel;
     };
+    }
   }
 }
+
+#endif
diff --git a/src/algorithms/lb/BGModel.cpp b/src/algorithms/lb/BGModel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4f71a8f4e22218f54e5e6fb575388d5222eef2f
--- /dev/null
+++ b/src/algorithms/lb/BGModel.cpp
@@ -0,0 +1,50 @@
+#include "BGModel.h"
+
+using namespace bgslibrary::algorithms::lb;
+
+BGModel::BGModel(int width, int height) : m_width(width), m_height(height)
+{
+  m_SrcImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
+  m_BGImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
+  m_FGImage = cvCreateImage(cvSize(m_width, m_height), IPL_DEPTH_8U, 3);
+
+  cvZero(m_SrcImage);
+  cvZero(m_BGImage);
+  cvZero(m_FGImage);
+}
+
+BGModel::~BGModel()
+{
+  if (m_SrcImage != NULL) cvReleaseImage(&m_SrcImage);
+  if (m_BGImage != NULL) cvReleaseImage(&m_BGImage);
+  if (m_FGImage != NULL) cvReleaseImage(&m_FGImage);
+}
+
+IplImage* BGModel::GetSrc()
+{
+  return m_SrcImage;
+}
+
+IplImage* BGModel::GetFG()
+{
+  return m_FGImage;
+}
+
+IplImage* BGModel::GetBG()
+{
+  return m_BGImage;
+}
+
+void BGModel::InitModel(IplImage* image)
+{
+  cvCopy(image, m_SrcImage);
+  Init();
+  return;
+}
+
+void BGModel::UpdateModel(IplImage* image)
+{
+  cvCopy(image, m_SrcImage);
+  Update();
+  return;
+}
diff --git a/src/algorithms/lb/BGModel.h b/src/algorithms/lb/BGModel.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb0bb4c09b1838564300c6cbf9c29ddfc2046b95
--- /dev/null
+++ b/src/algorithms/lb/BGModel.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <math.h>
+#include <float.h>
+
+#include <opencv2/opencv.hpp>
+
+#include "Types.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      class BGModel
+      {
+      public:
+
+        BGModel(int width, int height);
+        virtual ~BGModel();
+
+        void InitModel(IplImage* image);
+        void UpdateModel(IplImage* image);
+
+        virtual void setBGModelParameter(int id, int value) {};
+
+        virtual IplImage* GetSrc();
+        virtual IplImage* GetFG();
+        virtual IplImage* GetBG();
+
+      protected:
+
+        IplImage* m_SrcImage;
+        IplImage* m_BGImage;
+        IplImage* m_FGImage;
+
+        const unsigned int m_width;
+        const unsigned int m_height;
+
+        virtual void Init() = 0;
+        virtual void Update() = 0;
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/BGModelFuzzyGauss.cpp b/src/algorithms/lb/BGModelFuzzyGauss.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ead2406ff00a3afe14a85fddde795a1ebc0114b
--- /dev/null
+++ b/src/algorithms/lb/BGModelFuzzyGauss.cpp
@@ -0,0 +1,171 @@
+#include "BGModelFuzzyGauss.h"
+
+using namespace bgslibrary::algorithms::lb;
+using namespace bgslibrary::algorithms::lb::BGModelFuzzyGaussParams;
+
+BGModelFuzzyGauss::BGModelFuzzyGauss(int width, int height) : BGModel(width, height)
+{
+  m_alphamax = ALPHAFUZZYGAUSS;
+  m_threshold = THRESHOLDFUZZYGAUSS * THRESHOLDFUZZYGAUSS;
+  m_threshBG = THRESHOLDBG;
+  m_noise = NOISEFUZZYGAUSS;
+
+  m_pMu = new DBLRGB[m_width * m_height];
+  m_pVar = new DBLRGB[m_width * m_height];
+
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  for (unsigned int k = 0; k < (m_width * m_height); k++)
+  {
+    pMu->Red = 0.0;
+    pMu->Green = 0.0;
+    pMu->Blue = 0.0;
+
+    pVar->Red = m_noise;
+    pVar->Green = m_noise;
+    pVar->Blue = m_noise;
+
+    pMu++;
+    pVar++;
+  }
+}
+
+BGModelFuzzyGauss::~BGModelFuzzyGauss()
+{
+  delete[] m_pMu;
+  delete[] m_pVar;
+}
+
+void BGModelFuzzyGauss::setBGModelParameter(int id, int value)
+{
+  double dvalue = (double)value / 255.0;
+
+  switch (id)
+  {
+  case 0:
+    m_threshold = 100.0*dvalue*dvalue;
+    break;
+
+  case 1:
+    m_threshBG = dvalue;
+    break;
+
+  case 2:
+    m_alphamax = dvalue*dvalue*dvalue;
+    break;
+
+  case 3:
+    m_noise = 100.0*dvalue;
+    break;
+  }
+
+  return;
+}
+
+void BGModelFuzzyGauss::Init()
+{
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      pMu->Red = prgbSrc[i][j].Red;
+      pMu->Green = prgbSrc[i][j].Green;
+      pMu->Blue = prgbSrc[i][j].Blue;
+
+      pVar->Red = m_noise;
+      pVar->Green = m_noise;
+      pVar->Blue = m_noise;
+
+      pMu++;
+      pVar++;
+    }
+  }
+
+  return;
+}
+
+void BGModelFuzzyGauss::Update()
+{
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+  Image<BYTERGB> prgbBG(m_BGImage);
+  Image<BYTERGB> prgbFG(m_FGImage);
+
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      double srcR = (double)prgbSrc[i][j].Red;
+      double srcG = (double)prgbSrc[i][j].Green;
+      double srcB = (double)prgbSrc[i][j].Blue;
+
+      // Fuzzy background subtraction (Mahalanobis distance)
+
+      double dr = srcR - pMu->Red;
+      double dg = srcG - pMu->Green;
+      double db = srcB - pMu->Blue;
+
+      double d2 = dr*dr / pVar->Red + dg*dg / pVar->Green + db*db / pVar->Blue;
+
+      double fuzzyBG = 1.0;
+
+      if (d2 < m_threshold)
+        fuzzyBG = d2 / m_threshold;
+
+      // Fuzzy running average
+
+      double alpha = m_alphamax*exp(FUZZYEXP*fuzzyBG);
+
+      if (dr*dr > DBL_MIN)
+        pMu->Red += alpha*dr;
+
+      if (dg*dg > DBL_MIN)
+        pMu->Green += alpha*dg;
+
+      if (db*db > DBL_MIN)
+        pMu->Blue += alpha*db;
+
+      double d;
+
+      d = (srcR - pMu->Red)*(srcR - pMu->Red) - pVar->Red;
+      if (d*d > DBL_MIN)
+        pVar->Red += alpha*d;
+
+      d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green;
+      if (d*d > DBL_MIN)
+        pVar->Green += alpha*d;
+
+      d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue;
+      if (d*d > DBL_MIN)
+        pVar->Blue += alpha*d;
+
+      pVar->Red = (std::max)(pVar->Red, m_noise);
+      pVar->Green = (std::max)(pVar->Green, m_noise);
+      pVar->Blue = (std::max)(pVar->Blue, m_noise);
+
+      // Set foreground and background
+
+      if (fuzzyBG >= m_threshBG)
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
+      else
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
+
+      prgbBG[i][j].Red = (unsigned char)pMu->Red;
+      prgbBG[i][j].Green = (unsigned char)pMu->Green;
+      prgbBG[i][j].Blue = (unsigned char)pMu->Blue;
+
+      pMu++;
+      pVar++;
+    }
+  }
+
+  return;
+}
diff --git a/src/algorithms/lb/BGModelFuzzyGauss.h b/src/algorithms/lb/BGModelFuzzyGauss.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d4070e4501e820852ec5dcf2777894b4808c1c4
--- /dev/null
+++ b/src/algorithms/lb/BGModelFuzzyGauss.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "BGModel.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      namespace BGModelFuzzyGaussParams {
+        const float ALPHAFUZZYGAUSS = 0.02f;
+        const float THRESHOLDFUZZYGAUSS = 3.5f;
+        const float THRESHOLDBG = 0.5f;
+        const float NOISEFUZZYGAUSS = 50.0f;
+        const float FUZZYEXP = -5.0f;
+      }
+
+      class BGModelFuzzyGauss : public BGModel
+      {
+      public:
+        BGModelFuzzyGauss(int width, int height);
+        ~BGModelFuzzyGauss();
+
+        void setBGModelParameter(int id, int value);
+
+      protected:
+        double m_alphamax;
+        double m_threshold;
+        double m_threshBG;
+        double m_noise;
+
+        DBLRGB* m_pMu;
+        DBLRGB* m_pVar;
+
+        void Init();
+        void Update();
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/BGModelFuzzySom.cpp b/src/algorithms/lb/BGModelFuzzySom.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74eef2cf875665391c7c40700954fe767c1797f2
--- /dev/null
+++ b/src/algorithms/lb/BGModelFuzzySom.cpp
@@ -0,0 +1,259 @@
+#include "BGModelFuzzySom.h"
+
+using namespace bgslibrary::algorithms::lb;
+using namespace bgslibrary::algorithms::lb::BGModelFuzzySomParams;
+
+BGModelFuzzySom::BGModelFuzzySom(int width, int height) : BGModel(width, height)
+{
+  m_offset = (KERNEL - 1) / 2;
+
+  if (SPAN_NEIGHBORS)
+    m_pad = 0;
+  else
+    m_pad = m_offset;
+
+  // SOM models
+
+  m_widthSOM = m_width*M + 2 * m_offset + (m_width - 1)*m_pad;
+  m_heightSOM = m_height*N + 2 * m_offset + (m_height - 1)*m_pad;
+
+  m_ppSOM = new DBLRGB*[m_heightSOM];
+  for (int n = 0; n < m_heightSOM; n++)
+    m_ppSOM[n] = new DBLRGB[m_widthSOM];
+
+  for (int j = 0; j < m_heightSOM; j++)
+  {
+    for (int i = 0; i < m_widthSOM; i++)
+    {
+      m_ppSOM[j][i].Red = 0.0;
+      m_ppSOM[j][i].Green = 0.0;
+      m_ppSOM[j][i].Blue = 0.0;
+    }
+  }
+
+  // Create weights
+
+  m_ppW = new double*[KERNEL];
+  for (int n = 0; n < KERNEL; n++)
+    m_ppW[n] = new double[KERNEL];
+
+  // Construct Gaussian kernel using Pascal's triangle
+
+  int cM;
+  int cN;
+  m_Wmax = DBL_MIN;
+
+  cN = 1;
+  for (int j = 0; j < KERNEL; j++)
+  {
+    cM = 1;
+
+    for (int i = 0; i < KERNEL; i++)
+    {
+      m_ppW[j][i] = cN*cM;
+
+      if (m_ppW[j][i] > m_Wmax)
+        m_Wmax = m_ppW[j][i];
+
+      cM = cM * (KERNEL - 1 - i) / (i + 1);
+    }
+
+    cN = cN * (KERNEL - 1 - j) / (j + 1);
+  }
+
+  // Parameters
+
+  m_epsilon1 = EPS1*EPS1;
+  m_epsilon2 = EPS2*EPS2;
+
+  m_alpha1 = C1 / m_Wmax;
+  m_alpha2 = C2 / m_Wmax;
+
+  m_K = 0;
+  m_TSteps = TRAINING_STEPS;
+}
+
+BGModelFuzzySom::~BGModelFuzzySom()
+{
+  for (int n = 0; n < m_heightSOM; n++)
+    delete[] m_ppSOM[n];
+
+  delete[] m_ppSOM;
+
+  for (int n = 0; n < KERNEL; n++)
+    delete[] m_ppW[n];
+
+  delete[] m_ppW;
+}
+
+void BGModelFuzzySom::setBGModelParameter(int id, int value)
+{
+  double dvalue = (double)value / 255.0;
+
+  switch (id)
+  {
+  case 0:
+    m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
+    break;
+
+  case 1:
+    m_epsilon1 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
+    break;
+
+  case 2:
+    m_alpha2 = dvalue*dvalue*dvalue / m_Wmax;
+    break;
+
+  case 3:
+    m_alpha1 = dvalue*dvalue*dvalue / m_Wmax;
+    break;
+
+  case 5:
+    m_TSteps = (int)(255.0*dvalue);
+    break;
+  }
+
+  return;
+}
+
+void BGModelFuzzySom::Init()
+{
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+
+  for (unsigned int j = 0; j < m_height; j++)
+  {
+    int jj = m_offset + j*(N + m_pad);
+
+    for (unsigned int i = 0; i < m_width; i++)
+    {
+      int ii = m_offset + i*(M + m_pad);
+
+      for (int l = 0; l < N; l++)
+      {
+        for (int k = 0; k < M; k++)
+        {
+          m_ppSOM[jj + l][ii + k].Red = (double)prgbSrc[j][i].Red;
+          m_ppSOM[jj + l][ii + k].Green = (double)prgbSrc[j][i].Green;
+          m_ppSOM[jj + l][ii + k].Blue = (double)prgbSrc[j][i].Blue;
+        }
+      }
+    }
+  }
+
+  m_K = 0;
+
+  return;
+}
+
+void BGModelFuzzySom::Update()
+{
+  double alpha, a;
+  double epsilon;
+
+  // calibration phase
+  if (m_K <= m_TSteps)
+  {
+    epsilon = m_epsilon1;
+    alpha = (m_alpha1 - m_K * (m_alpha1 - m_alpha2) / m_TSteps);
+    m_K++;
+  }
+  else // online phase
+  {
+    epsilon = m_epsilon2;
+    alpha = m_alpha2;
+  }
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+  Image<BYTERGB> prgbBG(m_BGImage);
+  Image<BYTERGB> prgbFG(m_FGImage);
+
+  for (unsigned int j = 0; j < m_height; j++)
+  {
+    int jj = m_offset + j*(N + m_pad);
+
+    for (unsigned int i = 0; i < m_width; i++)
+    {
+      int ii = m_offset + i*(M + m_pad);
+
+      double srcR = (double)prgbSrc[j][i].Red;
+      double srcG = (double)prgbSrc[j][i].Green;
+      double srcB = (double)prgbSrc[j][i].Blue;
+
+      // Find BMU
+
+      double d2min = DBL_MAX;
+      int iiHit = ii;
+      int jjHit = jj;
+
+      for (int l = 0; l < N; l++)
+      {
+        for (int k = 0; k < M; k++)
+        {
+          double dr = srcR - m_ppSOM[jj + l][ii + k].Red;
+          double dg = srcG - m_ppSOM[jj + l][ii + k].Green;
+          double db = srcB - m_ppSOM[jj + l][ii + k].Blue;
+
+          double d2 = dr*dr + dg*dg + db*db;
+
+          if (d2 < d2min)
+          {
+            d2min = d2;
+            iiHit = ii + k;
+            jjHit = jj + l;
+          }
+        }
+      }
+
+      double fuzzyBG = 1.0;
+
+      if (d2min < epsilon)
+        fuzzyBG = d2min / epsilon;
+
+      // Update SOM
+
+      double alphamax = alpha*exp(FUZZYEXP*fuzzyBG);
+
+      for (int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++)
+      {
+        for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++)
+        {
+          a = alphamax * m_ppW[l - jjHit + m_offset][k - iiHit + m_offset];
+
+          // speed hack.. avoid very small increment values. abs() is sloooow.
+
+          double d;
+
+          d = srcR - m_ppSOM[l][k].Red;
+          if (d*d > DBL_MIN)
+            m_ppSOM[l][k].Red += a*d;
+
+          d = srcG - m_ppSOM[l][k].Green;
+          if (d*d > DBL_MIN)
+            m_ppSOM[l][k].Green += a*d;
+
+          d = srcB - m_ppSOM[l][k].Blue;
+          if (d*d > DBL_MIN)
+            m_ppSOM[l][k].Blue += a*d;
+        }
+      }
+
+      if (fuzzyBG >= FUZZYTHRESH)
+      {
+        // Set foreground image
+        prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 255;
+      }
+      else
+      {
+        // Set background image
+        prgbBG[j][i].Red = m_ppSOM[jjHit][iiHit].Red;
+        prgbBG[j][i].Green = m_ppSOM[jjHit][iiHit].Green;
+        prgbBG[j][i].Blue = m_ppSOM[jjHit][iiHit].Blue;
+
+        // Set foreground image
+        prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 0;
+      }
+    }
+  }
+
+  return;
+}
diff --git a/src/algorithms/lb/BGModelFuzzySom.h b/src/algorithms/lb/BGModelFuzzySom.h
new file mode 100644
index 0000000000000000000000000000000000000000..58a477a890703c956c2d026a8cae622f63cf5179
--- /dev/null
+++ b/src/algorithms/lb/BGModelFuzzySom.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "BGModel.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      namespace BGModelFuzzySomParams {
+        const int M = 3;      // width SOM (per pixel)
+        const int N = 3;      // height SOM (per pixel)
+        const int KERNEL = 3; // size Gaussian kernel
+        const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels			//
+        const int TRAINING_STEPS = 100;    // number of training steps
+        const double EPS1 = 100.0; // model match distance during training
+        const double EPS2 = 20.0;  // model match distance
+        const double C1 = 1.0;     // learning rate during training
+        const double C2 = 0.05;    // learning rate
+        const double FUZZYEXP = -5.0;
+        const double FUZZYTHRESH = 0.8;
+      }
+
+      class BGModelFuzzySom : public BGModel
+      {
+      public:
+        BGModelFuzzySom(int width, int height);
+        ~BGModelFuzzySom();
+
+        void setBGModelParameter(int id, int value);
+
+      protected:
+        int m_widthSOM;
+        int m_heightSOM;
+        int m_offset;
+        int m_pad;
+        int m_K;
+        int m_TSteps;
+
+        double m_Wmax;
+
+        double m_epsilon1;
+        double m_epsilon2;
+        double m_alpha1;
+        double m_alpha2;
+
+        DBLRGB** m_ppSOM;  // SOM grid
+        double** m_ppW;    // Weights
+
+        void Init();
+        void Update();
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/BGModelGauss.cpp b/src/algorithms/lb/BGModelGauss.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fbb006a0bc2cd69b719960e5685946df568bca16
--- /dev/null
+++ b/src/algorithms/lb/BGModelGauss.cpp
@@ -0,0 +1,161 @@
+#include "BGModelGauss.h"
+
+using namespace bgslibrary::algorithms::lb;
+using namespace bgslibrary::algorithms::lb::BGModelGaussParams;
+
+BGModelGauss::BGModelGauss(int width, int height) : BGModel(width, height)
+{
+  m_alpha = ALPHAGAUSS;
+  m_threshold = THRESHGAUSS*THRESHGAUSS;
+  m_noise = NOISEGAUSS;
+
+  m_pMu = new DBLRGB[m_width * m_height];
+  m_pVar = new DBLRGB[m_width * m_height];
+
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  for (unsigned int k = 0; k < (m_width * m_height); k++)
+  {
+    pMu->Red = 0.0;
+    pMu->Green = 0.0;
+    pMu->Blue = 0.0;
+
+    pVar->Red = m_noise;
+    pVar->Green = m_noise;
+    pVar->Blue = m_noise;
+
+    pMu++;
+    pVar++;
+  }
+}
+
+BGModelGauss::~BGModelGauss()
+{
+  delete[] m_pMu;
+  delete[] m_pVar;
+}
+
+void BGModelGauss::setBGModelParameter(int id, int value)
+{
+  double dvalue = (double)value / 255.0;
+
+  switch (id)
+  {
+  case 0:
+    m_threshold = 100.0*dvalue*dvalue;
+    break;
+
+  case 1:
+    m_noise = 100.0*dvalue;
+    break;
+
+  case 2:
+    m_alpha = dvalue*dvalue*dvalue;
+    break;
+  }
+
+  return;
+}
+
+void BGModelGauss::Init()
+{
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      pMu->Red = prgbSrc[i][j].Red;
+      pMu->Green = prgbSrc[i][j].Green;
+      pMu->Blue = prgbSrc[i][j].Blue;
+
+      pVar->Red = m_noise;
+      pVar->Green = m_noise;
+      pVar->Blue = m_noise;
+
+      pMu++;
+      pVar++;
+    }
+  }
+
+  return;
+}
+
+void BGModelGauss::Update()
+{
+  DBLRGB *pMu = m_pMu;
+  DBLRGB *pVar = m_pVar;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+  Image<BYTERGB> prgbBG(m_BGImage);
+  Image<BYTERGB> prgbFG(m_FGImage);
+
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      double srcR = (double)prgbSrc[i][j].Red;
+      double srcG = (double)prgbSrc[i][j].Green;
+      double srcB = (double)prgbSrc[i][j].Blue;
+
+      // Mahalanobis distance
+
+      double dr = srcR - pMu->Red;
+      double dg = srcG - pMu->Green;
+      double db = srcB - pMu->Blue;
+
+      double d2 = dr*dr / pVar->Red + dg*dg / pVar->Green + db*db / pVar->Blue;
+
+      // Classify
+
+      if (d2 < m_threshold)
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
+      else
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
+
+      // Update parameters
+
+      if (dr*dr > DBL_MIN)
+        pMu->Red += m_alpha*dr;
+
+      if (dg*dg > DBL_MIN)
+        pMu->Green += m_alpha*dg;
+
+      if (db*db > DBL_MIN)
+        pMu->Blue += m_alpha*db;
+
+      double d;
+
+      d = (srcR - pMu->Red)*(srcR - pMu->Red) - pVar->Red;
+      if (d*d > DBL_MIN)
+        pVar->Red += m_alpha*d;
+
+      d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green;
+      if (d*d > DBL_MIN)
+        pVar->Green += m_alpha*d;
+
+      d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue;
+      if (d*d > DBL_MIN)
+        pVar->Blue += m_alpha*d;
+
+      pVar->Red = (std::min)(pVar->Red, m_noise);
+      pVar->Green = (std::min)(pVar->Green, m_noise);
+      pVar->Blue = (std::min)(pVar->Blue, m_noise);
+
+      // Set background
+
+      prgbBG[i][j].Red = (unsigned char)pMu->Red;
+      prgbBG[i][j].Green = (unsigned char)pMu->Green;
+      prgbBG[i][j].Blue = (unsigned char)pMu->Blue;
+
+      pMu++;
+      pVar++;
+    }
+  }
+
+  return;
+}
diff --git a/src/algorithms/lb/BGModelGauss.h b/src/algorithms/lb/BGModelGauss.h
new file mode 100644
index 0000000000000000000000000000000000000000..42945c14209741bef773ca95d1a3a9642f71b131
--- /dev/null
+++ b/src/algorithms/lb/BGModelGauss.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "BGModel.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      namespace BGModelGaussParams {
+        const double THRESHGAUSS = 2.5;   // Threshold
+        const double ALPHAGAUSS = 0.0001; // Learning rate
+        const double NOISEGAUSS = 50.0;   // Minimum variance (noise)
+      }
+      
+      class BGModelGauss : public BGModel
+      {
+      public:
+        BGModelGauss(int width, int height);
+        ~BGModelGauss();
+
+        void setBGModelParameter(int id, int value);
+
+      protected:
+        double m_alpha;
+        double m_threshold;
+        double m_noise;
+
+        DBLRGB* m_pMu;
+        DBLRGB* m_pVar;
+
+        void Init();
+        void Update();
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/BGModelMog.cpp b/src/algorithms/lb/BGModelMog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c23055f281ec3cd083cf7c1196792134f80bd95c
--- /dev/null
+++ b/src/algorithms/lb/BGModelMog.cpp
@@ -0,0 +1,270 @@
+#include "BGModelMog.h"
+
+using namespace bgslibrary::algorithms::lb;
+using namespace bgslibrary::algorithms::lb::BGModelMogParams;
+
+BGModelMog::BGModelMog(int width, int height) : BGModel(width, height)
+{
+  m_alpha = LEARNINGRATEMOG;
+  m_threshold = THRESHOLDMOG*THRESHOLDMOG;
+  m_noise = INITIALVARMOG;
+
+  m_T = BGTHRESHOLDMOG;
+
+  m_pMOG = new MOGDATA[NUMBERGAUSSIANS*m_width*m_height];
+  m_pK = new int[m_width*m_height];
+
+  MOGDATA *pMOG = m_pMOG;
+  int *pK = m_pK;
+
+  for (unsigned int i = 0; i < (m_width * m_height); i++)
+  {
+    for (unsigned int k = 0; k < NUMBERGAUSSIANS; k++)
+    {
+      pMOG->mu.Red = 0.0;
+      pMOG->mu.Green = 0.0;
+      pMOG->mu.Blue = 0.0;
+
+      pMOG->var.Red = 0.0;
+      pMOG->var.Green = 0.0;
+      pMOG->var.Blue = 0.0;
+
+      pMOG->w = 0.0;
+      pMOG->sortKey = 0.0;
+
+      pMOG++;
+    }
+
+    pK[i] = 0;
+  }
+}
+
+BGModelMog::~BGModelMog()
+{
+  delete[] m_pMOG;
+  delete[] m_pK;
+}
+
+void BGModelMog::setBGModelParameter(int id, int value)
+{
+  double dvalue = (double)value / 255.0;
+
+  switch (id)
+  {
+  case 0:
+    m_threshold = 100.0*dvalue*dvalue;
+    break;
+
+  case 1:
+    m_T = dvalue;
+    break;
+
+  case 2:
+    m_alpha = dvalue*dvalue*dvalue;
+    break;
+
+  case 3:
+    m_noise = 100.0*dvalue;;
+    break;
+  }
+
+  return;
+}
+
+void BGModelMog::Init()
+{
+  MOGDATA *pMOG = m_pMOG;
+  int *pK = m_pK;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+
+  int n = 0;
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      pMOG[0].mu.Red = prgbSrc[i][j].Red;
+      pMOG[0].mu.Green = prgbSrc[i][j].Green;
+      pMOG[0].mu.Blue = prgbSrc[i][j].Blue;
+
+      pMOG[0].var.Red = m_noise;
+      pMOG[0].var.Green = m_noise;
+      pMOG[0].var.Blue = m_noise;
+
+      pMOG[0].w = 1.0;
+      pMOG[0].sortKey = pMOG[0].w / sqrt(pMOG[0].var.Red + pMOG[0].var.Green + pMOG[0].var.Blue);
+
+      pK[n] = 1;
+      n++;
+
+      pMOG += NUMBERGAUSSIANS;
+    }
+  }
+
+  return;
+}
+
+void BGModelMog::Update()
+{
+  int kBG;
+
+  MOGDATA *pMOG = m_pMOG;
+  int *pK = m_pK;
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+  Image<BYTERGB> prgbBG(m_BGImage);
+  Image<BYTERGB> prgbFG(m_FGImage);
+
+  int n = 0;
+  for (unsigned int i = 0; i < m_height; i++)
+  {
+    for (unsigned int j = 0; j < m_width; j++)
+    {
+      double srcR = (double)prgbSrc[i][j].Red;
+      double srcG = (double)prgbSrc[i][j].Green;
+      double srcB = (double)prgbSrc[i][j].Blue;
+
+      // Find matching distribution
+
+      int kHit = -1;
+
+      for (int k = 0; k < pK[n]; k++)
+      {
+        // Mahalanobis distance
+        double dr = srcR - pMOG[k].mu.Red;
+        double dg = srcG - pMOG[k].mu.Green;
+        double db = srcB - pMOG[k].mu.Blue;
+        double d2 = dr*dr / pMOG[k].var.Red + dg*dg / pMOG[k].var.Green + db*db / pMOG[k].var.Blue;
+
+        if (d2 < m_threshold)
+        {
+          kHit = k;
+          break;
+        }
+      }
+
+      // Adjust parameters
+
+      // matching distribution found
+      if (kHit != -1)
+      {
+        for (int k = 0; k < pK[n]; k++)
+        {
+          if (k == kHit)
+          {
+            pMOG[k].w = pMOG[k].w + m_alpha*(1.0f - pMOG[k].w);
+
+            double d;
+
+            d = srcR - pMOG[k].mu.Red;
+            if (d*d > DBL_MIN)
+              pMOG[k].mu.Red += m_alpha*d;
+
+            d = srcG - pMOG[k].mu.Green;
+            if (d*d > DBL_MIN)
+              pMOG[k].mu.Green += m_alpha*d;
+
+            d = srcB - pMOG[k].mu.Blue;
+            if (d*d > DBL_MIN)
+              pMOG[k].mu.Blue += m_alpha*d;
+
+            d = (srcR - pMOG[k].mu.Red)*(srcR - pMOG[k].mu.Red) - pMOG[k].var.Red;
+            if (d*d > DBL_MIN)
+              pMOG[k].var.Red += m_alpha*d;
+
+            d = (srcG - pMOG[k].mu.Green)*(srcG - pMOG[k].mu.Green) - pMOG[k].var.Green;
+            if (d*d > DBL_MIN)
+              pMOG[k].var.Green += m_alpha*d;
+
+            d = (srcB - pMOG[k].mu.Blue)*(srcB - pMOG[k].mu.Blue) - pMOG[k].var.Blue;
+            if (d*d > DBL_MIN)
+              pMOG[k].var.Blue += m_alpha*d;
+
+            pMOG[k].var.Red = (std::max)(pMOG[k].var.Red, m_noise);
+            pMOG[k].var.Green = (std::max)(pMOG[k].var.Green, m_noise);
+            pMOG[k].var.Blue = (std::max)(pMOG[k].var.Blue, m_noise);
+          }
+          else
+            pMOG[k].w = (1.0 - m_alpha)*pMOG[k].w;
+        }
+      }
+      // no match found... create new one
+      else
+      {
+        if (pK[n] < NUMBERGAUSSIANS)
+          pK[n]++;
+
+        kHit = pK[n] - 1;
+
+        if (pK[n] == 1)
+          pMOG[kHit].w = 1.0;
+        else
+          pMOG[kHit].w = LEARNINGRATEMOG;
+
+        pMOG[kHit].mu.Red = srcR;
+        pMOG[kHit].mu.Green = srcG;
+        pMOG[kHit].mu.Blue = srcB;
+
+        pMOG[kHit].var.Red = m_noise;
+        pMOG[kHit].var.Green = m_noise;
+        pMOG[kHit].var.Blue = m_noise;
+      }
+
+      // Normalize weights
+
+      double wsum = 0.0;
+
+      for (int k = 0; k < pK[n]; k++)
+        wsum += pMOG[k].w;
+
+      double wfactor = 1.0 / wsum;
+
+      for (int k = 0; k < pK[n]; k++)
+      {
+        pMOG[k].w *= wfactor;
+        pMOG[k].sortKey = pMOG[k].w / sqrt(pMOG[k].var.Red + pMOG[k].var.Green + pMOG[k].var.Blue);
+      }
+
+      // Sort distributions
+
+      for (int k = 0; k < kHit; k++)
+      {
+        if (pMOG[kHit].sortKey > pMOG[k].sortKey)
+        {
+          std::swap(pMOG[kHit], pMOG[k]);
+          break;
+        }
+      }
+
+      // Determine background distributions
+
+      wsum = 0.0;
+
+      for (int k = 0; k < pK[n]; k++)
+      {
+        wsum += pMOG[k].w;
+
+        if (wsum > m_T)
+        {
+          kBG = k;
+          break;
+        }
+      }
+
+      if (kHit > kBG)
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255;
+      else
+        prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 0;
+
+      prgbBG[i][j].Red = (unsigned char)pMOG[0].mu.Red;
+      prgbBG[i][j].Green = (unsigned char)pMOG[0].mu.Green;
+      prgbBG[i][j].Blue = (unsigned char)pMOG[0].mu.Blue;
+
+      pMOG += NUMBERGAUSSIANS;
+
+      n++;
+    }
+  }
+
+  return;
+}
diff --git a/src/algorithms/lb/BGModelMog.h b/src/algorithms/lb/BGModelMog.h
new file mode 100644
index 0000000000000000000000000000000000000000..06fd1d066c9e4939f32b858752810c12c05724e7
--- /dev/null
+++ b/src/algorithms/lb/BGModelMog.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "BGModel.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      namespace BGModelMogParams {
+        const unsigned int NUMBERGAUSSIANS = 3;
+        const float LEARNINGRATEMOG = 0.001f;
+        const float THRESHOLDMOG = 2.5f;
+        const float BGTHRESHOLDMOG = 0.5f;
+        const float INITIALVARMOG = 50.0f;
+      }
+
+      typedef struct tagMOGDATA
+      {
+        DBLRGB mu;
+        DBLRGB var;
+        double w;
+        double sortKey;
+      } MOGDATA;
+
+      class BGModelMog : public BGModel
+      {
+      public:
+        BGModelMog(int width, int height);
+        ~BGModelMog();
+
+        void setBGModelParameter(int id, int value);
+
+      protected:
+        double m_alpha;
+        double m_threshold;
+        double m_noise;
+        double m_T;
+
+        MOGDATA* m_pMOG;
+        int* m_pK;				// number of distributions per pixel
+
+        void Init();
+        void Update();
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/BGModelSom.cpp b/src/algorithms/lb/BGModelSom.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..040a1daadb31fcbf80266c2ce21824c206162dbd
--- /dev/null
+++ b/src/algorithms/lb/BGModelSom.cpp
@@ -0,0 +1,252 @@
+#include "BGModelSom.h"
+
+using namespace bgslibrary::algorithms::lb;
+using namespace bgslibrary::algorithms::lb::BGModelSomParams;
+
+BGModelSom::BGModelSom(int width, int height) : BGModel(width, height)
+{
+  m_offset = (KERNEL - 1) / 2;
+
+  if (SPAN_NEIGHBORS)
+    m_pad = 0;
+  else
+    m_pad = m_offset;
+
+  // SOM models
+
+  m_widthSOM = m_width*M + 2 * m_offset + (m_width - 1)*m_pad;
+  m_heightSOM = m_height*N + 2 * m_offset + (m_height - 1)*m_pad;
+
+  m_ppSOM = new DBLRGB*[m_heightSOM];
+  for (int n = 0; n < m_heightSOM; n++)
+    m_ppSOM[n] = new DBLRGB[m_widthSOM];
+
+  for (int j = 0; j < m_heightSOM; j++)
+  {
+    for (int i = 0; i < m_widthSOM; i++)
+    {
+      m_ppSOM[j][i].Red = 0.0;
+      m_ppSOM[j][i].Green = 0.0;
+      m_ppSOM[j][i].Blue = 0.0;
+    }
+  }
+
+  // Create weights
+
+  m_ppW = new double*[KERNEL];
+  for (int n = 0; n < KERNEL; n++)
+    m_ppW[n] = new double[KERNEL];
+
+  // Construct Gaussian kernel using Pascal's triangle
+
+  int cM;
+  int cN;
+  m_Wmax = DBL_MIN;
+
+  cN = 1;
+  for (int j = 0; j < KERNEL; j++)
+  {
+    cM = 1;
+
+    for (int i = 0; i < KERNEL; i++)
+    {
+      m_ppW[j][i] = cN*cM;
+
+      if (m_ppW[j][i] > m_Wmax)
+        m_Wmax = m_ppW[j][i];
+
+      cM = cM * (KERNEL - 1 - i) / (i + 1);
+    }
+
+    cN = cN * (KERNEL - 1 - j) / (j + 1);
+  }
+
+  // Parameters
+
+  m_epsilon1 = EPS1*EPS1;
+  m_epsilon2 = EPS2*EPS2;
+
+  m_alpha1 = C1 / m_Wmax;
+  m_alpha2 = C2 / m_Wmax;
+
+  m_K = 0;
+  m_TSteps = TRAINING_STEPS;
+}
+
+BGModelSom::~BGModelSom()
+{
+  for (int n = 0; n < m_heightSOM; n++)
+    delete[] m_ppSOM[n];
+
+  delete[] m_ppSOM;
+
+  for (int n = 0; n < KERNEL; n++)
+    delete[] m_ppW[n];
+
+  delete[] m_ppW;
+}
+
+void BGModelSom::setBGModelParameter(int id, int value)
+{
+  double dvalue = (double)value / 255.0;
+
+  switch (id)
+  {
+  case 0:
+    m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
+    break;
+
+  case 1:
+    m_epsilon1 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue;
+    break;
+
+  case 2:
+    m_alpha2 = dvalue*dvalue*dvalue / m_Wmax;
+    break;
+
+  case 3:
+    m_alpha1 = dvalue*dvalue*dvalue / m_Wmax;
+    break;
+
+  case 5:
+    m_TSteps = (int)(255.0*dvalue);
+    break;
+  }
+
+  return;
+}
+
+void BGModelSom::Init()
+{
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+
+  for (unsigned int j = 0; j < m_height; j++)
+  {
+    int jj = m_offset + j*(N + m_pad);
+
+    for (unsigned int i = 0; i < m_width; i++)
+    {
+      int ii = m_offset + i*(M + m_pad);
+
+      for (int l = 0; l < N; l++)
+      {
+        for (int k = 0; k < M; k++)
+        {
+          m_ppSOM[jj + l][ii + k].Red = (double)prgbSrc[j][i].Red;
+          m_ppSOM[jj + l][ii + k].Green = (double)prgbSrc[j][i].Green;
+          m_ppSOM[jj + l][ii + k].Blue = (double)prgbSrc[j][i].Blue;
+        }
+      }
+    }
+  }
+
+  m_K = 0;
+
+  return;
+}
+
+void BGModelSom::Update()
+{
+  double alpha, a;
+  double epsilon;
+
+  // calibration phase
+  if (m_K <= m_TSteps)
+  {
+    epsilon = m_epsilon1;
+    alpha = (m_alpha1 - m_K*(m_alpha1 - m_alpha2) / m_TSteps);
+    m_K++;
+  }
+  else // online phase
+  {
+    epsilon = m_epsilon2;
+    alpha = m_alpha2;
+  }
+
+  Image<BYTERGB> prgbSrc(m_SrcImage);
+  Image<BYTERGB> prgbBG(m_BGImage);
+  Image<BYTERGB> prgbFG(m_FGImage);
+
+  for (unsigned int j = 0; j < m_height; j++)
+  {
+    int jj = m_offset + j*(N + m_pad);
+
+    for (unsigned int i = 0; i < m_width; i++)
+    {
+      int ii = m_offset + i*(M + m_pad);
+
+      double srcR = (double)prgbSrc[j][i].Red;
+      double srcG = (double)prgbSrc[j][i].Green;
+      double srcB = (double)prgbSrc[j][i].Blue;
+
+      // Find BMU
+
+      double d2min = DBL_MAX;
+      int iiHit = ii;
+      int jjHit = jj;
+
+      for (int l = 0; l < N; l++)
+      {
+        for (int k = 0; k < M; k++)
+        {
+          double dr = srcR - m_ppSOM[jj + l][ii + k].Red;
+          double dg = srcG - m_ppSOM[jj + l][ii + k].Green;
+          double db = srcB - m_ppSOM[jj + l][ii + k].Blue;
+
+          double d2 = dr*dr + dg*dg + db*db;
+
+          if (d2 < d2min)
+          {
+            d2min = d2;
+            iiHit = ii + k;
+            jjHit = jj + l;
+          }
+        }
+      }
+
+      // Update SOM
+
+      if (d2min <= epsilon) // matching model found
+      {
+        for (int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++)
+        {
+          for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++)
+          {
+            a = alpha*m_ppW[l - jjHit + m_offset][k - iiHit + m_offset];
+
+            // speed hack.. avoid very small increment values. abs() is sloooow.
+
+            double d;
+
+            d = srcR - m_ppSOM[l][k].Red;
+            if (d*d > DBL_MIN)
+              m_ppSOM[l][k].Red += a*d;
+
+            d = srcG - m_ppSOM[l][k].Green;
+            if (d*d > DBL_MIN)
+              m_ppSOM[l][k].Green += a*d;
+
+            d = srcB - m_ppSOM[l][k].Blue;
+            if (d*d > DBL_MIN)
+              m_ppSOM[l][k].Blue += a*d;
+          }
+        }
+
+        // Set background image
+        prgbBG[j][i].Red = m_ppSOM[jjHit][iiHit].Red;
+        prgbBG[j][i].Green = m_ppSOM[jjHit][iiHit].Green;
+        prgbBG[j][i].Blue = m_ppSOM[jjHit][iiHit].Blue;
+
+        // Set foreground image
+        prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 0;
+      }
+      else
+      {
+        // Set foreground image
+        prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 255;
+      }
+    }
+  }
+
+  return;
+}
diff --git a/src/algorithms/lb/BGModelSom.h b/src/algorithms/lb/BGModelSom.h
new file mode 100644
index 0000000000000000000000000000000000000000..9774fcab2d2c3a46c0cb2edd8d7a66b50144767c
--- /dev/null
+++ b/src/algorithms/lb/BGModelSom.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "BGModel.h"
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      namespace BGModelSomParams {
+        const int M = 3;         // width SOM (per pixel)
+        const int N = 3;         // height SOM (per pixel)
+        const int KERNEL = 3;    // size Gaussian kernel
+        const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels			//
+        const int TRAINING_STEPS = 100;    // number of training steps
+        const float EPS1 = 100.0; // model match distance during training
+        const float EPS2 = 20.0;  // model match distance
+        const float C1 = 1.0;     // learning rate during training
+        const float C2 = 0.05f;   // learning rate
+      }
+
+      class BGModelSom : public BGModel
+      {
+      public:
+        BGModelSom(int width, int height);
+        ~BGModelSom();
+
+        void setBGModelParameter(int id, int value);
+
+      protected:
+        int m_widthSOM;
+        int m_heightSOM;
+        int m_offset;
+        int m_pad;
+        int m_K;
+        int m_TSteps;
+
+        double m_Wmax;
+
+        double m_epsilon1;
+        double m_epsilon2;
+        double m_alpha1;
+        double m_alpha2;
+
+        DBLRGB** m_ppSOM;					// SOM grid
+        double** m_ppW;						// Weights
+
+        void Init();
+        void Update();
+      };
+    }
+  }
+}
diff --git a/src/algorithms/lb/Types.h b/src/algorithms/lb/Types.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ec3a9855e77be7d1b41ba81fdad3c2a651ca09c
--- /dev/null
+++ b/src/algorithms/lb/Types.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <opencv2/opencv.hpp>
+// opencv legacy includes
+#include <opencv2/core/core_c.h>
+
+namespace bgslibrary
+{
+  namespace algorithms
+  {
+    namespace lb
+    {
+      template<class T> class Image
+      {
+      private:
+        IplImage* imgp;
+
+      public:
+        Image(IplImage* img=0) {imgp=img;}
+        ~Image(){imgp=0;}
+        
+        void operator=(IplImage* img) {imgp=img;}
+        
+        inline T* operator[](const int rowIndx)
+        {
+          return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));
+        }
+      };
+
+      typedef struct{
+        unsigned char b,g,r;
+      } RgbPixel;
+
+      typedef struct{
+        unsigned char Blue,Green,Red;
+      } BYTERGB;
+
+      typedef struct{
+        unsigned int Blue,Green,Red;
+      } INTRGB;
+
+      typedef struct{
+        float b,g,r;
+      }RgbPixelFloat;
+
+      typedef struct{
+        double Blue,Green,Red;
+      } DBLRGB;
+
+      typedef Image<RgbPixel>       RgbImage;
+      typedef Image<RgbPixelFloat>  RgbImageFloat;
+      typedef Image<unsigned char>  BwImage;
+      typedef Image<float>          BwImageFloat;
+
+      /*
+        IplImage* img = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 3);
+        RgbImageFloat imgA(img);
+        for(int i = 0; i < m_height; i++)
+          for(int j = 0; j < m_width; j++)
+            imgA[i][j].b = 111;
+            imgA[i][j].g = 111;
+            imgA[i][j].r = 111;
+        */
+    }
+  }
+}
diff --git a/src/tools/ForegroundMaskAnalysis.cpp b/src/tools/ForegroundMaskAnalysis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..75231a773f9553e6f6d613ab5038ad79d1d73601
--- /dev/null
+++ b/src/tools/ForegroundMaskAnalysis.cpp
@@ -0,0 +1,68 @@
+#include "ForegroundMaskAnalysis.h"
+
+using namespace bgslibrary::tools;
+
+ForegroundMaskAnalysis::ForegroundMaskAnalysis() :
+  firstTime(true), showOutput(true),
+  stopAt(0), img_ref_path("")
+{
+  debug_construction(ForegroundMaskAnalysis);
+  initLoadSaveConfig(quote(ForegroundMaskAnalysis));
+}
+
+ForegroundMaskAnalysis::~ForegroundMaskAnalysis() {
+  debug_destruction(ForegroundMaskAnalysis);
+}
+
+void ForegroundMaskAnalysis::process(const long &frameNumber, const std::string &name, const cv::Mat &img_input)
+{
+  if (img_input.empty())
+    return;
+
+  if (stopAt == frameNumber && img_ref_path.empty() == false)
+  {
+    cv::Mat img_ref = cv::imread(img_ref_path, 0);
+
+    if (showOutput)
+      cv::imshow("ForegroundMaskAnalysis", img_ref);
+
+    int rn = cv::countNonZero(img_ref);
+    cv::Mat i;
+    cv::Mat u;
+
+    if (rn > 0) {
+      i = img_input & img_ref;
+      u = img_input | img_ref;
+    }
+    else {
+      i = (~img_input) & (~img_ref);
+      u = (~img_input) | (~img_ref);
+    }
+
+    int in = cv::countNonZero(i);
+    int un = cv::countNonZero(u);
+
+    double s = (((double)in) / ((double)un));
+
+    if (showOutput) {
+      cv::imshow("A^B", i);
+      cv::imshow("AvB", u);
+    }
+
+    std::cout << name << " - Similarity Measure: " << s << " press ENTER to continue" << std::endl;
+
+    cv::waitKey(0);
+  }
+
+  firstTime = false;
+}
+
+void ForegroundMaskAnalysis::save_config(cv::FileStorage &fs) {
+  fs << "stopAt" << stopAt;
+  fs << "img_ref_path" << img_ref_path;
+}
+
+void ForegroundMaskAnalysis::load_config(cv::FileStorage &fs) {
+  fs["stopAt"] >> stopAt;
+  fs["img_ref_path"] >> img_ref_path;
+}
diff --git a/src/tools/ForegroundMaskAnalysis.h b/src/tools/ForegroundMaskAnalysis.h
new file mode 100644
index 0000000000000000000000000000000000000000..60d6878c6a4eb351118d85c3ed4e1b1e69331631
--- /dev/null
+++ b/src/tools/ForegroundMaskAnalysis.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <iostream>
+#include <string>
+#include <opencv2/opencv.hpp>
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/features2d/features2d.hpp>
+// opencv legacy includes
+#include <opencv2/imgproc/types_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+#include <opencv2/highgui/highgui_c.h>
+
+#include "../utils/ILoadSaveConfig.h"
+
+namespace bgslibrary
+{
+  namespace tools
+  {
+    class ForegroundMaskAnalysis: public ILoadSaveConfig
+    {
+    private:
+      bool firstTime;
+      bool showOutput;
+
+    public:
+      ForegroundMaskAnalysis();
+      ~ForegroundMaskAnalysis();
+
+      int stopAt;
+      std::string img_ref_path;
+
+      void process(const long &frameNumber, const std::string &name, const cv::Mat &img_input);
+
+    private:
+      void save_config(cv::FileStorage &fs);
+      void load_config(cv::FileStorage &fs);
+    };
+  }
+}
diff --git a/package_bgs/T2F/FuzzyUtils.cpp b/src/tools/FuzzyUtils.cpp
similarity index 95%
rename from package_bgs/T2F/FuzzyUtils.cpp
rename to src/tools/FuzzyUtils.cpp
index a151136e6eb946138bb411ef9bf9d6088e8d789c..7fc37e4f587d39bc6c687f87762c1a10d7fa053e 100644
--- a/package_bgs/T2F/FuzzyUtils.cpp
+++ b/src/tools/FuzzyUtils.cpp
@@ -1,24 +1,10 @@
-/*
-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 "FuzzyUtils.h"
 
-FuzzyUtils::FuzzyUtils(void) {}
+using namespace bgslibrary::tools;
 
-FuzzyUtils::~FuzzyUtils(void) {}
+FuzzyUtils::FuzzyUtils() {}
+
+FuzzyUtils::~FuzzyUtils() {}
 
 void FuzzyUtils::LBP(IplImage* InputImage, IplImage* LBPimage)
 {
diff --git a/src/tools/FuzzyUtils.h b/src/tools/FuzzyUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b5b993afe1a04823d67f294a91fcba033b47fd9
--- /dev/null
+++ b/src/tools/FuzzyUtils.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "PixelUtils.h"
+
+namespace bgslibrary
+{
+  namespace tools
+  {
+    class FuzzyUtils
+    {
+    public:
+      FuzzyUtils(void);
+      ~FuzzyUtils(void);
+
+      void LBP(IplImage* InputImage, IplImage* LBP);
+      void getBinValue(float* neighberGrayPixel, float* BinaryValue, int m, int n);
+
+      void SimilarityDegreesImage(IplImage* CurrentImage, IplImage* BGImage, IplImage* DeltaImage, int n, int color_space);
+      void RatioPixels(float* CurrentPixel, float* BGPixel, float* DeltaPixel, int n);
+
+      void getFuzzyIntegralSugeno(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage);
+      void getFuzzyIntegralChoquet(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage);
+      void FuzzyMeasureG(float g1, float g2, float g3, float *G);
+      void Trier(float* g, int n, int* index);
+      float min(float *a, float *b);
+      float max(float *g, int n);
+      void gDeDeux(float* a, float* b, float* lambda);
+      void getLambda(float* g);
+
+      void AdaptativeSelectiveBackgroundModelUpdate(IplImage* CurrentImage, IplImage* BGImage, IplImage* OutputImage, IplImage* Integral, float seuil, float alpha);
+    };
+  }
+}
diff --git a/package_analysis/PerformanceUtils.cpp b/src/tools/PerformanceUtils.cpp
similarity index 79%
rename from package_analysis/PerformanceUtils.cpp
rename to src/tools/PerformanceUtils.cpp
index 6ad5e5faa64d7b746eba212fd2df8313dcb64365..c81702a7e7ed343dd3ee526913b451c812838446 100644
--- a/package_analysis/PerformanceUtils.cpp
+++ b/src/tools/PerformanceUtils.cpp
@@ -1,29 +1,16 @@
-/*
-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 "PerformanceUtils.h"
-//#include <opencv2/legacy/compat.hpp>
-//#include <opencv2/highgui/highgui_c.h>
 
-PerformanceUtils::PerformanceUtils(void) {}
+using namespace bgslibrary::tools;
 
-PerformanceUtils::~PerformanceUtils(void) {}
+PerformanceUtils::PerformanceUtils() {
+  //debug_construction(PerformanceUtils);
+}
 
-float PerformanceUtils::NrPixels(IplImage *image)
-{
+PerformanceUtils::~PerformanceUtils() {
+  //debug_destruction(PerformanceUtils);
+}
+
+float PerformanceUtils::NrPixels(IplImage *image) {
   return (float)(image->width * image->height);
 }
 
@@ -37,13 +24,10 @@ float PerformanceUtils::NrAllDetectedPixNotNULL(IplImage *image, IplImage *groun
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
-
       if ((pixelGT[0] != 0) || (pixelI[0] != 0))
         Union12++;
     }
@@ -64,33 +48,27 @@ float PerformanceUtils::NrTruePositives(IplImage *image, IplImage *ground_truth,
 
   IplImage *TPimage = 0;
 
-  if (debug)
-  {
+  if (debug) {
     TPimage = cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels);
     cvSetZero(TPimage);
   }
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
 
-      if ((pixelGT[0] != 0) && (pixelI[0] != 0))
-      {
+      if ((pixelGT[0] != 0) && (pixelI[0] != 0)) {
         if (debug)
           p.PutGrayPixel(TPimage, x, y, *pixelI);
-
         nTP++;
       }
     }
   }
 
-  if (debug)
-  {
+  if (debug) {
     cvNamedWindow("TPImage", 0);
     cvShowImage("TPImage", TPimage);
     //std::cout << "True Positives: " << nTP << std::endl;
@@ -114,35 +92,28 @@ float PerformanceUtils::NrTrueNegatives(IplImage* image, IplImage* ground_truth,
 
   IplImage *TNimage = 0;
 
-  if (debug)
-  {
+  if (debug) {
     TNimage = cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels);
     cvSetZero(TNimage);
   }
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
 
-      if ((pixelGT[0] == 0) && (pixelI[0] == 0.0))
-      {
+      if ((pixelGT[0] == 0) && (pixelI[0] == 0.0)) {
         *pixelI = 255;
-
         if (debug)
           p.PutGrayPixel(TNimage, x, y, *pixelI);
-
         nTN++;
       }
     }
   }
 
-  if (debug)
-  {
+  if (debug) {
     cvNamedWindow("TNImage", 0);
     cvShowImage("TNImage", TNimage);
     //std::cout << "True Negatives: " << nTN << std::endl;
@@ -166,33 +137,27 @@ float PerformanceUtils::NrFalsePositives(IplImage *image, IplImage *ground_truth
 
   IplImage *FPimage = 0;
 
-  if (debug)
-  {
+  if (debug) {
     FPimage = cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels);
     cvSetZero(FPimage);
   }
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
 
-      if ((pixelGT[0] == 0) && (pixelI[0] != 0))
-      {
+      if ((pixelGT[0] == 0) && (pixelI[0] != 0)) {
         if (debug)
           p.PutGrayPixel(FPimage, x, y, *pixelI);
-
         nFP++;
       }
     }
   }
 
-  if (debug)
-  {
+  if (debug) {
     cvNamedWindow("FPImage", 0);
     cvShowImage("FPImage", FPimage);
     //std::cout << "False Positives: " << nFP << std::endl;
@@ -216,33 +181,27 @@ float PerformanceUtils::NrFalseNegatives(IplImage * image, IplImage *ground_trut
 
   IplImage *FNimage = 0;
 
-  if (debug)
-  {
+  if (debug) {
     FNimage = cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels);
     cvSetZero(FNimage);
   }
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
 
-      if ((pixelGT[0] != 0) && (pixelI[0] == 0))
-      {
+      if ((pixelGT[0] != 0) && (pixelI[0] == 0)) {
         if (debug)
           p.PutGrayPixel(FNimage, x, y, *pixelGT);
-
         nFN++;
       }
     }
   }
 
-  if (debug)
-  {
+  if (debug) {
     cvNamedWindow("FNImage", 0);
     cvShowImage("FNImage", FNimage);
     //std::cout << "False Negatives: " << nFN << std::endl;
@@ -266,13 +225,11 @@ float PerformanceUtils::SimilarityMeasure(IplImage *image, IplImage *ground_trut
   cv::Mat i;
   cv::Mat u;
 
-  if (rn > 0)
-  {
+  if (rn > 0) {
     i = img_input & img_ref;
     u = img_input | img_ref;
   }
-  else
-  {
+  else {
     i = (~img_input) & (~img_ref);
     u = (~img_input) | (~img_ref);
   }
@@ -282,8 +239,7 @@ float PerformanceUtils::SimilarityMeasure(IplImage *image, IplImage *ground_trut
 
   double s = (((double)in) / ((double)un));
 
-  if (debug)
-  {
+  if (debug) {
     cv::imshow("A^B", i);
     cv::imshow("AvB", u);
 
@@ -306,33 +262,27 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa
 
   PixelUtils p;
 
-  for (int y = 0; y < image->height; y++)
-  {
-    for (int x = 0; x < image->width; x++)
-    {
+  for (int y = 0; y < image->height; y++) {
+    for (int x = 0; x < image->width; x++) {
       p.GetGrayPixel(ground_truth, x, y, pixelGT);
       p.GetGrayPixel(image, x, y, pixelI);
 
-      if ((pixelGT[0] != 0) && (pixelI[0] != 0)) // TP
-      {
+      if ((pixelGT[0] != 0) && (pixelI[0] != 0)) { // TP
         *pixelI = 30;
         p.PutGrayPixel(ROCimage, x, y, *pixelI);
       }
 
-      if ((pixelGT[0] == 0) && (pixelI[0] == 0.0)) // TN
-      {
+      if ((pixelGT[0] == 0) && (pixelI[0] == 0.0)) { // TN
         *pixelI = 0;
         p.PutGrayPixel(ROCimage, x, y, *pixelI);
       }
 
-      if ((pixelGT[0] == 0) && (pixelI[0] != 0)) // FP
-      {
+      if ((pixelGT[0] == 0) && (pixelI[0] != 0)) { // FP
         *pixelI = 255;
         p.PutGrayPixel(ROCimage, x, y, *pixelI);
       }
 
-      if ((pixelGT[0] != 0) && (pixelI[0] == 0)) // FN
-      {
+      if ((pixelGT[0] != 0) && (pixelI[0] == 0)) { // FN
         *pixelI = 100;
         p.PutGrayPixel(ROCimage, x, y, *pixelI);
       }
@@ -342,8 +292,7 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa
   cvNamedWindow("ROC image", 0);
   cvShowImage("ROC image", ROCimage);
 
-  if (saveResults)
-  {
+  if (saveResults) {
     unsigned char *pixelOI = (unsigned char*)malloc(1 * sizeof(unsigned char));
     unsigned char *pixelROC = (unsigned char*)malloc(1 * sizeof(unsigned char));
 
@@ -361,38 +310,31 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa
       for (int j = 0; j < 6; j++)
         freq[i][j] = 0.0;
 
-    for (int y = 0; y < image->height; y++)
-    {
-      for (int x = 0; x < image->width; x++)
-      {
-        for (int i = 0; i < 256; i++)
-        {
+    for (int y = 0; y < image->height; y++) {
+      for (int x = 0; x < image->width; x++) {
+        for (int i = 0; i < 256; i++) {
           p.GetGrayPixel(image, x, y, pixelOI);
           p.GetGrayPixel(ROCimage, x, y, pixelROC);
 
-          if ((pixelOI[0] == i) && (pixelROC[0] == 30.0)) // TP
-          {
+          if ((pixelOI[0] == i) && (pixelROC[0] == 30.0)) { // TP
             nTP++;
             freq[i][0] = nTP;
             break;
           }
 
-          if ((pixelOI[0] == i) && (pixelROC[0] == 0.0)) // TN
-          {
+          if ((pixelOI[0] == i) && (pixelROC[0] == 0.0)) { // TN
             nTN++;
             freq[i][1] = nTN;
             break;
           }
 
-          if ((pixelOI[0] == i) && (pixelROC[0] == 255.0)) // FP
-          {
+          if ((pixelOI[0] == i) && (pixelROC[0] == 255.0)) { // FP
             nFP++;
             freq[i][2] = nFP;
             break;
           }
 
-          if ((pixelOI[0] == i) && (pixelROC[0] == 100)) // FN
-          {
+          if ((pixelOI[0] == i) && (pixelROC[0] == 100)) { // FN
             nFN++;
             freq[i][3] = nFN;
             break;
@@ -412,16 +354,13 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa
 
     if (!f.is_open())
       std::cout << "Failed to open file " << filename << " for writing!" << std::endl;
-    else
-    {
+    else {
       f << "  I     TP     TN     FP     FN    FPR      FNR      DR   \n" << std::endl;
 
-      for (int i = 0; i < 256; i++)
-      {
+      for (int i = 0; i < 256; i++) {
         //printf("%4d - TP:%5.0f, TN:%5.0f, FP:%5.0f, FN:%5.0f,", i, freq[i][0], freq[i][1], freq[i][2], freq[i][3]);
 
-        if ((freq[i][3] + freq[i][0] != 0.0) && (freq[i][2] + freq[i][1] != 0.0))
-        {
+        if ((freq[i][3] + freq[i][0] != 0.0) && (freq[i][2] + freq[i][1] != 0.0)) {
           freq[i][4] = freq[i][3] / (freq[i][3] + freq[i][0]);  // FNR = FN / (TP + FN);
           freq[i][5] = freq[i][2] / (freq[i][2] + freq[i][1]);	// FPR = FP / (FP + TN);
           freq[i][6] = freq[i][0] / (freq[i][0] + freq[i][3]);	// DR = TP / (TP+FN);
@@ -507,14 +446,12 @@ void PerformanceUtils::PerformanceEvaluation(IplImage *image, IplImage *ground_t
   std::string results = sstm.str();
   std::cout << results;
 
-  if (saveResults)
-  {
+  if (saveResults) {
     std::ofstream f(filename);
 
     if (!f.is_open())
       std::cout << "Failed to open file " << filename << " for writing!" << std::endl;
-    else
-    {
+    else {
       f << results;
       std::cout << "Results saved in " << filename << std::endl;
       f.close();
diff --git a/src/tools/PerformanceUtils.h b/src/tools/PerformanceUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0d69c5ed2fcfc099f2c182e4e046bcc752208ce
--- /dev/null
+++ b/src/tools/PerformanceUtils.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <stdio.h>
+#include <fstream>
+#include <opencv2/opencv.hpp>
+
+#include "PixelUtils.h"
+
+namespace bgslibrary
+{
+  namespace tools
+  {
+    class PerformanceUtils
+    {
+    public:
+      PerformanceUtils();
+      ~PerformanceUtils();
+
+      float NrPixels(IplImage *image);
+      float NrAllDetectedPixNotNULL(IplImage *image, IplImage *ground_truth);
+      float NrTruePositives(IplImage *image, IplImage *ground_truth, bool debug = false);
+      float NrTrueNegatives(IplImage *image, IplImage *ground_truth, bool debug = false);
+      float NrFalsePositives(IplImage *image, IplImage *ground_truth, bool debug = false);
+      float NrFalseNegatives(IplImage *image, IplImage *ground_truth, bool debug = false);
+      float SimilarityMeasure(IplImage *image, IplImage *ground_truth, bool debug = false);
+
+      void ImageROC(IplImage *image, IplImage* ground_truth, bool saveResults = false, std::string filename = "");
+      void PerformanceEvaluation(IplImage *image, IplImage *ground_truth, bool saveResults = false, std::string filename = "", bool debug = false);
+    };
+  }
+}
diff --git a/package_analysis/PixelUtils.cpp b/src/tools/PixelUtils.cpp
similarity index 92%
rename from package_analysis/PixelUtils.cpp
rename to src/tools/PixelUtils.cpp
index adce122f642ec9260254921999f6954bce28dc03..2ca5a6c500a661b6e0553732ed21ee09a8c3d877 100644
--- a/package_analysis/PixelUtils.cpp
+++ b/src/tools/PixelUtils.cpp
@@ -1,23 +1,13 @@
-/*
-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 "PixelUtils.h"
 
-PixelUtils::PixelUtils(void) {}
-PixelUtils::~PixelUtils(void) {}
+using namespace bgslibrary::tools;
+
+PixelUtils::PixelUtils() {
+  //debug_construction(PixelUtils);
+}
+PixelUtils::~PixelUtils() {
+  //debug_destruction(PixelUtils);
+}
 
 void PixelUtils::ColorConversion(IplImage* RGBImage, IplImage* ConvertedImage, int color_space)
 {
diff --git a/src/tools/PixelUtils.h b/src/tools/PixelUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..1522562de236c3bcbf2060aea1b81fcf4c09a2d7
--- /dev/null
+++ b/src/tools/PixelUtils.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <stdio.h>
+#include <opencv2/opencv.hpp>
+// opencv legacy includes
+//#include <opencv2/legacy/compat.hpp>
+//#include <opencv2/highgui/highgui_c.h>
+#include <opencv2/imgproc/types_c.h>
+#include <opencv2/imgproc/imgproc_c.h>
+#ifndef MEX_COMPILE_FLAG
+#include <opencv2/highgui/highgui_c.h>
+#endif
+
+namespace bgslibrary
+{
+  namespace tools
+  {
+    class PixelUtils
+    {
+    public:
+      PixelUtils();
+      ~PixelUtils();
+
+      void ColorConversion(IplImage* RGBImage, IplImage* ConvertedImage, int color_space);
+      void cvttoOTHA(IplImage* RGBImage, IplImage* OthaImage);
+
+      void PostProcessing(IplImage *InputImage);
+
+      void GetPixel(IplImage *image, int m, int n, unsigned char *pixelcourant);
+      void GetGrayPixel(IplImage *image, int m, int n, unsigned char *pixelcourant);
+
+      void PutPixel(IplImage *image, int p, int q, unsigned char *pixelcourant);
+      void PutGrayPixel(IplImage *image, int p, int q, unsigned char pixelcourant);
+
+      void GetPixel(IplImage *image, int m, int n, float *pixelcourant);
+      void GetGrayPixel(IplImage *image, int m, int n, float *pixelcourant);
+
+      void PutPixel(IplImage *image, int p, int q, float *pixelcourant);
+      void PutGrayPixel(IplImage *image, int p, int q, float pixelcourant);
+
+      void getNeighberhoodGrayPixel(IplImage* InputImage, int x, int y, float* neighberPixel);
+      void ForegroundMaximum(IplImage *Foreground, float *Maximum, int n);
+      void ForegroundMinimum(IplImage *Foreground, float *Minimum, int n);
+      void ComplementaryAlphaImageCreation(IplImage *AlphaImage, IplImage *ComplementaryAlphaImage, int n);
+    };
+  }
+}
diff --git a/src/utils/GenericKeys.h b/src/utils/GenericKeys.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5b1b048772269b2106f84dbed7cdee167e3f82e
--- /dev/null
+++ b/src/utils/GenericKeys.h
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace bgslibrary
+{
+  const int KEY_REPEAT = 'r';
+  const int KEY_SPACE = 32;
+  const int KEY_ESC = 27;
+  const int KEY_ESC2 = 'q';
+}
diff --git a/src/utils/GenericMacros.h b/src/utils/GenericMacros.h
new file mode 100755
index 0000000000000000000000000000000000000000..025bf72a45d4e08129888c599c3e0e3fc191ac5d
--- /dev/null
+++ b/src/utils/GenericMacros.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <iostream>
+
+#define DEBUG_OBJ_LIFE
+
+#if !defined(quote)
+#define quote(x) #x
+#endif
+
+#if !defined(debug_construction)
+#if defined(DEBUG_OBJ_LIFE)
+#define debug_construction(x) std::cout << "+" << quote(x) << "()" << std::endl
+#else
+#define debug_construction(x)
+#endif
+#endif
+
+#if !defined(debug_destruction)
+#if defined(DEBUG_OBJ_LIFE)
+#define debug_destruction(x) std::cout << "-" << quote(x) << "()" << std::endl
+#else
+#define debug_destruction(x)
+#endif
+#endif
diff --git a/src/utils/ILoadSaveConfig.h b/src/utils/ILoadSaveConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d2261a1c263f3e452700789f4ca5bc55e2ab8e4
--- /dev/null
+++ b/src/utils/ILoadSaveConfig.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "GenericMacros.h"
+
+namespace bgslibrary
+{
+  const std::string DEFAULT_CONFIG_BASE_PATH = "./config";
+  const std::string DEFAULT_CONFIG_EXTENSION = ".xml";
+  
+  class ILoadSaveConfig
+  {
+  public:
+    ILoadSaveConfig() :
+    config_base_path(DEFAULT_CONFIG_BASE_PATH),
+    config_extension(DEFAULT_CONFIG_EXTENSION),
+    config_file_path("")
+    {
+      //debug_construction(ILoadSaveConfig);
+    }
+    virtual ~ILoadSaveConfig() {
+      //debug_destruction(ILoadSaveConfig);
+    }
+
+  protected:
+    std::string config_base_path;
+    std::string config_extension;
+    std::string config_file_path;
+    //static const std::string config_base_path;
+    //static const std::string config_extension;
+    virtual void save_config(cv::FileStorage &fs) = 0;
+    virtual void load_config(cv::FileStorage &fs) = 0;
+    void initLoadSaveConfig(const std::string _config_file_name) {
+      if(!_config_file_name.empty()) {
+        config_file_path = config_base_path + "/" + _config_file_name + config_extension;
+        if (!std::ifstream(config_file_path))
+          _save_config();
+        _load_config();
+      }
+    }
+    
+  private:
+    void _save_config() {
+      //std::cout << "_save_config: " << config_file_path << std::endl;
+      cv::FileStorage fs(config_file_path, cv::FileStorage::WRITE);
+      if (_is_valid(fs))
+        save_config(fs);
+      fs.release();
+    }
+    void _load_config() {
+      //std::cout << "_load_config: " << config_file_path << std::endl;
+      cv::FileStorage fs;
+      fs.open(config_file_path, cv::FileStorage::READ);
+      if (_is_valid(fs))
+        load_config(fs);
+      fs.release();
+    }
+    bool _is_valid(cv::FileStorage &fs) {
+      if (!fs.isOpened()) {
+        std::cerr << "Failed to open " << config_file_path << std::endl;
+        //std::cerr << "Please check if the path above is valid" << std::endl;
+        return false;
+      }
+      return true;
+    }
+  };
+  //const std::string ILoadSaveConfig::config_base_path = "./config";
+  //const std::string ILoadSaveConfig::config_extension = ".xml";
+}
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/fet/FG/1.png b/tools/fet/FG/1.png
similarity index 100%
rename from fet/FG/1.png
rename to tools/fet/FG/1.png
diff --git a/fet/FG/10.png b/tools/fet/FG/10.png
similarity index 100%
rename from fet/FG/10.png
rename to tools/fet/FG/10.png
diff --git a/fet/FG/11.png b/tools/fet/FG/11.png
similarity index 100%
rename from fet/FG/11.png
rename to tools/fet/FG/11.png
diff --git a/fet/FG/12.png b/tools/fet/FG/12.png
similarity index 100%
rename from fet/FG/12.png
rename to tools/fet/FG/12.png
diff --git a/fet/FG/13.png b/tools/fet/FG/13.png
similarity index 100%
rename from fet/FG/13.png
rename to tools/fet/FG/13.png
diff --git a/fet/FG/14.png b/tools/fet/FG/14.png
similarity index 100%
rename from fet/FG/14.png
rename to tools/fet/FG/14.png
diff --git a/fet/FG/15.png b/tools/fet/FG/15.png
similarity index 100%
rename from fet/FG/15.png
rename to tools/fet/FG/15.png
diff --git a/fet/FG/16.png b/tools/fet/FG/16.png
similarity index 100%
rename from fet/FG/16.png
rename to tools/fet/FG/16.png
diff --git a/fet/FG/17.png b/tools/fet/FG/17.png
similarity index 100%
rename from fet/FG/17.png
rename to tools/fet/FG/17.png
diff --git a/fet/FG/18.png b/tools/fet/FG/18.png
similarity index 100%
rename from fet/FG/18.png
rename to tools/fet/FG/18.png
diff --git a/fet/FG/19.png b/tools/fet/FG/19.png
similarity index 100%
rename from fet/FG/19.png
rename to tools/fet/FG/19.png
diff --git a/fet/FG/2.png b/tools/fet/FG/2.png
similarity index 100%
rename from fet/FG/2.png
rename to tools/fet/FG/2.png
diff --git a/fet/FG/20.png b/tools/fet/FG/20.png
similarity index 100%
rename from fet/FG/20.png
rename to tools/fet/FG/20.png
diff --git a/fet/FG/21.png b/tools/fet/FG/21.png
similarity index 100%
rename from fet/FG/21.png
rename to tools/fet/FG/21.png
diff --git a/fet/FG/22.png b/tools/fet/FG/22.png
similarity index 100%
rename from fet/FG/22.png
rename to tools/fet/FG/22.png
diff --git a/fet/FG/23.png b/tools/fet/FG/23.png
similarity index 100%
rename from fet/FG/23.png
rename to tools/fet/FG/23.png
diff --git a/fet/FG/24.png b/tools/fet/FG/24.png
similarity index 100%
rename from fet/FG/24.png
rename to tools/fet/FG/24.png
diff --git a/fet/FG/25.png b/tools/fet/FG/25.png
similarity index 100%
rename from fet/FG/25.png
rename to tools/fet/FG/25.png
diff --git a/fet/FG/26.png b/tools/fet/FG/26.png
similarity index 100%
rename from fet/FG/26.png
rename to tools/fet/FG/26.png
diff --git a/fet/FG/27.png b/tools/fet/FG/27.png
similarity index 100%
rename from fet/FG/27.png
rename to tools/fet/FG/27.png
diff --git a/fet/FG/28.png b/tools/fet/FG/28.png
similarity index 100%
rename from fet/FG/28.png
rename to tools/fet/FG/28.png
diff --git a/fet/FG/29.png b/tools/fet/FG/29.png
similarity index 100%
rename from fet/FG/29.png
rename to tools/fet/FG/29.png
diff --git a/fet/FG/3.png b/tools/fet/FG/3.png
similarity index 100%
rename from fet/FG/3.png
rename to tools/fet/FG/3.png
diff --git a/fet/FG/30.png b/tools/fet/FG/30.png
similarity index 100%
rename from fet/FG/30.png
rename to tools/fet/FG/30.png
diff --git a/fet/FG/31.png b/tools/fet/FG/31.png
similarity index 100%
rename from fet/FG/31.png
rename to tools/fet/FG/31.png
diff --git a/fet/FG/4.png b/tools/fet/FG/4.png
similarity index 100%
rename from fet/FG/4.png
rename to tools/fet/FG/4.png
diff --git a/fet/FG/5.png b/tools/fet/FG/5.png
similarity index 100%
rename from fet/FG/5.png
rename to tools/fet/FG/5.png
diff --git a/fet/FG/6.png b/tools/fet/FG/6.png
similarity index 100%
rename from fet/FG/6.png
rename to tools/fet/FG/6.png
diff --git a/fet/FG/7.png b/tools/fet/FG/7.png
similarity index 100%
rename from fet/FG/7.png
rename to tools/fet/FG/7.png
diff --git a/fet/FG/8.png b/tools/fet/FG/8.png
similarity index 100%
rename from fet/FG/8.png
rename to tools/fet/FG/8.png
diff --git a/fet/FG/9.png b/tools/fet/FG/9.png
similarity index 100%
rename from fet/FG/9.png
rename to tools/fet/FG/9.png
diff --git a/fet/GT/1.png b/tools/fet/GT/1.png
similarity index 100%
rename from fet/GT/1.png
rename to tools/fet/GT/1.png
diff --git a/fet/GT/10.png b/tools/fet/GT/10.png
similarity index 100%
rename from fet/GT/10.png
rename to tools/fet/GT/10.png
diff --git a/fet/GT/11.png b/tools/fet/GT/11.png
similarity index 100%
rename from fet/GT/11.png
rename to tools/fet/GT/11.png
diff --git a/fet/GT/12.png b/tools/fet/GT/12.png
similarity index 100%
rename from fet/GT/12.png
rename to tools/fet/GT/12.png
diff --git a/fet/GT/13.png b/tools/fet/GT/13.png
similarity index 100%
rename from fet/GT/13.png
rename to tools/fet/GT/13.png
diff --git a/fet/GT/14.png b/tools/fet/GT/14.png
similarity index 100%
rename from fet/GT/14.png
rename to tools/fet/GT/14.png
diff --git a/fet/GT/15.png b/tools/fet/GT/15.png
similarity index 100%
rename from fet/GT/15.png
rename to tools/fet/GT/15.png
diff --git a/fet/GT/16.png b/tools/fet/GT/16.png
similarity index 100%
rename from fet/GT/16.png
rename to tools/fet/GT/16.png
diff --git a/fet/GT/17.png b/tools/fet/GT/17.png
similarity index 100%
rename from fet/GT/17.png
rename to tools/fet/GT/17.png
diff --git a/fet/GT/18.png b/tools/fet/GT/18.png
similarity index 100%
rename from fet/GT/18.png
rename to tools/fet/GT/18.png
diff --git a/fet/GT/19.png b/tools/fet/GT/19.png
similarity index 100%
rename from fet/GT/19.png
rename to tools/fet/GT/19.png
diff --git a/fet/GT/2.png b/tools/fet/GT/2.png
similarity index 100%
rename from fet/GT/2.png
rename to tools/fet/GT/2.png
diff --git a/fet/GT/20.png b/tools/fet/GT/20.png
similarity index 100%
rename from fet/GT/20.png
rename to tools/fet/GT/20.png
diff --git a/fet/GT/21.png b/tools/fet/GT/21.png
similarity index 100%
rename from fet/GT/21.png
rename to tools/fet/GT/21.png
diff --git a/fet/GT/22.png b/tools/fet/GT/22.png
similarity index 100%
rename from fet/GT/22.png
rename to tools/fet/GT/22.png
diff --git a/fet/GT/23.png b/tools/fet/GT/23.png
similarity index 100%
rename from fet/GT/23.png
rename to tools/fet/GT/23.png
diff --git a/fet/GT/24.png b/tools/fet/GT/24.png
similarity index 100%
rename from fet/GT/24.png
rename to tools/fet/GT/24.png
diff --git a/fet/GT/25.png b/tools/fet/GT/25.png
similarity index 100%
rename from fet/GT/25.png
rename to tools/fet/GT/25.png
diff --git a/fet/GT/26.png b/tools/fet/GT/26.png
similarity index 100%
rename from fet/GT/26.png
rename to tools/fet/GT/26.png
diff --git a/fet/GT/27.png b/tools/fet/GT/27.png
similarity index 100%
rename from fet/GT/27.png
rename to tools/fet/GT/27.png
diff --git a/fet/GT/28.png b/tools/fet/GT/28.png
similarity index 100%
rename from fet/GT/28.png
rename to tools/fet/GT/28.png
diff --git a/fet/GT/29.png b/tools/fet/GT/29.png
similarity index 100%
rename from fet/GT/29.png
rename to tools/fet/GT/29.png
diff --git a/fet/GT/3.png b/tools/fet/GT/3.png
similarity index 100%
rename from fet/GT/3.png
rename to tools/fet/GT/3.png
diff --git a/fet/GT/30.png b/tools/fet/GT/30.png
similarity index 100%
rename from fet/GT/30.png
rename to tools/fet/GT/30.png
diff --git a/fet/GT/31.png b/tools/fet/GT/31.png
similarity index 100%
rename from fet/GT/31.png
rename to tools/fet/GT/31.png
diff --git a/fet/GT/4.png b/tools/fet/GT/4.png
similarity index 100%
rename from fet/GT/4.png
rename to tools/fet/GT/4.png
diff --git a/fet/GT/5.png b/tools/fet/GT/5.png
similarity index 100%
rename from fet/GT/5.png
rename to tools/fet/GT/5.png
diff --git a/fet/GT/6.png b/tools/fet/GT/6.png
similarity index 100%
rename from fet/GT/6.png
rename to tools/fet/GT/6.png
diff --git a/fet/GT/7.png b/tools/fet/GT/7.png
similarity index 100%
rename from fet/GT/7.png
rename to tools/fet/GT/7.png
diff --git a/fet/GT/8.png b/tools/fet/GT/8.png
similarity index 100%
rename from fet/GT/8.png
rename to tools/fet/GT/8.png
diff --git a/fet/GT/9.png b/tools/fet/GT/9.png
similarity index 100%
rename from fet/GT/9.png
rename to tools/fet/GT/9.png
diff --git a/fet/README.txt b/tools/fet/README.txt
similarity index 100%
rename from fet/README.txt
rename to tools/fet/README.txt
diff --git a/fet/SC/1.png b/tools/fet/SC/1.png
similarity index 100%
rename from fet/SC/1.png
rename to tools/fet/SC/1.png
diff --git a/fet/SC/10.png b/tools/fet/SC/10.png
similarity index 100%
rename from fet/SC/10.png
rename to tools/fet/SC/10.png
diff --git a/fet/SC/11.png b/tools/fet/SC/11.png
similarity index 100%
rename from fet/SC/11.png
rename to tools/fet/SC/11.png
diff --git a/fet/SC/12.png b/tools/fet/SC/12.png
similarity index 100%
rename from fet/SC/12.png
rename to tools/fet/SC/12.png
diff --git a/fet/SC/13.png b/tools/fet/SC/13.png
similarity index 100%
rename from fet/SC/13.png
rename to tools/fet/SC/13.png
diff --git a/fet/SC/14.png b/tools/fet/SC/14.png
similarity index 100%
rename from fet/SC/14.png
rename to tools/fet/SC/14.png
diff --git a/fet/SC/15.png b/tools/fet/SC/15.png
similarity index 100%
rename from fet/SC/15.png
rename to tools/fet/SC/15.png
diff --git a/fet/SC/16.png b/tools/fet/SC/16.png
similarity index 100%
rename from fet/SC/16.png
rename to tools/fet/SC/16.png
diff --git a/fet/SC/17.png b/tools/fet/SC/17.png
similarity index 100%
rename from fet/SC/17.png
rename to tools/fet/SC/17.png
diff --git a/fet/SC/18.png b/tools/fet/SC/18.png
similarity index 100%
rename from fet/SC/18.png
rename to tools/fet/SC/18.png
diff --git a/fet/SC/19.png b/tools/fet/SC/19.png
similarity index 100%
rename from fet/SC/19.png
rename to tools/fet/SC/19.png
diff --git a/fet/SC/2.png b/tools/fet/SC/2.png
similarity index 100%
rename from fet/SC/2.png
rename to tools/fet/SC/2.png
diff --git a/fet/SC/20.png b/tools/fet/SC/20.png
similarity index 100%
rename from fet/SC/20.png
rename to tools/fet/SC/20.png
diff --git a/fet/SC/21.png b/tools/fet/SC/21.png
similarity index 100%
rename from fet/SC/21.png
rename to tools/fet/SC/21.png
diff --git a/fet/SC/22.png b/tools/fet/SC/22.png
similarity index 100%
rename from fet/SC/22.png
rename to tools/fet/SC/22.png
diff --git a/fet/SC/23.png b/tools/fet/SC/23.png
similarity index 100%
rename from fet/SC/23.png
rename to tools/fet/SC/23.png
diff --git a/fet/SC/24.png b/tools/fet/SC/24.png
similarity index 100%
rename from fet/SC/24.png
rename to tools/fet/SC/24.png
diff --git a/fet/SC/25.png b/tools/fet/SC/25.png
similarity index 100%
rename from fet/SC/25.png
rename to tools/fet/SC/25.png
diff --git a/fet/SC/26.png b/tools/fet/SC/26.png
similarity index 100%
rename from fet/SC/26.png
rename to tools/fet/SC/26.png
diff --git a/fet/SC/27.png b/tools/fet/SC/27.png
similarity index 100%
rename from fet/SC/27.png
rename to tools/fet/SC/27.png
diff --git a/fet/SC/28.png b/tools/fet/SC/28.png
similarity index 100%
rename from fet/SC/28.png
rename to tools/fet/SC/28.png
diff --git a/fet/SC/29.png b/tools/fet/SC/29.png
similarity index 100%
rename from fet/SC/29.png
rename to tools/fet/SC/29.png
diff --git a/fet/SC/3.png b/tools/fet/SC/3.png
similarity index 100%
rename from fet/SC/3.png
rename to tools/fet/SC/3.png
diff --git a/fet/SC/30.png b/tools/fet/SC/30.png
similarity index 100%
rename from fet/SC/30.png
rename to tools/fet/SC/30.png
diff --git a/fet/SC/31.png b/tools/fet/SC/31.png
similarity index 100%
rename from fet/SC/31.png
rename to tools/fet/SC/31.png
diff --git a/fet/SC/4.png b/tools/fet/SC/4.png
similarity index 100%
rename from fet/SC/4.png
rename to tools/fet/SC/4.png
diff --git a/fet/SC/5.png b/tools/fet/SC/5.png
similarity index 100%
rename from fet/SC/5.png
rename to tools/fet/SC/5.png
diff --git a/fet/SC/6.png b/tools/fet/SC/6.png
similarity index 100%
rename from fet/SC/6.png
rename to tools/fet/SC/6.png
diff --git a/fet/SC/7.png b/tools/fet/SC/7.png
similarity index 100%
rename from fet/SC/7.png
rename to tools/fet/SC/7.png
diff --git a/fet/SC/8.png b/tools/fet/SC/8.png
similarity index 100%
rename from fet/SC/8.png
rename to tools/fet/SC/8.png
diff --git a/fet/SC/9.png b/tools/fet/SC/9.png
similarity index 100%
rename from fet/SC/9.png
rename to tools/fet/SC/9.png
diff --git a/fet/fet.py b/tools/fet/fet.py
similarity index 50%
rename from fet/fet.py
rename to tools/fet/fet.py
index eeccc86762562f3c127cdcbe74773d30c8969b05..1f5602570f7b374f30141923c66d56349cec4f3c 100644
--- a/fet/fet.py
+++ b/tools/fet/fet.py
@@ -11,6 +11,10 @@ import os
 from os import listdir
 from os.path import isfile, join
 
+import sys
+if sys.version_info >= (3, 0):
+  from six.moves import xrange
+
 path_gt = 'GT/'
 path_fg = 'FG/'
 path_sc = 'SC/'
@@ -40,54 +44,54 @@ red   = [0,0,255] # for FP
 white = [255,255,255] # for TP
 black = [0,0,0] # for TN
 
-print 'Processing'
+print('Processing')
 k = 1
 for file_gt, file_fg in zip(files_gt, files_fg):
-    print(k, file_gt, file_fg)
-    img_gt = cv2.imread(path_gt + file_gt,cv2.IMREAD_GRAYSCALE)
-    img_fg = cv2.imread(path_fg + file_fg,cv2.IMREAD_GRAYSCALE)
-    # img_gt = cv2.resize(img_gt, (0,0), fx=0.5, fy=0.5) 
-    # print(img_gt.shape,img_fg.shape)
-    rows,cols = img_gt.shape
-    img_fg = cv2.resize(img_fg,(cols,rows)) 
-    img_res = np.zeros((rows,cols,3),np.uint8)
-    for i in xrange(rows):
-        for j in xrange(cols):
-            pixel_gt = img_gt[i,j]
-            pixel_fg = img_fg[i,j]        
-            if(pixel_gt == 255 and pixel_fg == 255):
-                TP = TP + 1
-                img_res[i,j] = white
-            if(pixel_gt == 0 and pixel_fg == 255):
-                FP = FP + 1
-                img_res[i,j] = red
-            if(pixel_gt == 0 and pixel_fg == 0):
-                TN = TN + 1
-                img_res[i,j] = black
-            if(pixel_gt == 255 and pixel_fg == 0):
-                FN = FN + 1
-                img_res[i,j] = green
-    cv2.imshow('GT',img_gt)
-    cv2.imshow('FG',img_fg)
-    cv2.imshow('SC',img_res)
-    cv2.imwrite(path_sc + file_gt, img_res)
-    cv2.waitKey(1) # 33
-    k = k + 1
-    #break
+  print(k, file_gt, file_fg)
+  img_gt = cv2.imread(path_gt + file_gt,cv2.IMREAD_GRAYSCALE)
+  img_fg = cv2.imread(path_fg + file_fg,cv2.IMREAD_GRAYSCALE)
+  # img_gt = cv2.resize(img_gt, (0,0), fx=0.5, fy=0.5) 
+  # print(img_gt.shape,img_fg.shape)
+  rows,cols = img_gt.shape
+  img_fg = cv2.resize(img_fg,(cols,rows)) 
+  img_res = np.zeros((rows,cols,3),np.uint8)
+  for i in xrange(rows):
+    for j in xrange(cols):
+      pixel_gt = img_gt[i,j]
+      pixel_fg = img_fg[i,j]        
+      if(pixel_gt == 255 and pixel_fg == 255):
+        TP = TP + 1
+        img_res[i,j] = white
+      if(pixel_gt == 0 and pixel_fg == 255):
+        FP = FP + 1
+        img_res[i,j] = red
+      if(pixel_gt == 0 and pixel_fg == 0):
+        TN = TN + 1
+        img_res[i,j] = black
+      if(pixel_gt == 255 and pixel_fg == 0):
+        FN = FN + 1
+        img_res[i,j] = green
+  cv2.imshow('GT',img_gt)
+  cv2.imshow('FG',img_fg)
+  cv2.imshow('SC',img_res)
+  cv2.imwrite(path_sc + file_gt, img_res)
+  cv2.waitKey(1) # 33
+  k = k + 1
+  #break
 cv2.destroyAllWindows()
 
 Recall = TP / (TP + FN)
 Precision = TP / (TP + FP)
 Fscore = 2*Precision*Recall/(Precision+Recall)
 
-print 'Score:'
-print 'TP: ', TP
-print 'FP: ', FP
-print 'TN: ', TN
-print 'FN: ', FN
-print 'Recall: ', Recall
-print 'Precision: ', Precision
-print 'Fscore: ', Fscore
-print ''
+print('Score:')
+print('TP: ', TP)
+print('FP: ', FP)
+print('TN: ', TN)
+print('FN: ', FN)
+print('Recall: ', Recall)
+print('Precision: ', Precision)
+print('Fscore: ', Fscore)
+print('')
 
 #####################################################################
diff --git a/wrapper/java/.gitignore b/wrapper/java/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ca2b249f97151067cbc6bf5addbc43f358775d34
--- /dev/null
+++ b/wrapper/java/.gitignore
@@ -0,0 +1,9 @@
+nbproject/
+build.xml
+build/
+dist/
+build_*/
+*.dll
+*.bat
+*.sh
+*.lib
diff --git a/wrapper/java/CMakeLists.txt b/wrapper/java/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fc044fa89c9151c03cdd314d58479ad018ee9d5e
--- /dev/null
+++ b/wrapper/java/CMakeLists.txt
@@ -0,0 +1,87 @@
+cmake_minimum_required(VERSION 2.8)
+project(libbgs_java_module)
+
+# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+if(UNIX)
+	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=gnu++0x")
+	set(CMAKE_MACOSX_RPATH 1)
+endif(UNIX)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+#set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules)
+
+# compilation mode setup
+set(CMAKE_BUILD_TYPE Release)
+#set(CMAKE_BUILD_TYPE Debug)
+
+if(WIN32)
+	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+endif(WIN32)
+
+set(bgs_out_dir ".")
+# First for the generic no-config case (e.g. with mingw)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${bgs_out_dir})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${bgs_out_dir})
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${bgs_out_dir})
+# Second, for multi-config builds (e.g. msvc)
+foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
+    string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
+    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${bgs_out_dir})
+endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
+
+if(UNIX)
+	# add some standard warnings
+	ADD_DEFINITIONS(-Wno-variadic-macros -Wno-long-long -Wall -Wextra -Winit-self -Woverloaded-virtual -Wsign-promo -Wno-unused-parameter -pedantic -Woverloaded-virtual -Wno-unknown-pragmas)
+
+	# -ansi does not compile with sjn module
+	#ADD_DEFINITIONS(-ansi)
+
+	# if you like to have warinings about conversions, e.g. double->int or double->float etc., or float compare
+	#ADD_DEFINITIONS(-Wconversion -Wfloat-equal)
+endif(UNIX)
+
+find_package(JNI REQUIRED)
+if (JNI_FOUND)
+    message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
+    message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
+endif()
+
+set(OpenCV_STATIC OFF)
+find_package(OpenCV REQUIRED)
+if (OpenCV_FOUND)
+  message(STATUS "OpenCV library status:")
+  message(STATUS "    version: ${OpenCV_VERSION}")
+  message(STATUS "    libraries: ${OpenCV_LIBS}")
+  message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
+endif()
+
+file(GLOB_RECURSE tools_src ../../src/tools/*.cpp ../../src/tools/*.c)
+file(GLOB_RECURSE tools_inc ../../src/tools/*.h ../../src/tools/*.hpp)
+file(GLOB_RECURSE utils_src ../../src/utils/*.cpp ../../src/utils/*.c)
+file(GLOB_RECURSE utils_inc ../../src/utils/*.h ../../src/utils/*.hpp)
+file(GLOB_RECURSE bgs_src ../../src/algorithms/*.cpp ../../src/algorithms/*.c)
+file(GLOB_RECURSE bgs_inc ../../src/algorithms/*.h ../../src/algorithms/*.hpp)
+
+include_directories(${CMAKE_SOURCE_DIR} ${JNI_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
+
+add_library(libbgs STATIC ${bgs_src} ${tools_src} ${utils_src})
+target_link_libraries(libbgs ${OpenCV_LIBS})
+set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc})
+if(WIN32)
+	# set_property(TARGET libbgs PROPERTY SUFFIX ".lib")
+else()
+	set_property(TARGET libbgs PROPERTY OUTPUT_NAME "bgs")
+endif()
+
+set(SOURCE_FILES bgslibrary_java_module.cpp)
+add_library(libbgs_java_module SHARED ${SOURCE_FILES})
+set_target_properties(libbgs_java_module PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(libbgs_java_module libbgs ${OpenCV_LIBS})
+if(WIN32)
+	# set_property(TARGET libbgs_java_module PROPERTY SUFFIX ".lib")
+else()
+	set_property(TARGET libbgs_java_module PROPERTY OUTPUT_NAME "bgs_java_module")
+endif()
diff --git a/wrapper/java/README.md b/wrapper/java/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cce69604ff9a0dfe080ed0e174a311bf85a01d80
--- /dev/null
+++ b/wrapper/java/README.md
@@ -0,0 +1,55 @@
+### For Windows users
+
+* Running CMAKE with Visual Studio 2015 and OpenCV 3.2.0 (x64)
+
+* * Working directory: **bgslibrary\wrapper\java**
+
+```
+:: Set OpenCV env
+echo "Setting up OpenCV env"
+set OpenCV_DIR=C:\OpenCV3.2.0\build
+set PATH=%PATH%;%OpenCV_DIR%\x64\vc14\bin
+
+:: Run CMake
+echo "Running CMake"
+rmdir /S /Q build_cmake
+if not exist "build_cmake" mkdir build_cmake
+cd build_cmake
+cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 14 Win64" ..
+cd ..
+```
+
+* Open **libbgs_java_module.sln** in your Visual Studio IDE and switch to **RELEASE** mode
+
+* Click on **ALL_BUILD** and build
+
+* Copy **libbgs_java_module.dll** to **bgslibrary\wrapper\java**
+
+* Compile Java source
+
+```
+:: Compile
+echo "Compiling"
+javac -cp .;src/;libs/opencv-320.jar src/bgslibrary/Main.java
+```
+
+* Run
+
+```
+:: Run
+echo "Running Main class"
+java -cp .;src/;libs/opencv-320.jar -Djava.library.path=. bgslibrary.Main
+```
+
+[![bgslibrary](https://sites.google.com/site/andrewssobral/bgslib_java_wrapper_screen.png)]()
+
+
+#### Generating JNI files (optional)
+
+```
+:: Generate JNI
+cd src
+echo "Generating JNI"
+javah -cp .;../libs/opencv-320.jar bgslibrary.Main
+cd ..
+```
diff --git a/wrapper/java/bgslibrary_java_module.cpp b/wrapper/java/bgslibrary_java_module.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7f2a579fe2e2e0ff811688c7da9ac4efb26d009
--- /dev/null
+++ b/wrapper/java/bgslibrary_java_module.cpp
@@ -0,0 +1,282 @@
+#include <iostream>
+#include <opencv2/opencv.hpp>
+
+#include "bgslibrary_java_module.hpp"
+
+static IBGS *ptrBGS = nullptr;
+static std::string algorithm = "";
+
+namespace bgslibrary
+{
+  IBGS* init_alg(std::string alg_name)
+  {
+    if (alg_name.compare("FrameDifference") == 0)
+      return (IBGS *)malloc(sizeof(FrameDifference));
+    if (alg_name.compare("StaticFrameDifference") == 0)
+      return (IBGS *)malloc(sizeof(StaticFrameDifference));
+    if (alg_name.compare("WeightedMovingMean") == 0)
+      return (IBGS *)malloc(sizeof(WeightedMovingMean));
+    if (alg_name.compare("WeightedMovingVariance") == 0)
+      return (IBGS *)malloc(sizeof(WeightedMovingVariance));
+#if CV_MAJOR_VERSION == 2
+    if (alg_name.compare("MixtureOfGaussianV1") == 0)
+      return (IBGS *)malloc(sizeof(MixtureOfGaussianV1)); // only for OpenCV 2.x
+#endif
+    if (alg_name.compare("MixtureOfGaussianV2") == 0)
+      return (IBGS *)malloc(sizeof(MixtureOfGaussianV2));
+    if (alg_name.compare("AdaptiveBackgroundLearning") == 0)
+      return (IBGS *)malloc(sizeof(AdaptiveBackgroundLearning));
+    if (alg_name.compare("AdaptiveSelectiveBackgroundLearning") == 0)
+      return (IBGS *)malloc(sizeof(AdaptiveSelectiveBackgroundLearning));
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    if (alg_name.compare("GMG") == 0)
+      return (IBGS *)malloc(sizeof(GMG)); // only for OpenCV >= 2.4.3
+#endif
+#if CV_MAJOR_VERSION >= 3
+    if (alg_name.compare("KNN") == 0)
+      return (IBGS *)malloc(sizeof(KNN)); // only for OpenCV 3.x
+#endif
+    if (alg_name.compare("DPAdaptiveMedian") == 0)
+      return (IBGS *)malloc(sizeof(DPAdaptiveMedian));
+    if (alg_name.compare("DPGrimsonGMM") == 0)
+      return (IBGS *)malloc(sizeof(DPGrimsonGMM));
+    if (alg_name.compare("DPZivkovicAGMM") == 0)
+      return (IBGS *)malloc(sizeof(DPZivkovicAGMM));
+    if (alg_name.compare("DPMean") == 0)
+      return (IBGS *)malloc(sizeof(DPMean));
+    if (alg_name.compare("DPWrenGA") == 0)
+      return (IBGS *)malloc(sizeof(DPWrenGA));
+    if (alg_name.compare("DPPratiMediod") == 0)
+      return (IBGS *)malloc(sizeof(DPPratiMediod));
+    if (alg_name.compare("DPEigenbackground") == 0)
+      return (IBGS *)malloc(sizeof(DPEigenbackground));
+    if (alg_name.compare("DPTexture") == 0)
+      return (IBGS *)malloc(sizeof(DPTexture));
+    if (alg_name.compare("T2FGMM_UM") == 0)
+      return (IBGS *)malloc(sizeof(T2FGMM_UM));
+    if (alg_name.compare("T2FGMM_UV") == 0)
+      return (IBGS *)malloc(sizeof(T2FGMM_UV));
+    if (alg_name.compare("T2FMRF_UM") == 0)
+      return (IBGS *)malloc(sizeof(T2FMRF_UM));
+    if (alg_name.compare("T2FMRF_UV") == 0)
+      return (IBGS *)malloc(sizeof(T2FMRF_UV));
+    if (alg_name.compare("FuzzySugenoIntegral") == 0)
+      return (IBGS *)malloc(sizeof(FuzzySugenoIntegral));
+    if (alg_name.compare("FuzzyChoquetIntegral") == 0)
+      return (IBGS *)malloc(sizeof(FuzzyChoquetIntegral));
+    if (alg_name.compare("LBSimpleGaussian") == 0)
+      return (IBGS *)malloc(sizeof(LBSimpleGaussian));
+    if (alg_name.compare("LBFuzzyGaussian") == 0)
+      return (IBGS *)malloc(sizeof(LBFuzzyGaussian));
+    if (alg_name.compare("LBMixtureOfGaussians") == 0)
+      return (IBGS *)malloc(sizeof(LBMixtureOfGaussians));
+    if (alg_name.compare("LBAdaptiveSOM") == 0)
+      return (IBGS *)malloc(sizeof(LBAdaptiveSOM));
+    if (alg_name.compare("LBFuzzyAdaptiveSOM") == 0)
+      return (IBGS *)malloc(sizeof(LBFuzzyAdaptiveSOM));
+    if (alg_name.compare("LBP_MRF") == 0)
+      return (IBGS *)malloc(sizeof(LBP_MRF));
+    if (alg_name.compare("MultiLayer") == 0)
+      return (IBGS *)malloc(sizeof(MultiLayer));
+    if (alg_name.compare("PixelBasedAdaptiveSegmenter") == 0)
+      return (IBGS *)malloc(sizeof(PixelBasedAdaptiveSegmenter));
+    if (alg_name.compare("VuMeter") == 0)
+      return (IBGS *)malloc(sizeof(VuMeter));
+    if (alg_name.compare("KDE") == 0)
+      return (IBGS *)malloc(sizeof(KDE));
+    if (alg_name.compare("IndependentMultimodal") == 0)
+      return (IBGS *)malloc(sizeof(IndependentMultimodal));
+    if (alg_name.compare("MultiCue") == 0)
+      return (IBGS *)malloc(sizeof(MultiCue));
+    if (alg_name.compare("SigmaDelta") == 0)
+      return (IBGS *)malloc(sizeof(SigmaDelta));
+    if (alg_name.compare("SuBSENSE") == 0)
+      return (IBGS *)malloc(sizeof(SuBSENSE));
+    if (alg_name.compare("LOBSTER") == 0)
+      return (IBGS *)malloc(sizeof(LOBSTER));
+    if (alg_name.compare("PAWCS") == 0)
+      return (IBGS *)malloc(sizeof(PAWCS));
+    if (alg_name.compare("TwoPoints") == 0)
+      return (IBGS *)malloc(sizeof(TwoPoints));
+    if (alg_name.compare("ViBe") == 0)
+      return (IBGS *)malloc(sizeof(ViBe));
+    if (alg_name.compare("CodeBook") == 0)
+      return (IBGS *)malloc(sizeof(CodeBook));
+    return NULL;
+  }
+
+  IBGS* get_alg(std::string alg_name)
+  {
+    if (alg_name.compare("FrameDifference") == 0)
+      return new (ptrBGS) FrameDifference();
+    if (alg_name.compare("StaticFrameDifference") == 0)
+      return new (ptrBGS) StaticFrameDifference();
+    if (alg_name.compare("WeightedMovingMean") == 0)
+      return new (ptrBGS) WeightedMovingMean();
+    if (alg_name.compare("WeightedMovingVariance") == 0)
+      return new (ptrBGS) WeightedMovingVariance();
+#if CV_MAJOR_VERSION == 2
+    if (alg_name.compare("MixtureOfGaussianV1") == 0)
+      return new (ptrBGS) MixtureOfGaussianV1(); // only for OpenCV 2.x
+#endif
+    if (alg_name.compare("MixtureOfGaussianV2") == 0)
+      return new (ptrBGS) MixtureOfGaussianV2();
+    if (alg_name.compare("AdaptiveBackgroundLearning") == 0)
+      return new (ptrBGS) AdaptiveBackgroundLearning();
+    if (alg_name.compare("AdaptiveSelectiveBackgroundLearning") == 0)
+      return new (ptrBGS) AdaptiveSelectiveBackgroundLearning();
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+    if (alg_name.compare("GMG") == 0)
+      return new (ptrBGS) GMG(); // only for OpenCV >= 2.4.3
+#endif
+#if CV_MAJOR_VERSION >= 3
+    if (alg_name.compare("KNN") == 0)
+      return new (ptrBGS) KNN(); // only on OpenCV 3.x
+#endif
+    if (alg_name.compare("DPAdaptiveMedian") == 0)
+      return new (ptrBGS) DPAdaptiveMedian();
+    if (alg_name.compare("DPGrimsonGMM") == 0)
+      return new (ptrBGS) DPGrimsonGMM();
+    if (alg_name.compare("DPZivkovicAGMM") == 0)
+      return new (ptrBGS) DPZivkovicAGMM();
+    if (alg_name.compare("DPMean") == 0)
+      return new (ptrBGS) DPMean();
+    if (alg_name.compare("DPWrenGA") == 0)
+      return new (ptrBGS) DPWrenGA();
+    if (alg_name.compare("DPPratiMediod") == 0)
+      return new (ptrBGS) DPPratiMediod();
+    if (alg_name.compare("DPEigenbackground") == 0)
+      return new (ptrBGS) DPEigenbackground();
+    if (alg_name.compare("DPTexture") == 0)
+      return new (ptrBGS) DPTexture();
+    if (alg_name.compare("T2FGMM_UM") == 0)
+      return new (ptrBGS) T2FGMM_UM();
+    if (alg_name.compare("T2FGMM_UV") == 0)
+      return new (ptrBGS) T2FGMM_UV();
+    if (alg_name.compare("T2FMRF_UM") == 0)
+      return new (ptrBGS) T2FMRF_UM();
+    if (alg_name.compare("T2FMRF_UV") == 0)
+      return new (ptrBGS) T2FMRF_UV();
+    if (alg_name.compare("FuzzySugenoIntegral") == 0)
+      return new (ptrBGS) FuzzySugenoIntegral();
+    if (alg_name.compare("FuzzyChoquetIntegral") == 0)
+      return new (ptrBGS) FuzzyChoquetIntegral();
+    if (alg_name.compare("LBSimpleGaussian") == 0)
+      return new (ptrBGS) LBSimpleGaussian();
+    if (alg_name.compare("LBFuzzyGaussian") == 0)
+      return new (ptrBGS) LBFuzzyGaussian();
+    if (alg_name.compare("LBMixtureOfGaussians") == 0)
+      return new (ptrBGS) LBMixtureOfGaussians();
+    if (alg_name.compare("LBAdaptiveSOM") == 0)
+      return new (ptrBGS) LBAdaptiveSOM();
+    if (alg_name.compare("LBFuzzyAdaptiveSOM") == 0)
+      return new (ptrBGS) LBFuzzyAdaptiveSOM();
+    if (alg_name.compare("LBP_MRF") == 0)
+      return new (ptrBGS) LBP_MRF();
+    if (alg_name.compare("MultiLayer") == 0)
+      return new (ptrBGS) MultiLayer();
+    if (alg_name.compare("PixelBasedAdaptiveSegmenter") == 0)
+      return new (ptrBGS) PixelBasedAdaptiveSegmenter();
+    if (alg_name.compare("VuMeter") == 0)
+      return new (ptrBGS) VuMeter();
+    if (alg_name.compare("KDE") == 0)
+      return new (ptrBGS) KDE();
+    if (alg_name.compare("IndependentMultimodal") == 0)
+      return new (ptrBGS) IndependentMultimodal();
+    if (alg_name.compare("MultiCue") == 0)
+      return new (ptrBGS) MultiCue();
+    if (alg_name.compare("SigmaDelta") == 0)
+      return new (ptrBGS) SigmaDelta();
+    if (alg_name.compare("SuBSENSE") == 0)
+      return new (ptrBGS) SuBSENSE();
+    if (alg_name.compare("LOBSTER") == 0)
+      return new (ptrBGS) LOBSTER();
+    if (alg_name.compare("PAWCS") == 0)
+      return new (ptrBGS) PAWCS();
+    if (alg_name.compare("TwoPoints") == 0)
+      return new (ptrBGS) TwoPoints();
+    if (alg_name.compare("ViBe") == 0)
+      return new (ptrBGS) ViBe();
+    if (alg_name.compare("CodeBook") == 0)
+      return new (ptrBGS) CodeBook();
+    return NULL;
+  }
+}
+
+bool constructObject(std::string algorithm)
+{
+  if (ptrBGS != nullptr) destroyObject();
+
+  ptrBGS = bgslibrary::init_alg(algorithm);
+  if (ptrBGS != nullptr)
+  {
+    ptrBGS = bgslibrary::get_alg(algorithm);
+    if (ptrBGS == nullptr)
+    {
+      std::cout << "Failed to construct an object on memory. Algorithm not initialized." << std::endl;
+      return false;
+    }
+    else
+    {
+      ptrBGS->setShowOutput(false);
+      return true;
+    }
+  }
+  else
+  {
+    std::cout << "Failed to allocate memory. Algorithm not found?" << std::endl;
+    return false;
+  }
+}
+
+void computeForegroundMask(const cv::Mat &img_input, cv::Mat &img_output)
+{
+  if (ptrBGS != nullptr)
+  {
+    cv::Mat fgmask, bgmodel;
+
+    ptrBGS->process(img_input, fgmask, bgmodel);
+
+    if (fgmask.empty())
+      fgmask = cv::Mat::zeros(img_input.size(), CV_8UC1);
+    if (bgmodel.empty())
+      bgmodel = cv::Mat::zeros(img_input.size(), CV_8UC3);
+
+    fgmask.copyTo(img_output);
+
+    fgmask.release();
+    bgmodel.release();
+  }
+  else
+    std::cout << "Algorithm not initialized." << std::endl;
+}
+
+void destroyObject()
+{
+  if (ptrBGS != nullptr)
+  {
+    // explicitly call destructor for "placement new"
+    ptrBGS->~IBGS();
+    free(ptrBGS);
+    ptrBGS = nullptr;
+  }
+}
+
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_constructObject(JNIEnv *env, jclass, jstring jstr)
+{
+  GetJStringContent(env, jstr, algorithm);
+  constructObject(algorithm);
+}
+
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_computeForegroundMask
+(JNIEnv *, jclass, jlong input_matPtr, jlong output_matPtr)
+{
+  cv::Mat& in_mat = *reinterpret_cast<cv::Mat*>(input_matPtr);
+  cv::Mat& fg_mat = *reinterpret_cast<cv::Mat*>(output_matPtr);
+  computeForegroundMask(in_mat, fg_mat);
+}
+
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_destroyObject(JNIEnv *, jclass)
+{
+  destroyObject();
+}
diff --git a/wrapper/java/bgslibrary_java_module.hpp b/wrapper/java/bgslibrary_java_module.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1044f28cd2caa3bc95c1100a2cf6fbdec221ba20
--- /dev/null
+++ b/wrapper/java/bgslibrary_java_module.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <string>
+
+#include "src/bgslibrary_BgsLib.h"
+#include "../../src/algorithms/algorithms.h"
+
+bool constructObject(std::string algorithm);
+void computeForegroundMask(const cv::Mat &img_input, cv::Mat &img_output);
+void destroyObject();
+
+template <typename T>
+std::string ToString(T val)
+{
+  std::stringstream stream;
+  stream << val;
+  return stream.str();
+}
+
+jstring StringToJString(JNIEnv * env, const std::string & nativeString)
+{
+  return env->NewStringUTF(nativeString.c_str());
+}
+
+void GetJStringContent(JNIEnv *AEnv, jstring AStr, std::string &ARes)
+{
+  if (!AStr)
+  {
+    ARes.clear();
+    return;
+  }
+
+  const auto *s = AEnv->GetStringUTFChars(AStr, nullptr);
+  ARes = s;
+  AEnv->ReleaseStringUTFChars(AStr, s);
+}
diff --git a/demos/linux_ubuntu/.gitignore b/wrapper/java/config/.gitignore
similarity index 54%
rename from demos/linux_ubuntu/.gitignore
rename to wrapper/java/config/.gitignore
index 46d4288c817cdfd5c83571222c2c43e4674d6c32..4e2a98bb114355ae964e78a929c12d44f75815de 100644
--- a/demos/linux_ubuntu/.gitignore
+++ b/wrapper/java/config/.gitignore
@@ -2,7 +2,3 @@
 *
 # Except these files
 !.gitignore
-!CMakeLists.txt
-!FrameDifferenceTest.cpp
-!README.txt
-!config/
diff --git a/wrapper/java/images/320x240.gif b/wrapper/java/images/320x240.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f88252131ad520f21e6771e62c43e8fbb77db631
Binary files /dev/null and b/wrapper/java/images/320x240.gif differ
diff --git a/wrapper/java/images/640x480.png b/wrapper/java/images/640x480.png
new file mode 100644
index 0000000000000000000000000000000000000000..90dd040b8bcffce6cf7ead7677572c5753d45c87
Binary files /dev/null and b/wrapper/java/images/640x480.png differ
diff --git a/wrapper/java/libs/README.md b/wrapper/java/libs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..15698e23e0903630038eb74b3f2d7841b503c6f3
--- /dev/null
+++ b/wrapper/java/libs/README.md
@@ -0,0 +1,3 @@
+### Windows version
+
+The 'opencv-320.jar' file was copied from 'C:\OpenCV3.2.0\build\java'.
diff --git a/wrapper/java/libs/opencv-320.jar b/wrapper/java/libs/opencv-320.jar
new file mode 100644
index 0000000000000000000000000000000000000000..9542446ca08d3ca26c6ba2a79c887414afbf145a
Binary files /dev/null and b/wrapper/java/libs/opencv-320.jar differ
diff --git a/wrapper/java/src/bgslibrary/.gitignore b/wrapper/java/src/bgslibrary/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6b468b62a9884e67ca19b673f8e14e1931d65036
--- /dev/null
+++ b/wrapper/java/src/bgslibrary/.gitignore
@@ -0,0 +1 @@
+*.class
diff --git a/wrapper/java/src/bgslibrary/BgsLib.java b/wrapper/java/src/bgslibrary/BgsLib.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc24e30a74dbfd12c3738e47f41e381dd892bf47
--- /dev/null
+++ b/wrapper/java/src/bgslibrary/BgsLib.java
@@ -0,0 +1,38 @@
+package bgslibrary;
+
+import org.opencv.core.Core;
+
+public class BgsLib
+{
+  static
+  {
+    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+    System.loadLibrary("libbgs_java_module");
+  }
+  
+  private static final String[] algorithms =
+    {
+      "FrameDifference", "StaticFrameDifference", "WeightedMovingMean", 
+      "WeightedMovingVariance", "MixtureOfGaussianV1", "MixtureOfGaussianV2", 
+      "AdaptiveBackgroundLearning", "AdaptiveSelectiveBackgroundLearning", 
+      "GMG", "KNN", "DPAdaptiveMedian", "DPGrimsonGMM", "DPZivkovicAGMM", 
+      "DPMean", "DPWrenGA", "DPPratiMediod", "DPEigenbackground", "DPTexture", 
+      "T2FGMM_UM", "T2FGMM_UV", "T2FMRF_UM", "T2FMRF_UV", "FuzzySugenoIntegral", 
+      "FuzzyChoquetIntegral", "LBSimpleGaussian", "LBFuzzyGaussian", 
+      "LBMixtureOfGaussians", "LBAdaptiveSOM", "LBFuzzyAdaptiveSOM", "LBP_MRF", 
+      "MultiLayer", "PixelBasedAdaptiveSegmenter", "VuMeter", "KDE", 
+      "IndependentMultimodal", "MultiCue", "SigmaDelta", "SuBSENSE", "LOBSTER", 
+      "PAWCS", "TwoPoints", "ViBe", "CodeBook"
+    };
+  
+  public static final String[] getListAlgorithms()
+  {
+    return algorithms;
+  }
+
+  public static native void constructObject(String str);
+
+  public static native void computeForegroundMask(long input_matPtr, long output_matPtr);
+
+  public static native void destroyObject();
+}
diff --git a/wrapper/java/src/bgslibrary/ImagePanel.java b/wrapper/java/src/bgslibrary/ImagePanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..d97d548cf4e5b6e38f0cc16578f2c16302d17d61
--- /dev/null
+++ b/wrapper/java/src/bgslibrary/ImagePanel.java
@@ -0,0 +1,44 @@
+package bgslibrary;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+class ImagePanel extends JPanel
+{
+  private Image img;
+
+  public ImagePanel(String img)
+  {
+    this(new ImageIcon(img).getImage());
+  }
+
+  public ImagePanel(Image img)
+  {
+    this.img = img;
+    Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
+    setPreferredSize(size);
+    setMinimumSize(size);
+    setMaximumSize(size);
+    setSize(size);
+    setLayout(null);
+    setBorder(BorderFactory.createLineBorder(Color.black));
+  }
+
+  public void updateImage(Image img)
+  {
+    this.img = img;
+    validate();
+    repaint();
+  }
+
+  @Override
+  public void paintComponent(Graphics g)
+  {
+    g.drawImage(img, 0, 0, null);
+  }
+}
diff --git a/wrapper/java/src/bgslibrary/Main.java b/wrapper/java/src/bgslibrary/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6131995a2542e507fb300a66f93323644d13767
--- /dev/null
+++ b/wrapper/java/src/bgslibrary/Main.java
@@ -0,0 +1,191 @@
+package bgslibrary;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.io.InputStream;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import org.opencv.core.Core;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.core.MatOfByte;
+import org.opencv.imgproc.Imgproc;
+import org.opencv.videoio.VideoCapture;
+
+public final class Main
+{
+  static
+  {
+    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+  }
+  
+  private static BgsLib bgslib;
+  
+  private JFrame window;
+  private JButton startButton, stopButton;
+  private ImagePanel image;
+  private JComboBox comboBox;
+  private String selectedAlgorithm;
+
+  public Main()
+  {
+    buildGUI();
+  }
+
+  private void buildGUI()
+  {
+    window = new JFrame("Camera Panel");
+
+    startButton = new JButton("Start");
+    stopButton = new JButton("Stop");
+
+    window.add(startButton, BorderLayout.WEST);
+    window.add(stopButton, BorderLayout.EAST);
+
+    //image = new ImagePanel(new ImageIcon("images/320x240.gif").getImage());
+    image = new ImagePanel(new ImageIcon("images/640x480.png").getImage());
+    window.add(image, BorderLayout.CENTER);
+
+    String[] options = {"* Select a background subtraction algorithm"};
+    options = Utils.generalConcatAll(options, bgslib.getListAlgorithms());
+    
+    comboBox = new JComboBox(options);
+    comboBox.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if(begin == true)
+        {
+          JOptionPane.showMessageDialog(null, "Stop capture first.", "Warning",
+          JOptionPane.WARNING_MESSAGE);
+          comboBox.setSelectedIndex(0);
+          selectedAlgorithm = null;
+          return;
+        }
+        
+        String item = comboBox.getSelectedItem().toString();
+        
+        if(item.startsWith("*"))
+          selectedAlgorithm = null;
+        else
+          selectedAlgorithm = item;
+        
+        //System.out.println("Selected algorithm: " + selectedAlgorithm);
+      }
+    });
+    window.add(comboBox, BorderLayout.SOUTH);
+
+    window.setSize(default_width + 130, default_height + 28);
+    window.setLocationRelativeTo(null);
+    window.setVisible(true);
+    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    window.setResizable(false);
+
+    startButton.addActionListener((ActionEvent e) ->
+    {
+      start();
+    });
+
+    stopButton.addActionListener((ActionEvent e) ->
+    {
+      stop();
+    });
+  }
+
+  private Boolean begin = false;
+  private VideoCapture video = null;
+  private CaptureThread thread = null;
+
+  private void start()
+  {
+    if (begin == false)
+    {
+      video = new VideoCapture(0);
+
+      if (video.isOpened())
+      {
+        if(selectedAlgorithm != null)
+          BgsLib.constructObject(selectedAlgorithm);
+        
+        thread = new CaptureThread();
+        thread.start();
+        begin = true;
+      }
+    }
+  }
+
+  private MatOfByte matOfByte = new MatOfByte();
+  private BufferedImage bufImage = null;
+  private InputStream in;
+  private final int default_width = 640;
+  private final int default_height = 480;
+  private Mat frameaux = new Mat();
+  private Mat frame = new Mat(default_height, default_width, CvType.CV_8UC3);
+  private Mat fgmask = new Mat();
+
+  class CaptureThread extends Thread
+  {
+    @Override
+    public void run()
+    {
+      if (video.isOpened())
+      {
+        while (begin == true)
+        {
+          video.retrieve(frameaux);
+          Imgproc.resize(frameaux, frame, frame.size());
+          
+          if(selectedAlgorithm != null)
+          {
+            BgsLib.computeForegroundMask(frame.getNativeObjAddr(), fgmask.getNativeObjAddr());
+            bufImage = Utils.toBufferedImage(fgmask);
+          }
+          else
+            bufImage = Utils.toBufferedImage(frame);
+          
+          image.updateImage(bufImage);
+
+          try
+          {
+            Thread.sleep(5);
+          }
+          catch (Exception ex)
+          {
+          }
+        }
+      }
+    }
+  }
+
+  private void stop()
+  {
+    begin = false;
+    try
+    {
+      Thread.sleep(500);
+    }
+    catch (Exception ex)
+    {
+    }
+    
+    if(video != null)
+    {
+      video.release();
+      video = null;
+    }
+    
+    BgsLib.destroyObject();
+  }
+
+  public static void main(String[] args)
+  {
+    new Main();
+  }
+}
diff --git a/wrapper/java/src/bgslibrary/Utils.java b/wrapper/java/src/bgslibrary/Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a321af77c36fb5ad2abe7c1d747f682f6f9f86e
--- /dev/null
+++ b/wrapper/java/src/bgslibrary/Utils.java
@@ -0,0 +1,86 @@
+package bgslibrary;
+
+import java.awt.FlowLayout;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.UUID;
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import org.opencv.core.Mat;
+import org.opencv.imgcodecs.Imgcodecs;
+
+public class Utils
+{
+  static final private SecureRandom random = new SecureRandom();
+
+  static final public String nextSessionId()
+  {
+    return new BigInteger(130, random).toString(32);
+  }
+
+  static final public String nextUUID()
+  {
+    return UUID.randomUUID().toString();
+  }
+
+  static final public BufferedImage toBufferedImage(Mat m)
+  {
+    int type = BufferedImage.TYPE_BYTE_GRAY;
+    if (m.channels() > 1)
+      type = BufferedImage.TYPE_3BYTE_BGR;
+    int bufferSize = m.channels() * m.cols() * m.rows();
+    byte[] b = new byte[bufferSize];
+    m.get(0, 0, b); // get all the pixels
+    BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
+    final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
+    System.arraycopy(b, 0, targetPixels, 0, b.length);
+    return image;
+  }
+
+  static final public void imshow(Mat image)
+  {
+    try
+    {
+      BufferedImage bufImage = toBufferedImage(image);
+      JFrame frame = new JFrame("Image");
+      frame.getContentPane().setLayout(new FlowLayout());
+      frame.getContentPane().add(new JLabel(new ImageIcon(bufImage)));
+      frame.pack();
+      frame.setSize(image.width() + 40, image.height() + 60);
+      frame.setLocationRelativeTo(null);
+      frame.setVisible(true);
+      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    }
+    catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  static final public void writeImage(Mat image, String fileName)
+  {
+    //System.out.println(String.format("Writing image at %s", fileName));
+    Imgcodecs.imwrite(fileName, image);
+  }
+
+  static final public String[] generalConcatAll(String[]... jobs)
+  {
+    int len = 0;
+    for (final String[] job : jobs)
+      len += job.length;
+
+    final String[] result = new String[len];
+
+    int currentPos = 0;
+    for (final String[] job : jobs)
+    {
+      System.arraycopy(job, 0, result, currentPos, job.length);
+      currentPos += job.length;
+    }
+
+    return result;
+  }
+}
diff --git a/wrapper/java/src/bgslibrary_BgsLib.h b/wrapper/java/src/bgslibrary_BgsLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..06ff9941a00c966877de52c4a59f60f5cdb66335
--- /dev/null
+++ b/wrapper/java/src/bgslibrary_BgsLib.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class bgslibrary_BgsLib */
+
+#ifndef _Included_bgslibrary_BgsLib
+#define _Included_bgslibrary_BgsLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     bgslibrary_BgsLib
+ * Method:    constructObject
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_constructObject
+  (JNIEnv *, jclass, jstring);
+
+/*
+ * Class:     bgslibrary_BgsLib
+ * Method:    computeForegroundMask
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_computeForegroundMask
+  (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class:     bgslibrary_BgsLib
+ * Method:    destroyObject
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_bgslibrary_BgsLib_destroyObject
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/wrapper/matlab/.gitignore b/wrapper/matlab/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fb0ba78a689016dda41d1665b04badbb53cd2e7e
--- /dev/null
+++ b/wrapper/matlab/.gitignore
@@ -0,0 +1,5 @@
+*.mex*
+*.asv
+*.exe
+*.dll
+*.lib
diff --git a/wrapper/matlab/README.txt b/wrapper/matlab/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7e03be06b1ffb9935e5a0d32b934c2c877cf58b5
--- /dev/null
+++ b/wrapper/matlab/README.txt
@@ -0,0 +1,31 @@
+---------------------------------------
+- BUILDING BGSLIBRARY MATLAB WRAPPER -
+---------------------------------------
+Tested on MATLAB R2015b and R2016b
+
+* Dependencies:
+* * Computer Vision System Toolbox OpenCV Interface
+https://fr.mathworks.com/matlabcentral/fileexchange/47953-computer-vision-system-toolbox-opencv-interface
+* * * It provides wrapper files for OpenCV 2.4.9
+
+* Compatible compilers:
+    Windows 32 bit: MS Visual Studio 2012
+    Windows 64 bit: MS Visual Studio 2012
+    Linux 64 bit: gcc-4.7.2 (g++)
+    Mac 64 bit: Xcode 6.2.0 (Clang++)
+
+* * Note: It works successfully with MS Visual Studio 2013
+
+* * For Xcode 7.3.1 and MATLAB R2015b please see:
+https://fr.mathworks.com/matlabcentral/answers/246507-why-can-t-mex-find-a-supported-compiler-in-matlab-r2015b-after-i-upgraded-to-xcode-7-0#answer_194526
+
+* First install [Computer Vision System Toolbox OpenCV Interface]
+* * Go to: bgslibrary/wrapper_matlab
+* * Double-click on [opencvinterface.mlpkginstall] inside your MATLAB.
+-- wait installation, it takes a few minutes ---
+
+* Run: compile.m
+
+* Run demo: demo.m
+
+* See [run_demo.m] for more info
diff --git a/wrapper/matlab/README_visionopencv.txt b/wrapper/matlab/README_visionopencv.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a802f6f2ad8824cd401c7892d8df07a314b9efbe
--- /dev/null
+++ b/wrapper/matlab/README_visionopencv.txt
@@ -0,0 +1,81 @@
+CONTENTS OF THIS FILE
+---------------------
+* Introduction
+* Requirements
+* Installation
+* Contents
+* Utility functions
+* How to compile OpenCV mex function
+* Example
+
+
+INTRODUCTION
+------------
+"Computer Vision System Toolbox OpenCV Interface" is used to create mex files 
+that link against OpenCV. The support package also contains graphics 
+processing unit (GPU) support. 
+
+REQUIREMENTS
+------------
+This package requires the following:
+* Computer Vision System Toolbox® Version R2016a installation
+* A compatible C++ compiler
+
+The mex function uses pre-built OpenCV libraries which are shipped with the 
+Computer Vision System Toolbox. Your compiler must be compatible with the 
+pre-built OpenCV libraries. The following is a list of compatible compilers:
+    Windows 32 bit: MS Visual Studio 2012
+    Windows 64 bit: MS Visual Studio 2012
+    Linux 64 bit: gcc-4.7.2 (g++)
+    Mac 64 bit: Xcode 6.2.0 (Clang++)
+
+INSTALLATION
+------------
+Use the support package installer which can be invoked using the  
+visionSupportPackages function.
+After the support package is installed, the location of the package can be 
+found by executing the following MATLAB command:
+>> fileparts(which('mexOpenCV.m'))
+
+CONTENTS
+--------
+In addition to the files and folders required by the support package installer, 
+the package contains the following folder:
+
+example: Six subfolders containing examples. Each subfolder contains source 
+	 file that calls the OpenCV function and the test script to test the 
+	 generated mex file.
+
+UTILITY FUNCTIONS
+-----------------
+The support package uses a set of utility functions to marshall data 
+between OpenCV and MATLAB. It supports only CPP-linkage. GPU support is 
+only available on glnxa64 and win64 platforms. The utility functions support 
+CUDA-enabled NVIDIA GPU with compute capability 2.0 or higher. 
+
+General purpose utility functions are available at:
+  (matlabroot)/extern/include/opencvmex.hpp
+Utility functions for GPU support are available at:
+  (matlabroot)/extern/include/opencvgpumex.hpp
+
+HOW TO COMPILE OPENCV MEX FUNCTION
+----------------------------------
+Follow these steps:
+1. Change your current working folder to the folder where the source file is located. 
+2. Call the mexOpenCV function with the source file. 
+>> mexOpenCV yourfile.cpp
+
+To get more information, type the following at the MATLAB command prompt:
+>> help mexOpenCV
+
+EXAMPLES
+--------
+There are three examples included in the package: 
+* Template Matching (includes regular and GPU versions)
+* Image registration using ORB detector and descriptor (includes regular, 
+  GPU and code-generation versions)
+* Foreground Detection
+
+To run them, follow the steps in the README.txt file located in the corresponding 
+sub-folders of the examples folder.
+
diff --git a/wrapper_matlab/backgroundSubtractor.m b/wrapper/matlab/backgroundSubtractor.m
similarity index 74%
rename from wrapper_matlab/backgroundSubtractor.m
rename to wrapper/matlab/backgroundSubtractor.m
index e4317664f7d8580f8ce4740dc4b6c51b8835b268..859d796b6067f7546e926ca93f49892aa8665f6a 100644
--- a/wrapper_matlab/backgroundSubtractor.m
+++ b/wrapper/matlab/backgroundSubtractor.m
@@ -1,21 +1,3 @@
-%{
-/*
- * 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/>.
- */
-%}
 classdef backgroundSubtractor
   %backgroundSubtractor Wrapper class for BGSLibrary
   %   obj = backgroundSubtractor(algorithm)
diff --git a/wrapper_matlab/backgroundSubtractor_wrapper.cpp b/wrapper/matlab/backgroundSubtractor_wrapper.cpp
similarity index 94%
rename from wrapper_matlab/backgroundSubtractor_wrapper.cpp
rename to wrapper/matlab/backgroundSubtractor_wrapper.cpp
index 547012070adb5a3318282452faa650bf5aa3f6a7..ac956a43257c2a5087a46dce251e6cfed3d5a67b 100644
--- a/wrapper_matlab/backgroundSubtractor_wrapper.cpp
+++ b/wrapper/matlab/backgroundSubtractor_wrapper.cpp
@@ -1,23 +1,5 @@
-/*
- * 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 "opencvmex.hpp"
- // On some platforms, the following include is needed for "placement new".
- // For more information see: http://en.wikipedia.org/wiki/Placement_syntax
+
 #include <memory>
 
 #include <typeinfo>
@@ -66,6 +48,7 @@
 #include "PAWCS.h"
 #include "TwoPoints.h"
 #include "ViBe.h"
+#include "CodeBook.h"
 
 using namespace bgslibrary::algorithms;
 
@@ -97,7 +80,7 @@ namespace bgslibrary
     if (alg_name.compare("GMG") == 0)
       return (IBGS *)mxCalloc(1, sizeof(GMG)); // only for OpenCV >= 2.4.3
 #endif
-#if CV_MAJOR_VERSION == 3
+#if CV_MAJOR_VERSION >= 3
     if (alg_name.compare("KNN") == 0)
       return (IBGS *)mxCalloc(1, sizeof(KNN)); // only for OpenCV 3.x
 #endif
@@ -165,6 +148,8 @@ namespace bgslibrary
       return (IBGS *)mxCalloc(1, sizeof(TwoPoints));
     if (alg_name.compare("ViBe") == 0)
       return (IBGS *)mxCalloc(1, sizeof(ViBe));
+    if (alg_name.compare("CodeBook") == 0)
+      return (IBGS *)mxCalloc(1, sizeof(CodeBook));
     return NULL;
   }
 
@@ -192,7 +177,7 @@ namespace bgslibrary
     if (alg_name.compare("GMG") == 0)
       return new (ptrBGS) GMG(); // only for OpenCV >= 2.4.3
 #endif
-#if CV_MAJOR_VERSION == 3
+#if CV_MAJOR_VERSION >= 3
     if (alg_name.compare("KNN") == 0)
       return new (ptrBGS) KNN(); // only on OpenCV 3.x
 #endif
@@ -260,6 +245,8 @@ namespace bgslibrary
       return new (ptrBGS) TwoPoints();
     if (alg_name.compare("ViBe") == 0)
       return new (ptrBGS) ViBe();
+    if (alg_name.compare("CodeBook") == 0)
+      return new (ptrBGS) CodeBook();
     return NULL;
   }
 }
diff --git a/wrapper/matlab/compile.m b/wrapper/matlab/compile.m
new file mode 100644
index 0000000000000000000000000000000000000000..527db494e0bf0fcd8c15eaf23a619f5023d98e15
--- /dev/null
+++ b/wrapper/matlab/compile.m
@@ -0,0 +1,95 @@
+%% Compile
+clc;
+mexOpenCV -v -DMEX_COMPILE_FLAG -I"../../src/algorithms" backgroundSubtractor_wrapper.cpp ...
+  "../../src/algorithms/FrameDifference.cpp" ...
+  "../../src/algorithms/StaticFrameDifference.cpp" ...
+  "../../src/algorithms/WeightedMovingMean.cpp" ...
+  "../../src/algorithms/WeightedMovingVariance.cpp" ...
+  "../../src/algorithms/MixtureOfGaussianV1.cpp" ...
+  "../../src/algorithms/MixtureOfGaussianV2.cpp" ...
+  "../../src/algorithms/AdaptiveBackgroundLearning.cpp" ...
+  "../../src/algorithms/AdaptiveSelectiveBackgroundLearning.cpp" ...
+  "../../src/algorithms/GMG.cpp" ...
+  "../../src/algorithms/KNN.cpp" ...
+  "../../src/algorithms/DPAdaptiveMedian.cpp" ...
+  "../../src/algorithms/DPGrimsonGMM.cpp" ...
+  "../../src/algorithms/DPZivkovicAGMM.cpp" ...
+  "../../src/algorithms/DPMean.cpp" ...
+  "../../src/algorithms/DPWrenGA.cpp" ...
+  "../../src/algorithms/DPPratiMediod.cpp" ...
+  "../../src/algorithms/DPEigenbackground.cpp" ...
+  "../../src/algorithms/DPTexture.cpp" ...
+  "../../src/algorithms/dp/AdaptiveMedianBGS.cpp" ...
+  "../../src/algorithms/dp/Image.cpp" ...
+  "../../src/algorithms/dp/Error.cpp" ...
+  "../../src/algorithms/dp/GrimsonGMM.cpp" ...
+  "../../src/algorithms/dp/ZivkovicAGMM.cpp" ...
+  "../../src/algorithms/dp/MeanBGS.cpp" ...
+  "../../src/algorithms/dp/WrenGA.cpp"  ...
+  "../../src/algorithms/dp/PratiMediodBGS.cpp" ...
+  "../../src/algorithms/dp/Eigenbackground.cpp" ...
+  "../../src/algorithms/dp/TextureBGS.cpp" ...
+  "../../src/algorithms/T2FGMM_UM.cpp" ...
+  "../../src/algorithms/T2FGMM_UV.cpp" ...
+  "../../src/algorithms/T2FMRF_UM.cpp" ...
+  "../../src/algorithms/T2FMRF_UV.cpp" ...
+  "../../src/algorithms/FuzzyChoquetIntegral.cpp" ...
+  "../../src/algorithms/FuzzySugenoIntegral.cpp" ...
+  "../../src/algorithms/T2F/T2FGMM.cpp" ...
+  "../../src/algorithms/T2F/T2FMRF.cpp" ...
+  "../../src/algorithms/T2F/MRF.cpp" ...
+  "../../src/tools/FuzzyUtils.cpp" ...
+  "../../src/tools/PixelUtils.cpp" ...
+  "../../src/algorithms/MultiLayer.cpp" ...
+  "../../src/algorithms/MultiLayer/CMultiLayerBGS.cpp" ...
+  "../../src/algorithms/MultiLayer/LocalBinaryPattern.cpp" ...
+  "../../src/algorithms/MultiLayer/BlobResult.cpp" ...
+  "../../src/algorithms/MultiLayer/BlobExtraction.cpp" ...
+  "../../src/algorithms/MultiLayer/blob.cpp" ...
+  "../../src/algorithms/LBSimpleGaussian.cpp" ...
+  "../../src/algorithms/LBFuzzyGaussian.cpp" ...
+  "../../src/algorithms/LBMixtureOfGaussians.cpp" ...
+  "../../src/algorithms/LBAdaptiveSOM.cpp" ...
+  "../../src/algorithms/LBFuzzyAdaptiveSOM.cpp" ...
+  "../../src/algorithms/lb/BGModel.cpp" ...
+  "../../src/algorithms/lb/BGModelFuzzyGauss.cpp" ...
+  "../../src/algorithms/lb/BGModelFuzzySom.cpp" ...
+  "../../src/algorithms/lb/BGModelGauss.cpp" ...
+  "../../src/algorithms/lb/BGModelMog.cpp" ...
+  "../../src/algorithms/lb/BGModelSom.cpp" ...
+  "../../src/algorithms/LBP_MRF.cpp" ...
+  "../../src/algorithms/LBP_MRF/MotionDetection.cpp" ...
+  "../../src/algorithms/LBP_MRF/MEImage.cpp" ...
+  "../../src/algorithms/LBP_MRF/MEHistogram.cpp" ...
+  "../../src/algorithms/LBP_MRF/MEDefs.cpp" ...
+  "../../src/algorithms/LBP_MRF/maxflow.cpp" ...
+  "../../src/algorithms/LBP_MRF/graph.cpp" ...
+  "../../src/algorithms/PixelBasedAdaptiveSegmenter.cpp" ...
+  "../../src/algorithms/PBAS/PBAS.cpp" ...
+  "../../src/algorithms/VuMeter.cpp" ...
+  "../../src/algorithms/VuMeter/TBackgroundVuMeter.cpp" ...
+  "../../src/algorithms/VuMeter/TBackground.cpp" ...
+  "../../src/algorithms/KDE.cpp" ...
+  "../../src/algorithms/KDE/NPBGSubtractor.cpp" ...
+  "../../src/algorithms/KDE/NPBGmodel.cpp" ...
+  "../../src/algorithms/KDE/KernelTable.cpp" ...
+  "../../src/algorithms/IndependentMultimodal.cpp" ...
+  "../../src/algorithms/IMBS/IMBS.cpp" ...
+  "../../src/algorithms/MultiCue.cpp" ...
+  "../../src/algorithms/SigmaDelta.cpp" ...
+  "../../src/algorithms/SigmaDelta/sdLaMa091.cpp" ...
+  "../../src/algorithms/SuBSENSE.cpp" ...
+  "../../src/algorithms/LOBSTER.cpp" ...
+  "../../src/algorithms/PAWCS.cpp" ...
+  "../../src/algorithms/LBSP/LBSP.cpp" ...
+  "../../src/algorithms/LBSP/LBSP_.cpp" ...
+  "../../src/algorithms/LBSP/BackgroundSubtractorLBSP.cpp" ...
+  "../../src/algorithms/LBSP/BackgroundSubtractorLBSP_.cpp" ...
+  "../../src/algorithms/LBSP/BackgroundSubtractorLOBSTER.cpp" ...
+  "../../src/algorithms/LBSP/BackgroundSubtractorPAWCS.cpp" ...
+  "../../src/algorithms/LBSP/BackgroundSubtractorSuBSENSE.cpp" ...
+  "../../src/algorithms/ViBe.cpp" ...
+  "../../src/algorithms/ViBe/vibe-background-sequential.cpp" ...
+  "../../src/algorithms/TwoPoints.cpp" ...
+  "../../src/algorithms/TwoPoints/two_points.cpp" ...
+  "../../src/algorithms/CodeBook.cpp"
diff --git a/demos/macosx/.gitignore b/wrapper/matlab/config/.gitignore
similarity index 54%
rename from demos/macosx/.gitignore
rename to wrapper/matlab/config/.gitignore
index 46d4288c817cdfd5c83571222c2c43e4674d6c32..4e2a98bb114355ae964e78a929c12d44f75815de 100644
--- a/demos/macosx/.gitignore
+++ b/wrapper/matlab/config/.gitignore
@@ -2,7 +2,3 @@
 *
 # Except these files
 !.gitignore
-!CMakeLists.txt
-!FrameDifferenceTest.cpp
-!README.txt
-!config/
diff --git a/wrapper_matlab/demo.m b/wrapper/matlab/demo.m
similarity index 62%
rename from wrapper_matlab/demo.m
rename to wrapper/matlab/demo.m
index 942e457fb227cc4f11104f276f0a498d40eb0181..f40dc8a84f3f68020fe73cb61610939c72bcabfe 100644
--- a/wrapper_matlab/demo.m
+++ b/wrapper/matlab/demo.m
@@ -1,21 +1,3 @@
-%{
-/*
- * 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/>.
- */
-%}
 % Example:
 % demo('FrameDifference')
 % demo('StaticFrameDifference')
@@ -27,7 +9,7 @@ end
 
 % Create video reader object
 %filename = 'visiontraffic.avi';
-filename = '../dataset/demo.avi';
+filename = '../../dataset/demo.avi';
 hsrc = vision.VideoFileReader(filename, ...
                               'ImageColorSpace', 'RGB', ...
                               'VideoOutputDataType', 'uint8');
diff --git a/wrapper_matlab/mxarray.h b/wrapper/matlab/mxarray.h
similarity index 100%
rename from wrapper_matlab/mxarray.h
rename to wrapper/matlab/mxarray.h
diff --git a/wrapper_matlab/mxtypes.h b/wrapper/matlab/mxtypes.h
similarity index 100%
rename from wrapper_matlab/mxtypes.h
rename to wrapper/matlab/mxtypes.h
diff --git a/wrapper/matlab/opencvinterface.mlpkginstall b/wrapper/matlab/opencvinterface.mlpkginstall
new file mode 100644
index 0000000000000000000000000000000000000000..2d7683deb07d850c55a5a98d8cf2bf861bb3080e
--- /dev/null
+++ b/wrapper/matlab/opencvinterface.mlpkginstall
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+This file should be opened using MATLAB (http://www.mathworks.com).
+To open it with a specific instance of MATLAB, 
+ a) Open MATLAB,
+ b) Browse to this file using the Current Folder Browser, and
+ c) Double-click on this file
+
+Copyright 2014 The MathWorks, Inc.
+-->
+<MWSignpost>
+
+  <PackageInfo version="1.0">
+    <SignpostData>
+       <Repository>MathWorks</Repository>
+       <Name>OpenCV Interface</Name>
+       <BaseProduct>Computer Vision System Toolbox</BaseProduct>
+       <FullName>Computer Vision System Toolbox OpenCV Interface</FullName>
+       <BaseCode>CVST_OPENCV_INTERFACE</BaseCode>
+    </SignpostData>
+    <Signature>C0753A7DD7BC6A2500F8268502F7D019</Signature>
+  </PackageInfo>
+
+</MWSignpost>
+
+<!-- License for this .mlpkginstall file
+
+MATHWORKS LIMITED LICENSE
+
+IMPORTANT NOTICE
+
+READ THE TERMS AND CONDITIONS OF THIS MATHWORKS LIMITED LICENSE AGREEMENT
+(THE "AGREEMENT") CAREFULLY BEFORE ACCESSING THESE MATERIALS (AS DEFINED
+BELOW).
+
+THIS AGREEMENT REPRESENTS THE ENTIRE AGREEMENT BETWEEN YOU (THE "LICENSEE")
+AND THE MATHWORKS, INC. ("MATHWORKS") CONCERNING THE SOFTWARE AND
+DOCUMENTATION MADE AVAILABLE FOR ACCESS HEREUNDER (COLLECTIVELY, THE
+"MATERIALS").
+
+BY ACCESSING THESE MATERIALS, YOU ACCEPT THE TERMS OF THIS AGREEMENT.
+
+1. DEFINITIONS.
+
+  1.1. "Licensee" means you, whether an individual or an entity, to whom
+  MathWorks grants the License, and who is responsible for complying with the
+  contractual obligations of the License, and ensuring that anyone permitted
+  access to the Materials also complies with such obligations.
+
+  1.2. "Documentation" means the user guides, if any, accompanying delivery
+  of the Materials, as may be updated from time to time, as well as any
+  reports or other feedback that MathWorks may, in its sole discretion,
+  provide to Licensee.  Documentation may be delivered in printed and/or
+  online forms, and in one or more languages.
+
+  1.3. "Licensor" means any person who, or entity which, grants a license
+  to MathWorks to redistribute that person's or entity's intellectual
+  property.
+
+  1.4. "Materials" means the computer software delivered and licensed
+  hereunder, including Documentation, enhancements and error corrections.
+
+  1.5. "Third Party" means any person or legal entity that is not MathWorks
+  or the Licensee.
+
+2. LICENSE GRANT.  MathWorks hereby grants to Licensee, subject to the
+terms of this Agreement, a nonexclusive, nontransferable, revocable license
+(the "License") to use the Materials internally or for the purpose of
+providing to MathWorks engineering feedback on the Materials, as the context
+ may require.  In all cases, the Materials are licensed to you solely for
+ use in conjunction with MathWorks products and services.
+
+3. LICENSE RESTRICTIONS.  The License is subject to the express
+restrictions set forth below. Licensee shall not, and shall not permit any
+Third Party to:
+
+  3.1. modify, or create any derivative work of, any part of the licensed
+  Materials
+
+  3.2. adapt, translate, copy, or convert all or any part of the Materials
+  in order to create software or other materials, a principal purpose of
+  which is (a) to perform the same or similar functions as the Materials or
+  any other technology or materials licensed by MathWorks, or (b) to replace
+  any component of the Materials or any other technology or materials
+  licensed by MathWorks;
+
+  3.3. rent, lease, or loan the Materials; use the Materials for supporting
+   Third Parties' use of the Materials, time share the Materials, or provide
+   service bureau use;
+
+  3.4. disassemble, decompile, reverse engineer the Materials or otherwise
+  attempt to gain access to its method of operation or source code (other
+  than files provided for convenience in source code form by MathWorks);
+
+  3.5. sell, license, sublicense, publish, display, distribute, disseminate,
+  assign, or otherwise transfer (whether by sale, exchange, lease, gift, or
+  otherwise) to a Third Party the Materials, any copy or portion thereof, or
+  any License or other rights thereto, in whole or in part, without MathWorks'
+  prior written consent;
+
+  3.6. alter, remove, or obscure any copyright, trade secret, patent,
+  trademark, logo, proprietary and/or other legal notices on or in copies of
+  the Materials;
+
+  3.7. use MathWorks' name, trade names, logos, or other trademarks of
+  MathWorks or any of its affiliates or Licensors in any advertising,
+  promotional literature or any other material, whether in written,
+  electronic, or other form, distributed to any Third Party, except in the
+  form provided by MathWorks, and then solely for purposes of identifying
+  MathWorks' Materials;
+
+  3.8. provide access (directly or indirectly) to the Materials via a web or
+  network application other than the licensee's internal network;
+
+  3.9. copy, make available for copy, or otherwise reproduce the Materials,
+  in whole or in part, except either (a) as may be required for their
+  installation into computer memory for the purpose of executing the
+  Materials in accordance with this Agreement; or (b) to make a reasonable
+  number of copies solely for back-up purposes provided that any such
+  permitted copies shall reproduce all copyright, trade secret, patent, logo,
+  proprietary and/or other legal notices contained in the original copy
+  obtained from MathWorks; and/or
+
+  3.10. republish the Documentation.
+
+4. RETENTION OF RIGHT, TITLE AND INTEREST BY MATHWORKS AND ITS LICENSORS;
+CONFIDENTIALITY.  The Materials shall at all times remain the property of
+MathWorks and/or its Licensors and Licensee shall have no right, title, or
+interest therein, except as expressly set forth in this Agreement.  The
+Materials are a commercially valuable product of MathWorks, the design and
+development of which reflect the efforts of skilled development experts and
+the investment of considerable time and expense. MathWorks claims and
+reserves all rights and benefits afforded under all relevant laws and
+regulations. Licensee shall take appropriate action by instruction,
+agreement, or otherwise with any persons permitted access to the Materials,
+so as to enable Licensee to satisfy its obligations under the terms of this
+Agreement.  The Materials are proprietary information of MathWorks, and are
+protected by copyright law, trade secret law and other applicable law.
+Although MathWorks may consider a commercial release of the Materials, it
+is under no obligation to do so and MathWorks reserves the right to alter
+features, licensing terms, or other characteristics of any such commercial
+release.
+
+5. LICENSES FOR THIRD PARTY SOFTWARE.  MathWorks has been granted licenses
+to distribute certain Third Party software.  Certain MathWorks Materials
+require the use of Third Party software products that may require a
+separate license from such Third Parties to use those Third Party products.
+Licensee agrees and acknowledges that, to the extent that the Materials
+contain any Third Party software: (i) such Third Party software is provided
+on an "as-is", pass-through basis, and as such is provided to Licensee
+without warranty, indemnification, support or other representation by
+MathWorks; and (ii) MathWorks bears no liability with respect to such Third
+Party software.
+
+6. TERM AND TERMINATION.  This Agreement shall continue until termination
+by MathWorks or Licensee as provided below.  Either party may terminate this
+Agreement at any time, for any reason, upon written notice to the other
+party.  Upon termination, Licensee shall promptly return all but archival
+copies of the Materials in Licensee's possession or control, or promptly
+provide written certification of their destruction.
+
+7. EXPORT CONTROL.  The Materials may be subject to U.S. export control
+laws or other (U.S. and non-U.S.) governmental export and import laws and
+regulations.  Notwithstanding any other term of this Agreement or Third
+Party agreement, Licensee's rights under this Agreement may not be
+exercised by Licensee or any Third Party in violation of such laws and
+regulations, nor may this Agreement be transferred to any party where
+doing so would result in such a violation.  The terms of any limitation on
+the use, transfer or re-export of the Materials imposed by MathWorks in any
+Destination Control Statement or other document for the purpose of export
+control shall prevail over any term in this Agreement.  It shall be
+Licensee's responsibility to comply with the latest United States or other
+governmental export and import regulations.
+
+8. FEDERAL ACQUISITION.  This provision applies to all acquisitions of the
+Materials and Documentation by, for, or through the federal government of
+the United States.  By accepting delivery of the Materials or
+Documentation, the government hereby agrees that this software or
+documentation qualifies as commercial computer software or commercial
+computer software documentation as such terms are used or defined in FAR
+12.212, DFARS Part 227.72, and DFARS 252.227-7014.  Accordingly, the terms
+and conditions of this Agreement and only those rights specified in this
+Agreement, shall pertain to and govern the use, modification, reproduction,
+release, performance, display, and disclosure of the Materials and
+Documentation by the federal government (or other entity acquiring for or
+through the federal government) and shall supersede any conflicting
+contractual terms or conditions.  If this License fails to meet the
+government's needs or is inconsistent in any respect with federal
+procurement law, the government agrees to return the Materials and
+Documentation, unused, to MathWorks.
+
+9. FOR EUROPEAN UNION LICENSEES ONLY.  Any contractual provisions of this
+Agreement contrary to laws implemented under Article 6 of Appendix V of the
+European Union Software Directive or to the exceptions provided for in
+Article 5(2) and (3) of such Appendix shall be null and void solely to the
+extent decompiling, disassembling, or otherwise reverse-engineering of the
+Materials is necessary to enable the Licensee to create an independent
+program that is interoperable with the Materials or any other permitted
+objectives specified by such laws implemented under such directive
+(collectively, the "Permitted Objectives"), provided that any such
+information gained is used solely for such Permitted Objectives.
+
+10. ASSIGNMENT.  Licensee may not assign or otherwise transfer this
+Agreement and its rights and obligations hereunder, in whole or in part, by
+operation of law or otherwise, without the written consent of MathWorks.
+In the case of any permitted assignment or transfer of or under this
+Agreement, this Agreement or the relevant provisions shall be binding upon,
+and inure to the benefit of, the successors, executors, heirs,
+representatives, administrators and assigns of the parties hereto.
+MathWorks may charge Licensee an administrative fee for any permitted
+assignment.
+
+11. LIMITATION OF LIABILITY.  The Materials should not be relied on as the
+sole basis to solve a problem or implement a design whose incorrect solution
+or implementation could result in injury to person or property.  If the
+Materials are employed in such a manner, it is at the Licensee's own risk
+and MathWorks and its Licensors explicitly disclaim all liability for such
+misuse to the extent allowed by law.  MathWorks' and its Licensors'
+liability for death or personal injury resulting from negligence or for any
+other matter in relation to which liability by law cannot be excluded or
+limited shall not be excluded or limited.  Except as aforesaid, (a) any
+other liability of MathWorks and its Licensors (whether in relation to
+breach of contract, negligence or otherwise) shall not in total exceed one
+hundred dollars ($100.00); and (b) MathWorks and its Licensors shall have
+no liability for any indirect or consequential loss (whether foreseeable or
+otherwise and including loss of profits, loss of business, loss of
+opportunity, and loss of use of any computer hardware or software).  Some
+states do not allow the exclusion or limitation of incidental or
+consequential damages, so the above exclusion or limitation may not apply
+to Licensee.
+
+12. DISCLAIMER OF WARRANTIES.  The Materials are delivered "as is" and
+MathWorks makes and the Licensee receives no additional express or implied
+warranties.  MathWorks and its Licensors hereby expressly disclaim any and
+all other conditions, warranties, or other terms of any kind or nature
+concerning the Materials (including, without limitation, any with regard to
+infringement, merchantability, quality, accuracy, or fitness for a
+particular purpose or Licensee's purpose).  MathWorks also expressly
+disclaims any warranties that may be implied from usage of trade, course of
+dealing, or course of performance.  The Materials are provided with all
+faults, and the entire risk of satisfactory quality, performance, accuracy,
+and effort is with Licensee.  MathWorks does not warrant that the Materials
+will operate without interruption or be error free.  Some states and
+countries do not allow limitations on how long an implied warranty lasts,
+so the above limitation may not apply to Licensee.  Licensee may also have
+other rights which vary from state to state and country to country.
+Licensee accepts responsibility for its use of the Materials and the
+results obtained therefrom.
+
+13. GOVERNING LAW; JURISDICTION.  This Agreement shall be interpreted,
+enforced and construed and the rights of the parties hereunder governed in
+all respects by the laws of the Commonwealth of Massachusetts, United
+States of America, without regard to its conflicts of law provisions, and
+both parties consent to the jurisdiction of the federal and state courts
+located in said Commonwealth and consent to the service of process,
+pleadings and notices in connection with any and all actions initiated in
+such courts.  The parties agree that a final judgment in any such action or
+proceeding shall be conclusive and binding and may be enforced in any other
+jurisdiction.  To the extent any governing law, treaty, or regulation is in
+conflict with this Agreement, the conflicting terms of this Agreement shall
+be superseded only to the extent necessary by such law, treaty, or
+regulation.  If any provision of this Agreement shall be otherwise
+unlawful, void, or otherwise unenforceable, that provision shall be
+enforced to the maximum extent permissible.  In either case, the remainder
+of this Agreement shall not be affected.  The parties agree that the U.N.
+Convention on Contracts for the International Sale of Goods shall not apply
+to this Agreement.  The parties further agree that the Uniform Computer
+Information Transactions Act, or any version thereof, adopted by any state,
+in any form ("UCITA"), shall not apply to this Agreement.  To the extent
+that UCITA is applicable, the parties agree to opt out of the
+applicability of UCITA pursuant to the Opt-Out provision(s) contained
+therein.
+
+14. HEADINGS.  The inclusion of headings is for convenience of reference
+only and shall not affect the construction or interpretation of this
+Agreement.
+
+15. ENTIRE AGREEMENT.  This Agreement, together with any additional
+license_addendum.txt file included with the Materials, contains the entire
+understanding of the parties with regard to the Materials, and may not be
+modified or amended except by written instrument, executed by authorized
+representatives of MathWorks and Licensee.
+-->
diff --git a/wrapper_matlab/run_demo.m b/wrapper/matlab/run_demo.m
similarity index 68%
rename from wrapper_matlab/run_demo.m
rename to wrapper/matlab/run_demo.m
index e27174dfa82de5f47c9b8d68efeb5fb6ddcb3e16..72307dea9a0e23f8e5742baf2eead9a7626c264e 100644
--- a/wrapper_matlab/run_demo.m
+++ b/wrapper/matlab/run_demo.m
@@ -1,11 +1,21 @@
+%% Installation instructions
+% First install the 'Computer Vision System Toolbox OpenCV Interface'
+% by double-clicking on 'opencvinterface.mlpkginstall'
+%
+% More info:
+% https://fr.mathworks.com/help/vision/ug/opencv-interface.html
+% https://fr.mathworks.com/help/vision/opencv-interface-support-package.html
+% https://fr.mathworks.com/matlabcentral/fileexchange/47953-computer-vision-system-toolbox-opencv-interface
+
 %% Compile the BGSLibrary wrapper
-compile;
+% Run 'compile' for your first usage.
+% compile;
 
 %% Run demo
 demo;
 
 %% Run a specific algorithm
-demo('FrameDifference')
+% demo('FrameDifference')
 % demo('StaticFrameDifference')
 % demo('WeightedMovingMean')
 % demo('WeightedMovingVariance')
@@ -46,4 +56,5 @@ demo('FrameDifference')
 % demo('LOBSTER')
 % demo('PAWCS')
 % demo('TwoPoints')
-% demo('ViBe')
\ No newline at end of file
+% demo('ViBe')
+% demo('CodeBook')
\ No newline at end of file
diff --git a/wrapper/python/bgslibrary_module.cpp b/wrapper/python/bgslibrary_module.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6bc3757fc3f2284194c09dc0a6eb79236dda7b38
--- /dev/null
+++ b/wrapper/python/bgslibrary_module.cpp
@@ -0,0 +1,309 @@
+#include <pybind11/pybind11.h>
+#include <exception>
+
+#include <opencv2/opencv.hpp>
+
+#include "ndarray_converter.h"
+#include "../../src/algorithms/algorithms.h"
+
+#if CV_MAJOR_VERSION >= 4
+#define CV_LOAD_IMAGE_COLOR cv::IMREAD_COLOR
+#endif
+
+namespace py = pybind11;
+
+cv::Mat transpose_image(const cv::Mat& image)
+{
+  std::cerr << "Input size: " << image.size() << std::endl;
+  std::cerr << "Returning the image transpose" << std::endl;
+  return image.t();
+}
+
+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(pybgs, 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_<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_<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_<MixtureOfGaussianV2>(m, "MixtureOfGaussianV2")
+    .def(py::init<>())
+    .def("apply", &MixtureOfGaussianV2::apply)
+    .def("getBackgroundModel", &MixtureOfGaussianV2::getBackgroundModel)
+    ;
+
+#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3
+  py::class_<MixtureOfGaussianV1>(m, "MixtureOfGaussianV1")
+    .def(py::init<>())
+    .def("apply", &MixtureOfGaussianV1::apply)
+    .def("getBackgroundModel", &MixtureOfGaussianV1::getBackgroundModel)
+    ;
+#endif
+
+#if CV_MAJOR_VERSION == 2
+  py::class_<GMG>(m, "GMG")
+    .def(py::init<>())
+    .def("apply", &GMG::apply)
+    .def("getBackgroundModel", &GMG::getBackgroundModel)
+    ;
+#endif
+
+#if CV_MAJOR_VERSION >= 3
+  py::class_<KNN>(m, "KNN")
+    .def(py::init<>())
+    .def("apply", &KNN::apply)
+    .def("getBackgroundModel", &KNN::getBackgroundModel)
+    ;
+#endif
+
+#if CV_MAJOR_VERSION >= 2 && CV_MAJOR_VERSION <= 3
+  py::class_<DPAdaptiveMedian>(m, "DPAdaptiveMedian")
+    .def(py::init<>())
+    .def("apply", &DPAdaptiveMedian::apply)
+    .def("getBackgroundModel", &DPAdaptiveMedian::getBackgroundModel)
+    ;
+
+  py::class_<DPGrimsonGMM>(m, "DPGrimsonGMM")
+    .def(py::init<>())
+    .def("apply", &DPGrimsonGMM::apply)
+    .def("getBackgroundModel", &DPGrimsonGMM::getBackgroundModel)
+    ;
+
+  py::class_<DPZivkovicAGMM>(m, "DPZivkovicAGMM")
+    .def(py::init<>())
+    .def("apply", &DPZivkovicAGMM::apply)
+    .def("getBackgroundModel", &DPZivkovicAGMM::getBackgroundModel)
+    ;
+
+  py::class_<DPMean>(m, "DPMean")
+    .def(py::init<>())
+    .def("apply", &DPMean::apply)
+    .def("getBackgroundModel", &DPMean::getBackgroundModel)
+    ;
+
+  py::class_<DPWrenGA>(m, "DPWrenGA")
+    .def(py::init<>())
+    .def("apply", &DPWrenGA::apply)
+    .def("getBackgroundModel", &DPWrenGA::getBackgroundModel)
+    ;
+
+  py::class_<DPPratiMediod>(m, "DPPratiMediod")
+    .def(py::init<>())
+    .def("apply", &DPPratiMediod::apply)
+    .def("getBackgroundModel", &DPPratiMediod::getBackgroundModel)
+    ;
+
+  py::class_<DPEigenbackground>(m, "DPEigenbackground")
+    .def(py::init<>())
+    .def("apply", &DPEigenbackground::apply)
+    .def("getBackgroundModel", &DPEigenbackground::getBackgroundModel)
+    ;
+
+  py::class_<DPTexture>(m, "DPTexture")
+    .def(py::init<>())
+    .def("apply", &DPTexture::apply)
+    .def("getBackgroundModel", &DPTexture::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_<FuzzySugenoIntegral>(m, "FuzzySugenoIntegral")
+    .def(py::init<>())
+    .def("apply", &FuzzySugenoIntegral::apply)
+    .def("getBackgroundModel", &FuzzySugenoIntegral::getBackgroundModel)
+    ;
+
+  py::class_<FuzzyChoquetIntegral>(m, "FuzzyChoquetIntegral")
+    .def(py::init<>())
+    .def("apply", &FuzzyChoquetIntegral::apply)
+    .def("getBackgroundModel", &FuzzyChoquetIntegral::getBackgroundModel)
+    ;
+
+  py::class_<LBSimpleGaussian>(m, "LBSimpleGaussian")
+    .def(py::init<>())
+    .def("apply", &LBSimpleGaussian::apply)
+    .def("getBackgroundModel", &LBSimpleGaussian::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_<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_<LBP_MRF>(m, "LBP_MRF")
+    .def(py::init<>())
+    .def("apply", &LBP_MRF::apply)
+    .def("getBackgroundModel", &LBP_MRF::getBackgroundModel)
+    ;
+
+  py::class_<MultiLayer>(m, "MultiLayer")
+    .def(py::init<>())
+    .def("apply", &MultiLayer::apply)
+    .def("getBackgroundModel", &MultiLayer::getBackgroundModel)
+    ;
+
+  py::class_<PixelBasedAdaptiveSegmenter>(m, "PixelBasedAdaptiveSegmenter")
+    .def(py::init<>())
+    .def("apply", &PixelBasedAdaptiveSegmenter::apply)
+    .def("getBackgroundModel", &PixelBasedAdaptiveSegmenter::getBackgroundModel)
+    ;
+
+  py::class_<VuMeter>(m, "VuMeter")
+    .def(py::init<>())
+    .def("apply", &VuMeter::apply)
+    .def("getBackgroundModel", &VuMeter::getBackgroundModel)
+    ;
+
+  py::class_<KDE>(m, "KDE")
+    .def(py::init<>())
+    .def("apply", &KDE::apply)
+    .def("getBackgroundModel", &KDE::getBackgroundModel)
+    ;
+
+  py::class_<IndependentMultimodal>(m, "IndependentMultimodal")
+    .def(py::init<>())
+    .def("apply", &IndependentMultimodal::apply)
+    .def("getBackgroundModel", &IndependentMultimodal::getBackgroundModel)
+    ;
+
+  py::class_<MultiCue>(m, "MultiCue")
+    .def(py::init<>())
+    .def("apply", &MultiCue::apply)
+    .def("getBackgroundModel", &MultiCue::getBackgroundModel)
+    ;
+#endif
+
+  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_<LOBSTER>(m, "LOBSTER")
+    .def(py::init<>())
+    .def("apply", &LOBSTER::apply)
+    .def("getBackgroundModel", &LOBSTER::getBackgroundModel)
+    ;
+
+  py::class_<PAWCS>(m, "PAWCS")
+    .def(py::init<>())
+    .def("apply", &PAWCS::apply)
+    .def("getBackgroundModel", &PAWCS::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..e229c6f10c731ad2fe1291503eef39993fc0c1da
--- /dev/null
+++ b/wrapper/python/ndarray_converter.cpp
@@ -0,0 +1,357 @@
+#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;
+    }
+
+#if CV_MAJOR_VERSION < 4
+    UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
+#else
+    UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, AccessFlag flags, UMatUsageFlags usageFlags) const
+#endif
+    {
+        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);
+    }
+
+#if CV_MAJOR_VERSION < 4
+    bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
+#else
+    bool allocate(UMatData* u, AccessFlag accessFlags, UMatUsageFlags usageFlags) const
+#endif
+    {
+        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..2a1dc5ad775adca35430a3bbaccffa5379fac7b7
--- /dev/null
+++ b/wrapper/python/ndarray_converter.h
@@ -0,0 +1,41 @@
+# 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_matlab/.gitignore b/wrapper_matlab/.gitignore
deleted file mode 100644
index 1c363bf8e10adc1abae7940599fcf0292c8ec151..0000000000000000000000000000000000000000
--- a/wrapper_matlab/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.mex*
diff --git a/wrapper_matlab/compile.m b/wrapper_matlab/compile.m
deleted file mode 100644
index 314ada17de002e4a63f565b4178cc886a1c2f406..0000000000000000000000000000000000000000
--- a/wrapper_matlab/compile.m
+++ /dev/null
@@ -1,94 +0,0 @@
-%% Compile
-clc;
-mexOpenCV -v -DMEX_COMPILE_FLAG -I"..\package_bgs" backgroundSubtractor_wrapper.cpp ...
-  "..\package_bgs\FrameDifference.cpp" ...
-  "..\package_bgs\StaticFrameDifference.cpp" ...
-  "..\package_bgs\WeightedMovingMean.cpp" ...
-  "..\package_bgs\WeightedMovingVariance.cpp" ...
-  "..\package_bgs\MixtureOfGaussianV1.cpp" ...
-  "..\package_bgs\MixtureOfGaussianV2.cpp" ...
-  "..\package_bgs\AdaptiveBackgroundLearning.cpp" ...
-  "..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" ...
-  "..\package_bgs\GMG.cpp" ...
-  "..\package_bgs\KNN.cpp" ...
-  "..\package_bgs\DPAdaptiveMedian.cpp" ...
-  "..\package_bgs\DPGrimsonGMM.cpp" ...
-  "..\package_bgs\DPZivkovicAGMM.cpp" ...
-  "..\package_bgs\DPMean.cpp" ...
-  "..\package_bgs\DPWrenGA.cpp" ...
-  "..\package_bgs\DPPratiMediod.cpp" ...
-  "..\package_bgs\DPEigenbackground.cpp" ...
-  "..\package_bgs\DPTexture.cpp" ...
-  "..\package_bgs\dp\AdaptiveMedianBGS.cpp" ...
-  "..\package_bgs\dp\Image.cpp" ...
-  "..\package_bgs\dp\Error.cpp" ...
-  "..\package_bgs\dp\GrimsonGMM.cpp" ...
-  "..\package_bgs\dp\ZivkovicAGMM.cpp" ...
-  "..\package_bgs\dp\MeanBGS.cpp" ...
-  "..\package_bgs\dp\WrenGA.cpp"  ...
-  "..\package_bgs\dp\PratiMediodBGS.cpp" ...
-  "..\package_bgs\dp\Eigenbackground.cpp" ...
-  "..\package_bgs\dp\TextureBGS.cpp" ...
-  "..\package_bgs\T2FGMM_UM.cpp" ...
-  "..\package_bgs\T2FGMM_UV.cpp" ...
-  "..\package_bgs\T2FMRF_UM.cpp" ...
-  "..\package_bgs\T2FMRF_UV.cpp" ...
-  "..\package_bgs\FuzzyChoquetIntegral.cpp" ...
-  "..\package_bgs\FuzzySugenoIntegral.cpp" ...
-  "..\package_bgs\T2F\T2FGMM.cpp" ...
-  "..\package_bgs\T2F\T2FMRF.cpp" ...
-  "..\package_bgs\T2F\MRF.cpp" ...
-  "..\package_bgs\T2F\FuzzyUtils.cpp" ...
-  "..\package_analysis\PixelUtils.cpp" ...
-  "..\package_bgs\MultiLayer.cpp" ...
-  "..\package_bgs\MultiLayer\CMultiLayerBGS.cpp" ...
-  "..\package_bgs\MultiLayer\LocalBinaryPattern.cpp" ...
-  "..\package_bgs\MultiLayer\BlobResult.cpp" ...
-  "..\package_bgs\MultiLayer\BlobExtraction.cpp" ...
-  "..\package_bgs\MultiLayer\blob.cpp" ...
-  "..\package_bgs\LBSimpleGaussian.cpp" ...
-  "..\package_bgs\LBFuzzyGaussian.cpp" ...
-  "..\package_bgs\LBMixtureOfGaussians.cpp" ...
-  "..\package_bgs\LBAdaptiveSOM.cpp" ...
-  "..\package_bgs\LBFuzzyAdaptiveSOM.cpp" ...
-  "..\package_bgs\lb\BGModel.cpp" ...
-  "..\package_bgs\lb\BGModelFuzzyGauss.cpp" ...
-  "..\package_bgs\lb\BGModelFuzzySom.cpp" ...
-  "..\package_bgs\lb\BGModelGauss.cpp" ...
-  "..\package_bgs\lb\BGModelMog.cpp" ...
-  "..\package_bgs\lb\BGModelSom.cpp" ...
-  "..\package_bgs\LBP_MRF.cpp" ...
-  "..\package_bgs\LBP_MRF\MotionDetection.cpp" ...
-  "..\package_bgs\LBP_MRF\MEImage.cpp" ...
-  "..\package_bgs\LBP_MRF\MEHistogram.cpp" ...
-  "..\package_bgs\LBP_MRF\MEDefs.cpp" ...
-  "..\package_bgs\LBP_MRF\maxflow.cpp" ...
-  "..\package_bgs\LBP_MRF\graph.cpp" ...
-  "..\package_bgs\PixelBasedAdaptiveSegmenter.cpp" ...
-  "..\package_bgs\PBAS\PBAS.cpp" ...
-  "..\package_bgs\VuMeter.cpp" ...
-  "..\package_bgs\VuMeter\TBackgroundVuMeter.cpp" ...
-  "..\package_bgs\VuMeter\TBackground.cpp" ...
-  "..\package_bgs\KDE.cpp" ...
-  "..\package_bgs\KDE\NPBGSubtractor.cpp" ...
-  "..\package_bgs\KDE\NPBGmodel.cpp" ...
-  "..\package_bgs\KDE\KernelTable.cpp" ...
-  "..\package_bgs\IndependentMultimodal.cpp" ...
-  "..\package_bgs\IMBS\IMBS.cpp" ...
-  "..\package_bgs\MultiCue.cpp" ...
-  "..\package_bgs\SigmaDelta.cpp" ...
-  "..\package_bgs\SigmaDelta\sdLaMa091.cpp" ...
-  "..\package_bgs\SuBSENSE.cpp" ...
-  "..\package_bgs\LOBSTER.cpp" ...
-  "..\package_bgs\PAWCS.cpp" ...
-  "..\package_bgs\LBSP\LBSP.cpp" ...
-  "..\package_bgs\LBSP\LBSP_.cpp" ...
-  "..\package_bgs\LBSP\BackgroundSubtractorLBSP.cpp" ...
-  "..\package_bgs\LBSP\BackgroundSubtractorLBSP_.cpp" ...
-  "..\package_bgs\LBSP\BackgroundSubtractorLOBSTER.cpp" ...
-  "..\package_bgs\LBSP\BackgroundSubtractorPAWCS.cpp" ...
-  "..\package_bgs\LBSP\BackgroundSubtractorSuBSENSE.cpp" ...
-  "..\package_bgs\ViBe.cpp" ...
-  "..\package_bgs\ViBe\vibe-background-sequential.cpp" ...
-  "..\package_bgs\TwoPoints.cpp" ...
-  "..\package_bgs\TwoPoints\two_points.cpp"
diff --git a/wrapper_python/bgslibrary_module.cpp b/wrapper_python/bgslibrary_module.cpp
deleted file mode 100644
index edb75a8552bbc29d4e27ef72485d7859e38851c8..0000000000000000000000000000000000000000
--- a/wrapper_python/bgslibrary_module.cpp
+++ /dev/null
@@ -1,265 +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 <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <exception>
-
-#include <opencv2/opencv.hpp>
-#include "np_opencv_converter.h"
-
-#include "../package_bgs/bgslibrary.h"
-
-namespace py = boost::python;
-
-cv::Mat test_transpose(const cv::Mat& in)
-{
-	std::cerr << "Input size: " << in.size() << std::endl;
-	std::cerr << "Returning transpose" << std::endl;
-	return in.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)
-				;
-
-#if CV_MAJOR_VERSION == 2
-			py::class_<GMG>("GMG")
-				.def("apply", &GMG::apply)
-				.def("getBackgroundModel", &GMG::getBackgroundModel)
-				;
-#endif
-
-			py::class_<IndependentMultimodal>("IndependentMultimodal")
-				.def("apply", &IndependentMultimodal::apply)
-				.def("getBackgroundModel", &IndependentMultimodal::getBackgroundModel)
-				;
-
-			py::class_<KDE>("KDE")
-				.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)
-				;
-#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)
-				;
-
-#if CV_MAJOR_VERSION == 2
-			py::class_<MixtureOfGaussianV1>("MixtureOfGaussianV1")
-				.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)
-				;
-		}
-	} // namespace fs
-} // namespace python
diff --git a/wrapper_python/np_opencv_converter.cpp b/wrapper_python/np_opencv_converter.cpp
deleted file mode 100644
index 6050f6b40e5815670d2f2f8383381642ee2fd413..0000000000000000000000000000000000000000
--- a/wrapper_python/np_opencv_converter.cpp
+++ /dev/null
@@ -1,103 +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
-static void py_init() {
-  Py_Initialize();
-  import_array();
-}
-
-// 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 68386f0f16c8855ff0c0b7c74dac2a58ea9b6438..0000000000000000000000000000000000000000
--- a/wrapper_python/np_opencv_converter.h
+++ /dev/null
@@ -1,122 +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
-
-#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;
-
-    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 7ca21dd59b201947fb16ff6bf60c18a04073998e..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/conversion.cpp
+++ /dev/null
@@ -1,349 +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.
- */
-
-static void init()
-{
-    import_array();
-}
-
-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;
-}
-
-#define OPENCV_3 0
-#if OPENCV_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) 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);
-        }
-        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) const
-    {
-        return stdAllocator->allocate(u, accessFlags);
-    }
-
-    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(); }
-
-void NDArrayConverter::init()
-{
-    import_array();
-}
-
-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 OPENCV_3
-      m.addref();
-      Py_INCREF(o);
-#else
-        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 OPENCV_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 8ce616dbcd540e9842de24d4ec04d780f0c04e80..0000000000000000000000000000000000000000
--- a/wrapper_python/utils/conversion.h
+++ /dev/null
@@ -1,75 +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 <opencv2/core/core.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:
-    void init();
-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);
-    }
-
-};