diff --git a/.gitignore b/.gitignore index 3f5e0f7bbb092306784a68a8dd9a3fdf95c25e08..f1d9cb4f152103523a763b0ee6d6d67515a8239c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ etc/ build_*/ -binaries/ +dataset_*/ +binaries*/ java_gui/dist/ java_gui/build/ java_gui/bgslibrary.exe @@ -9,4 +10,5 @@ qt_gui/ fet/etc/ *.exe *.pdb -*.suo \ No newline at end of file +*.suo +*.dll diff --git a/CMakeLists.txt b/CMakeLists.txt index d8e60dae5f33cad38be88f2d074d9d0ddbdc676c..6a01cce7f22aefc347789b441115adb3c734e168 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,24 +2,44 @@ cmake_minimum_required(VERSION 2.8) project(bgslibrary) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") +# 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}") + +if(UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") +endif(UNIX) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") #set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules) -set( bgs_out_dir "." ) +# 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} ) +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) +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) @@ -30,6 +50,7 @@ IF(UNIX) #ADD_DEFINITIONS(-Wconversion -Wfloat-equal) endif(UNIX) +set(OpenCV_STATIC OFF) find_package(OpenCV REQUIRED) message(STATUS "OpenCV library status:") @@ -37,24 +58,50 @@ message(STATUS " version: ${OpenCV_VERSION}") message(STATUS " libraries: ${OpenCV_LIBS}") message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") -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_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 sources FrameProcessor.cpp PreProcessor.cpp VideoAnalysis.cpp VideoCapture.cpp) -file(GLOB main Main.cpp) +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) + + 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}") +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) # list(REMOVE_ITEM sources ${demo} ${demo2}) file(GLOB_RECURSE analysis_src package_analysis/*.cpp) -file(GLOB_RECURSE bgs_src package_bgs/*.cpp package_bgs/*.c) -file(GLOB_RECURSE bgs_include package_bgs/*.h) +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}) +endif() # GMG is not available in older OpenCV versions if(${OpenCV_VERSION} VERSION_LESS 2.4.3) @@ -62,10 +109,16 @@ if(${OpenCV_VERSION} VERSION_LESS 2.4.3) list(REMOVE_ITEM bgs_src ${gmg}) endif() -include_directories(${CMAKE_SOURCE_DIR}) - -add_library(libbgs STATIC ${sources} ${bgs_src} ${analysis_src}) -target_link_libraries(libbgs ${OpenCV_LIBS}) +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) +else() + #add_library(libbgs STATIC ${sources} ${bgs_src} ${analysis_src}) + add_library(libbgs STATIC ${bgs_src} ${analysis_src}) + target_link_libraries(libbgs ${OpenCV_LIBS}) +endif() set_property(TARGET libbgs PROPERTY PUBLIC_HEADER ${bgs_include}) if(WIN32) # set_property(TARGET libbgs PROPERTY SUFFIX ".lib") @@ -83,7 +136,7 @@ target_link_libraries(bgs_demo ${OpenCV_LIBS} libbgs) add_executable(bgs_demo2 ${demo2}) target_link_libraries(bgs_demo2 ${OpenCV_LIBS} libbgs) -INSTALL(TARGETS libbgs +install(TARGETS libbgs bgslibrary RUNTIME DESTINATION bin COMPONENT app LIBRARY DESTINATION lib COMPONENT runtime diff --git a/Demo.cpp b/Demo.cpp index 61561be797917b2b8dffb8f637f679df8c6e1c26..fec54d85fe804e6bece7ec0bd1e6d5c2b7fe7626 100644 --- a/Demo.cpp +++ b/Demo.cpp @@ -17,178 +17,98 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - -#include "package_bgs/FrameDifferenceBGS.h" -#include "package_bgs/StaticFrameDifferenceBGS.h" -#include "package_bgs/WeightedMovingMeanBGS.h" -#include "package_bgs/WeightedMovingVarianceBGS.h" -#include "package_bgs/MixtureOfGaussianV1BGS.h" -#include "package_bgs/MixtureOfGaussianV2BGS.h" -#include "package_bgs/AdaptiveBackgroundLearning.h" -#include "package_bgs/AdaptiveSelectiveBackgroundLearning.h" - -#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 -#include "package_bgs/GMG.h" -#endif - -#include "package_bgs/dp/DPAdaptiveMedianBGS.h" -#include "package_bgs/dp/DPGrimsonGMMBGS.h" -#include "package_bgs/dp/DPZivkovicAGMMBGS.h" -#include "package_bgs/dp/DPMeanBGS.h" -#include "package_bgs/dp/DPWrenGABGS.h" -#include "package_bgs/dp/DPPratiMediodBGS.h" -#include "package_bgs/dp/DPEigenbackgroundBGS.h" -#include "package_bgs/dp/DPTextureBGS.h" - -#include "package_bgs/tb/T2FGMM_UM.h" -#include "package_bgs/tb/T2FGMM_UV.h" -#include "package_bgs/tb/T2FMRF_UM.h" -#include "package_bgs/tb/T2FMRF_UV.h" -#include "package_bgs/tb/FuzzySugenoIntegral.h" -#include "package_bgs/tb/FuzzyChoquetIntegral.h" - -#include "package_bgs/lb/LBSimpleGaussian.h" -#include "package_bgs/lb/LBFuzzyGaussian.h" -#include "package_bgs/lb/LBMixtureOfGaussians.h" -#include "package_bgs/lb/LBAdaptiveSOM.h" -#include "package_bgs/lb/LBFuzzyAdaptiveSOM.h" - -#include "package_bgs/ck/LbpMrf.h" -#include "package_bgs/jmo/MultiLayerBGS.h" -// The PBAS algorithm was removed from BGSLibrary because it is -// based on patented algorithm ViBE -// http://www2.ulg.ac.be/telecom/research/vibe/ -//#include "package_bgs/pt/PixelBasedAdaptiveSegmenter.h" -#include "package_bgs/av/VuMeter.h" -#include "package_bgs/ae/KDE.h" -#include "package_bgs/db/IndependentMultimodalBGS.h" -#include "package_bgs/sjn/SJN_MultiCueBGS.h" -#include "package_bgs/bl/SigmaDeltaBGS.h" - -#include "package_bgs/pl/SuBSENSE.h" -#include "package_bgs/pl/LOBSTER.h" +#include "package_bgs/bgslibrary.h" int main(int argc, char **argv) { std::cout << "Using OpenCV " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << "." << CV_SUBMINOR_VERSION << std::endl; - CvCapture *capture = 0; - int resize_factor = 100; + VideoCapture capture; - if(argc > 1) + if (argc > 1) { std::cout << "Openning: " << argv[1] << std::endl; - capture = cvCaptureFromAVI(argv[1]); + capture.open(argv[1]); } else - { - capture = cvCaptureFromCAM(0); - resize_factor = 50; // set size = 50% of original image - } + capture.open(0); - if(!capture) + if (!capture.isOpened()) { std::cerr << "Cannot initialize video!" << std::endl; return -1; } - - IplImage *frame_aux = cvQueryFrame(capture); - IplImage *frame = cvCreateImage(cvSize((int)((frame_aux->width*resize_factor)/100) , (int)((frame_aux->height*resize_factor)/100)), frame_aux->depth, frame_aux->nChannels); - cvResize(frame_aux, frame); /* Background Subtraction Methods */ IBGS *bgs; - /*** Default Package ***/ - bgs = new FrameDifferenceBGS; - //bgs = new StaticFrameDifferenceBGS; - //bgs = new WeightedMovingMeanBGS; - //bgs = new WeightedMovingVarianceBGS; - //bgs = new MixtureOfGaussianV1BGS; - //bgs = new MixtureOfGaussianV2BGS; + 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; - - /*** DP Package (thanks to Donovan Parks) ***/ - //bgs = new DPAdaptiveMedianBGS; - //bgs = new DPGrimsonGMMBGS; - //bgs = new DPZivkovicAGMMBGS; - //bgs = new DPMeanBGS; - //bgs = new DPWrenGABGS; - //bgs = new DPPratiMediodBGS; - //bgs = new DPEigenbackgroundBGS; - //bgs = new DPTextureBGS; - - /*** TB Package (thanks to Thierry Bouwmans, Fida EL BAF and Zhenjie Zhao) ***/ + //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; - - /*** JMO Package (thanks to Jean-Marc Odobez) ***/ - //bgs = new MultiLayerBGS; - - /*** PT Package (thanks to Martin Hofmann, Philipp Tiefenbacher and Gerhard Rigoll) ***/ + //bgs = new MultiLayer; //bgs = new PixelBasedAdaptiveSegmenter; - - /*** LB Package (thanks to Laurence Bender) ***/ //bgs = new LBSimpleGaussian; //bgs = new LBFuzzyGaussian; //bgs = new LBMixtureOfGaussians; //bgs = new LBAdaptiveSOM; //bgs = new LBFuzzyAdaptiveSOM; - - /*** LBP-MRF Package (thanks to Csaba Kertész) ***/ - //bgs = new LbpMrf; - - /*** AV Package (thanks to Lionel Robinault and Antoine Vacavant) ***/ + //bgs = new LBP_MRF; //bgs = new VuMeter; - - /*** EG Package (thanks to Ahmed Elgammal) ***/ //bgs = new KDE; - - /*** DB Package (thanks to Domenico Daniele Bloisi) ***/ - //bgs = new IndependentMultimodalBGS; - - /*** SJN Package (thanks to SeungJong Noh) ***/ - //bgs = new SJN_MultiCueBGS; - - /*** BL Package (thanks to Benjamin Laugraud) ***/ - //bgs = new SigmaDeltaBGS; - - /*** PL Package (thanks to Pierre-Luc) ***/ - //bgs = new SuBSENSEBGS(); - //bgs = new LOBSTERBGS(); + //bgs = new IndependentMultimodal; + //bgs = new MultiCue; + //bgs = new SigmaDelta; + //bgs = new SuBSENSE; + //bgs = new LOBSTER; + //bgs = new PAWCS; + //bgs = new TwoPoints; + //bgs = new ViBe; int key = 0; - while(key != 'q') + cv::Mat img_input; + while (key != 'q') { - frame_aux = cvQueryFrame(capture); - if(!frame_aux) break; + capture >> img_input; + if (img_input.empty()) break; - cvResize(frame_aux, frame); - - cv::Mat img_input(frame); cv::imshow("input", img_input); 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 - + //if(!img_mask.empty()) // cv::imshow("Foreground", img_mask); // do something - + key = cvWaitKey(33); } delete bgs; + capture.release(); cvDestroyAllWindows(); - cvReleaseCapture(&capture); return 0; } diff --git a/Demo.py b/Demo.py new file mode 100644 index 0000000000000000000000000000000000000000..71bc35232e73fe4ff54b70d40d3690b274c31af7 --- /dev/null +++ b/Demo.py @@ -0,0 +1,84 @@ +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 index fe95c525feec74bb72e92234a6bd6d2d1fe47c38..22c6ffc36d5100967cfd2873b82f0bdb13b61268 100644 --- a/Demo2.cpp +++ b/Demo2.cpp @@ -17,56 +17,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - -#include "package_bgs/FrameDifferenceBGS.h" -#include "package_bgs/StaticFrameDifferenceBGS.h" -#include "package_bgs/WeightedMovingMeanBGS.h" -#include "package_bgs/WeightedMovingVarianceBGS.h" -#include "package_bgs/MixtureOfGaussianV1BGS.h" -#include "package_bgs/MixtureOfGaussianV2BGS.h" -#include "package_bgs/AdaptiveBackgroundLearning.h" -#include "package_bgs/AdaptiveSelectiveBackgroundLearning.h" - -#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 -#include "package_bgs/GMG.h" -#endif - -#include "package_bgs/dp/DPAdaptiveMedianBGS.h" -#include "package_bgs/dp/DPGrimsonGMMBGS.h" -#include "package_bgs/dp/DPZivkovicAGMMBGS.h" -#include "package_bgs/dp/DPMeanBGS.h" -#include "package_bgs/dp/DPWrenGABGS.h" -#include "package_bgs/dp/DPPratiMediodBGS.h" -#include "package_bgs/dp/DPEigenbackgroundBGS.h" -#include "package_bgs/dp/DPTextureBGS.h" - -#include "package_bgs/tb/T2FGMM_UM.h" -#include "package_bgs/tb/T2FGMM_UV.h" -#include "package_bgs/tb/T2FMRF_UM.h" -#include "package_bgs/tb/T2FMRF_UV.h" -#include "package_bgs/tb/FuzzySugenoIntegral.h" -#include "package_bgs/tb/FuzzyChoquetIntegral.h" - -#include "package_bgs/lb/LBSimpleGaussian.h" -#include "package_bgs/lb/LBFuzzyGaussian.h" -#include "package_bgs/lb/LBMixtureOfGaussians.h" -#include "package_bgs/lb/LBAdaptiveSOM.h" -#include "package_bgs/lb/LBFuzzyAdaptiveSOM.h" - -#include "package_bgs/ck/LbpMrf.h" -#include "package_bgs/jmo/MultiLayerBGS.h" -// The PBAS algorithm was removed from BGSLibrary because it is -// based on patented algorithm ViBE -// http://www2.ulg.ac.be/telecom/research/vibe/ -//#include "package_bgs/pt/PixelBasedAdaptiveSegmenter.h" -#include "package_bgs/av/VuMeter.h" -#include "package_bgs/ae/KDE.h" -#include "package_bgs/db/IndependentMultimodalBGS.h" -#include "package_bgs/sjn/SJN_MultiCueBGS.h" -#include "package_bgs/bl/SigmaDeltaBGS.h" - -#include "package_bgs/pl/SuBSENSE.h" -#include "package_bgs/pl/LOBSTER.h" +#include "package_bgs/bgslibrary.h" int main(int argc, char **argv) { @@ -75,81 +26,60 @@ int main(int argc, char **argv) /* Background Subtraction Methods */ IBGS *bgs; - /*** Default Package ***/ - bgs = new FrameDifferenceBGS; - //bgs = new StaticFrameDifferenceBGS; - //bgs = new WeightedMovingMeanBGS; - //bgs = new WeightedMovingVarianceBGS; - //bgs = new MixtureOfGaussianV1BGS; - //bgs = new MixtureOfGaussianV2BGS; + 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; - - /*** DP Package (thanks to Donovan Parks) ***/ - //bgs = new DPAdaptiveMedianBGS; - //bgs = new DPGrimsonGMMBGS; - //bgs = new DPZivkovicAGMMBGS; - //bgs = new DPMeanBGS; - //bgs = new DPWrenGABGS; - //bgs = new DPPratiMediodBGS; - //bgs = new DPEigenbackgroundBGS; - //bgs = new DPTextureBGS; - - /*** TB Package (thanks to Thierry Bouwmans, Fida EL BAF and Zhenjie Zhao) ***/ + //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; - - /*** JMO Package (thanks to Jean-Marc Odobez) ***/ - //bgs = new MultiLayerBGS; - - /*** PT Package (thanks to Martin Hofmann, Philipp Tiefenbacher and Gerhard Rigoll) ***/ + //bgs = new MultiLayer; //bgs = new PixelBasedAdaptiveSegmenter; - - /*** LB Package (thanks to Laurence Bender) ***/ //bgs = new LBSimpleGaussian; //bgs = new LBFuzzyGaussian; //bgs = new LBMixtureOfGaussians; //bgs = new LBAdaptiveSOM; //bgs = new LBFuzzyAdaptiveSOM; - - /*** LBP-MRF Package (thanks to Csaba Kertész) ***/ - //bgs = new LbpMrf; - - /*** AV Package (thanks to Lionel Robinault and Antoine Vacavant) ***/ + //bgs = new LBP_MRF; //bgs = new VuMeter; - - /*** EG Package (thanks to Ahmed Elgammal) ***/ //bgs = new KDE; - - /*** DB Package (thanks to Domenico Daniele Bloisi) ***/ - //bgs = new IndependentMultimodalBGS; - - /*** SJN Package (thanks to SeungJong Noh) ***/ - //bgs = new SJN_MultiCueBGS; - - /*** BL Package (thanks to Benjamin Laugraud) ***/ - //bgs = new SigmaDeltaBGS; - - /*** PL Package (thanks to Pierre-Luc) ***/ - //bgs = new SuBSENSEBGS(); - //bgs = new LOBSTERBGS(); + //bgs = new IndependentMultimodal; + //bgs = new MultiCue; + //bgs = new SigmaDelta; + //bgs = new SuBSENSE; + //bgs = new LOBSTER; + //bgs = new PAWCS; + //bgs = new TwoPoints; + //bgs = new ViBe; int frameNumber = 1; int key = 0; - while(key != 'q') + while (key != 'q') { std::stringstream ss; ss << frameNumber; - std::string fileName = "frames/" + ss.str() + ".png"; + std::string fileName = "dataset/frames/" + ss.str() + ".png"; std::cout << "reading " << fileName << std::endl; cv::Mat img_input = cv::imread(fileName, CV_LOAD_IMAGE_COLOR); - + if (img_input.empty()) break; @@ -157,18 +87,19 @@ int main(int argc, char **argv) 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 - + bgs->process(img_input, img_mask, img_bkgmodel); + // by default, "bgs->process(.)" automatically shows the foreground mask image + // or set "bgs->setShowOutput(false)" to disable + //if(!img_mask.empty()) // cv::imshow("Foreground", img_mask); // do something - + key = cvWaitKey(33); frameNumber++; } cvWaitKey(0); delete bgs; - cvDestroyAllWindows(); return 0; diff --git a/FrameProcessor.cpp b/FrameProcessor.cpp index 0cce65261c781861eca6eb926482c55cb5df3a96..50881219f6d4bf5e703840f3912204b006777686 100644 --- a/FrameProcessor.cpp +++ b/FrameProcessor.cpp @@ -37,23 +37,25 @@ namespace bgslibrary if (enablePreProcessor) preProcessor = new PreProcessor; - if (enableFrameDifferenceBGS) - frameDifference = new FrameDifferenceBGS; + if (enableFrameDifference) + frameDifference = new FrameDifference; - if (enableStaticFrameDifferenceBGS) - staticFrameDifference = new StaticFrameDifferenceBGS; + if (enableStaticFrameDifference) + staticFrameDifference = new StaticFrameDifference; - if (enableWeightedMovingMeanBGS) - weightedMovingMean = new WeightedMovingMeanBGS; + if (enableWeightedMovingMean) + weightedMovingMean = new WeightedMovingMean; - if (enableWeightedMovingVarianceBGS) - weightedMovingVariance = new WeightedMovingVarianceBGS; + if (enableWeightedMovingVariance) + weightedMovingVariance = new WeightedMovingVariance; - if (enableMixtureOfGaussianV1BGS) - mixtureOfGaussianV1BGS = new MixtureOfGaussianV1BGS; +#if CV_MAJOR_VERSION == 2 + if (enableMixtureOfGaussianV1) + mixtureOfGaussianV1 = new MixtureOfGaussianV1; +#endif - if (enableMixtureOfGaussianV2BGS) - mixtureOfGaussianV2BGS = new MixtureOfGaussianV2BGS; + if (enableMixtureOfGaussianV2) + mixtureOfGaussianV2 = new MixtureOfGaussianV2; if (enableAdaptiveBackgroundLearning) adaptiveBackgroundLearning = new AdaptiveBackgroundLearning; @@ -63,29 +65,29 @@ namespace bgslibrary gmg = new GMG; #endif - if (enableDPAdaptiveMedianBGS) - adaptiveMedian = new DPAdaptiveMedianBGS; + if (enableDPAdaptiveMedian) + dpAdaptiveMedian = new DPAdaptiveMedian; - if (enableDPGrimsonGMMBGS) - grimsonGMM = new DPGrimsonGMMBGS; + if (enableDPGrimsonGMM) + dpGrimsonGMM = new DPGrimsonGMM; - if (enableDPZivkovicAGMMBGS) - zivkovicAGMM = new DPZivkovicAGMMBGS; + if (enableDPZivkovicAGMM) + dpZivkovicAGMM = new DPZivkovicAGMM; - if (enableDPMeanBGS) - temporalMean = new DPMeanBGS; + if (enableDPMean) + dpTemporalMean = new DPMean; - if (enableDPWrenGABGS) - wrenGA = new DPWrenGABGS; + if (enableDPWrenGA) + dpWrenGA = new DPWrenGA; - if (enableDPPratiMediodBGS) - pratiMediod = new DPPratiMediodBGS; + if (enableDPPratiMediod) + dpPratiMediod = new DPPratiMediod; - if (enableDPEigenbackgroundBGS) - eigenBackground = new DPEigenbackgroundBGS; + if (enableDPEigenbackground) + dpEigenBackground = new DPEigenbackground; - if (enableDPTextureBGS) - textureBGS = new DPTextureBGS; + if (enableDPTexture) + dpTexture = new DPTexture; if (enableT2FGMM_UM) type2FuzzyGMM_UM = new T2FGMM_UM; @@ -121,13 +123,15 @@ namespace bgslibrary lbFuzzyAdaptiveSOM = new LBFuzzyAdaptiveSOM; if (enableLbpMrf) - lbpMrf = new LbpMrf; + lbpMrf = new LBP_MRF; - if(enableMultiLayerBGS) - multiLayerBGS = new MultiLayerBGS; +#if CV_MAJOR_VERSION == 2 + if (enableMultiLayer) + multiLayer = new MultiLayer; +#endif - //if(enablePBAS) - // pixelBasedAdaptiveSegmenter = new PixelBasedAdaptiveSegmenter; + if (enablePBAS) + pixelBasedAdaptiveSegmenter = new PixelBasedAdaptiveSegmenter; if (enableVuMeter) vuMeter = new VuMeter; @@ -136,19 +140,19 @@ namespace bgslibrary kde = new KDE; if (enableIMBS) - imbs = new IndependentMultimodalBGS; + imbs = new IndependentMultimodal; - if (enableMultiCueBGS) - mcbgs = new SJN_MultiCueBGS; + if (enableMultiCue) + multiCue = new MultiCue; - if (enableSigmaDeltaBGS) - sdbgs = new SigmaDeltaBGS; + if (enableSigmaDelta) + sigmaDelta = new SigmaDelta; - if (enableSuBSENSEBGS) - ssbgs = new SuBSENSEBGS; + if (enableSuBSENSE) + subSENSE = new SuBSENSE; - if (enableLOBSTERBGS) - lobgs = new LOBSTERBGS; + if (enableLOBSTER) + lobster = new LOBSTER; if (enableForegroundMaskAnalysis) foregroundMaskAnalysis = new ForegroundMaskAnalysis; @@ -171,169 +175,177 @@ namespace bgslibrary frameNumber++; if (enablePreProcessor) - preProcessor->process(img_input, img_prep); + preProcessor->process(img_input, img_preProcessor); - if (enableFrameDifferenceBGS) - process("FrameDifferenceBGS", frameDifference, img_prep, img_framediff); + if (enableFrameDifference) + process("FrameDifference", frameDifference, img_preProcessor, img_frameDifference); - if (enableStaticFrameDifferenceBGS) - process("StaticFrameDifferenceBGS", staticFrameDifference, img_prep, img_staticfdiff); + if (enableStaticFrameDifference) + process("StaticFrameDifference", staticFrameDifference, img_preProcessor, img_staticFrameDifference); - if (enableWeightedMovingMeanBGS) - process("WeightedMovingMeanBGS", weightedMovingMean, img_prep, img_wmovmean); + if (enableWeightedMovingMean) + process("WeightedMovingMean", weightedMovingMean, img_preProcessor, img_weightedMovingMean); - if (enableWeightedMovingVarianceBGS) - process("WeightedMovingVarianceBGS", weightedMovingVariance, img_prep, img_movvar); + if (enableWeightedMovingVariance) + process("WeightedMovingVariance", weightedMovingVariance, img_preProcessor, img_weightedMovingVariance); - if (enableMixtureOfGaussianV1BGS) - process("MixtureOfGaussianV1BGS", mixtureOfGaussianV1BGS, img_prep, img_mog1); +#if CV_MAJOR_VERSION == 2 + if (enableMixtureOfGaussianV1) + process("MixtureOfGaussianV1", mixtureOfGaussianV1, img_preProcessor, img_mixtureOfGaussianV1); +#endif - if (enableMixtureOfGaussianV2BGS) - process("MixtureOfGaussianV2BGS", mixtureOfGaussianV2BGS, img_prep, img_mog2); + if (enableMixtureOfGaussianV2) + process("MixtureOfGaussianV2", mixtureOfGaussianV2, img_preProcessor, img_mixtureOfGaussianV2); if (enableAdaptiveBackgroundLearning) - process("AdaptiveBackgroundLearning", adaptiveBackgroundLearning, img_prep, img_bkgl_fgmask); + 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_prep, img_gmg); + process("GMG", gmg, img_preProcessor, img_gmg); #endif - if (enableDPAdaptiveMedianBGS) - process("DPAdaptiveMedianBGS", adaptiveMedian, img_prep, img_adpmed); + if (enableDPAdaptiveMedian) + process("DPAdaptiveMedian", dpAdaptiveMedian, img_preProcessor, img_dpAdaptiveMedian); - if (enableDPGrimsonGMMBGS) - process("DPGrimsonGMMBGS", grimsonGMM, img_prep, img_grigmm); + if (enableDPGrimsonGMM) + process("DPGrimsonGMM", dpGrimsonGMM, img_preProcessor, img_dpGrimsonGMM); - if (enableDPZivkovicAGMMBGS) - process("DPZivkovicAGMMBGS", zivkovicAGMM, img_prep, img_zivgmm); + if (enableDPZivkovicAGMM) + process("DPZivkovicAGMM", dpZivkovicAGMM, img_preProcessor, img_dpZivkovicAGMM); - if (enableDPMeanBGS) - process("DPMeanBGS", temporalMean, img_prep, img_tmpmean); + if (enableDPMean) + process("DPMean", dpTemporalMean, img_preProcessor, img_dpTemporalMean); - if (enableDPWrenGABGS) - process("DPWrenGABGS", wrenGA, img_prep, img_wrenga); + if (enableDPWrenGA) + process("DPWrenGA", dpWrenGA, img_preProcessor, img_dpWrenGA); - if (enableDPPratiMediodBGS) - process("DPPratiMediodBGS", pratiMediod, img_prep, img_pramed); + if (enableDPPratiMediod) + process("DPPratiMediod", dpPratiMediod, img_preProcessor, img_dpPratiMediod); - if (enableDPEigenbackgroundBGS) - process("DPEigenbackgroundBGS", eigenBackground, img_prep, img_eigbkg); + if (enableDPEigenbackground) + process("DPEigenbackground", dpEigenBackground, img_preProcessor, img_dpEigenBackground); - if (enableDPTextureBGS) - process("DPTextureBGS", textureBGS, img_prep, img_texbgs); + if (enableDPTexture) + process("DPTexture", dpTexture, img_preProcessor, img_dpTexture); if (enableT2FGMM_UM) - process("T2FGMM_UM", type2FuzzyGMM_UM, img_prep, img_t2fgmm_um); + process("T2FGMM_UM", type2FuzzyGMM_UM, img_preProcessor, img_type2FuzzyGMM_UM); if (enableT2FGMM_UV) - process("T2FGMM_UV", type2FuzzyGMM_UV, img_prep, img_t2fgmm_uv); + process("T2FGMM_UV", type2FuzzyGMM_UV, img_preProcessor, img_type2FuzzyGMM_UV); if (enableT2FMRF_UM) - process("T2FMRF_UM", type2FuzzyMRF_UM, img_prep, img_t2fmrf_um); + process("T2FMRF_UM", type2FuzzyMRF_UM, img_preProcessor, img_type2FuzzyMRF_UM); if (enableT2FMRF_UV) - process("T2FMRF_UV", type2FuzzyMRF_UV, img_prep, img_t2fmrf_uv); + process("T2FMRF_UV", type2FuzzyMRF_UV, img_preProcessor, img_type2FuzzyMRF_UV); if (enableFuzzySugenoIntegral) - process("FuzzySugenoIntegral", fuzzySugenoIntegral, img_prep, img_fsi); + process("FuzzySugenoIntegral", fuzzySugenoIntegral, img_preProcessor, img_fuzzySugenoIntegral); if (enableFuzzyChoquetIntegral) - process("FuzzyChoquetIntegral", fuzzyChoquetIntegral, img_prep, img_fci); + process("FuzzyChoquetIntegral", fuzzyChoquetIntegral, img_preProcessor, img_fuzzyChoquetIntegral); if (enableLBSimpleGaussian) - process("LBSimpleGaussian", lbSimpleGaussian, img_prep, img_lb_sg); + process("LBSimpleGaussian", lbSimpleGaussian, img_preProcessor, img_lbSimpleGaussian); if (enableLBFuzzyGaussian) - process("LBFuzzyGaussian", lbFuzzyGaussian, img_prep, img_lb_fg); + process("LBFuzzyGaussian", lbFuzzyGaussian, img_preProcessor, img_lbFuzzyGaussian); if (enableLBMixtureOfGaussians) - process("LBMixtureOfGaussians", lbMixtureOfGaussians, img_prep, img_lb_mog); + process("LBMixtureOfGaussians", lbMixtureOfGaussians, img_preProcessor, img_lbMixtureOfGaussians); if (enableLBAdaptiveSOM) - process("LBAdaptiveSOM", lbAdaptiveSOM, img_prep, img_lb_som); + process("LBAdaptiveSOM", lbAdaptiveSOM, img_preProcessor, img_lbAdaptiveSOM); if (enableLBFuzzyAdaptiveSOM) - process("LBFuzzyAdaptiveSOM", lbFuzzyAdaptiveSOM, img_prep, img_lb_fsom); + process("LBFuzzyAdaptiveSOM", lbFuzzyAdaptiveSOM, img_preProcessor, img_lbFuzzyAdaptiveSOM); if (enableLbpMrf) - process("LbpMrf", lbpMrf, img_prep, img_lbp_mrf); + process("LbpMrf", lbpMrf, img_preProcessor, img_lbpMrf); - if(enableMultiLayerBGS) +#if CV_MAJOR_VERSION == 2 + if (enableMultiLayer) { - multiLayerBGS->setStatus(MultiLayerBGS::MLBGS_LEARN); - //multiLayerBGS->setStatus(MultiLayerBGS::MLBGS_DETECT); - process("MultiLayerBGS", multiLayerBGS, img_prep, img_mlbgs); + multiLayer->setStatus(MultiLayer::MLBGS_LEARN); + //multiLayer->setStatus(MultiLayer::MLBGS_DETECT); + process("MultiLayer", multiLayer, img_preProcessor, img_multiLayer); } +#endif - //if(enablePBAS) - // process("PBAS", pixelBasedAdaptiveSegmenter, img_prep, img_pt_pbas); + if (enablePBAS) + process("PBAS", pixelBasedAdaptiveSegmenter, img_preProcessor, img_pixelBasedAdaptiveSegmenter); if (enableVuMeter) - process("VuMeter", vuMeter, img_prep, img_vumeter); + process("VuMeter", vuMeter, img_preProcessor, img_vumeter); if (enableKDE) - process("KDE", kde, img_prep, img_kde); + process("KDE", kde, img_preProcessor, img_kde); if (enableIMBS) - process("IMBS", imbs, img_prep, img_imbs); + process("IMBS", imbs, img_preProcessor, img_imbs); - if (enableMultiCueBGS) - process("MultiCueBGS", mcbgs, img_prep, img_mcbgs); + if (enableMultiCue) + process("MultiCue", multiCue, img_preProcessor, img_multiCue); - if (enableSigmaDeltaBGS) - process("SigmaDeltaBGS", sdbgs, img_prep, img_sdbgs); + if (enableSigmaDelta) + process("SigmaDelta", sigmaDelta, img_preProcessor, img_sigmaDelta); - if (enableSuBSENSEBGS) - process("SuBSENSEBGS", ssbgs, img_prep, img_ssbgs); + if (enableSuBSENSE) + process("SuBSENSE", subSENSE, img_preProcessor, img_subSENSE); - if (enableLOBSTERBGS) - process("LOBSTERBGS", lobgs, img_prep, img_lobgs); + if (enableLOBSTER) + process("LOBSTER", lobster, img_preProcessor, img_lobster); if (enableForegroundMaskAnalysis) { foregroundMaskAnalysis->stopAt = frameToStop; foregroundMaskAnalysis->img_ref_path = imgref; - foregroundMaskAnalysis->process(frameNumber, "FrameDifferenceBGS", img_framediff); - foregroundMaskAnalysis->process(frameNumber, "StaticFrameDifferenceBGS", img_staticfdiff); - foregroundMaskAnalysis->process(frameNumber, "WeightedMovingMeanBGS", img_wmovmean); - foregroundMaskAnalysis->process(frameNumber, "WeightedMovingVarianceBGS", img_movvar); - foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV1BGS", img_mog1); - foregroundMaskAnalysis->process(frameNumber, "MixtureOfGaussianV2BGS", img_mog2); - foregroundMaskAnalysis->process(frameNumber, "AdaptiveBackgroundLearning", img_bkgl_fgmask); + 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, "DPAdaptiveMedianBGS", img_adpmed); - foregroundMaskAnalysis->process(frameNumber, "DPGrimsonGMMBGS", img_grigmm); - foregroundMaskAnalysis->process(frameNumber, "DPZivkovicAGMMBGS", img_zivgmm); - foregroundMaskAnalysis->process(frameNumber, "DPMeanBGS", img_tmpmean); - foregroundMaskAnalysis->process(frameNumber, "DPWrenGABGS", img_wrenga); - foregroundMaskAnalysis->process(frameNumber, "DPPratiMediodBGS", img_pramed); - foregroundMaskAnalysis->process(frameNumber, "DPEigenbackgroundBGS", img_eigbkg); - foregroundMaskAnalysis->process(frameNumber, "DPTextureBGS", img_texbgs); - foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UM", img_t2fgmm_um); - foregroundMaskAnalysis->process(frameNumber, "T2FGMM_UV", img_t2fgmm_uv); - foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UM", img_t2fmrf_um); - foregroundMaskAnalysis->process(frameNumber, "T2FMRF_UV", img_t2fmrf_uv); - foregroundMaskAnalysis->process(frameNumber, "FuzzySugenoIntegral", img_fsi); - foregroundMaskAnalysis->process(frameNumber, "FuzzyChoquetIntegral", img_fci); - foregroundMaskAnalysis->process(frameNumber, "LBSimpleGaussian", img_lb_sg); - foregroundMaskAnalysis->process(frameNumber, "LBFuzzyGaussian", img_lb_fg); - foregroundMaskAnalysis->process(frameNumber, "LBMixtureOfGaussians", img_lb_mog); - foregroundMaskAnalysis->process(frameNumber, "LBAdaptiveSOM", img_lb_som); - foregroundMaskAnalysis->process(frameNumber, "LBFuzzyAdaptiveSOM", img_lb_fsom); - foregroundMaskAnalysis->process(frameNumber, "LbpMrf", img_lbp_mrf); - foregroundMaskAnalysis->process(frameNumber, "MultiLayerBGS", img_mlbgs); - //foregroundMaskAnalysis->process(frameNumber, "PBAS", img_pt_pbas); + 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, "MultiCueBGS", img_mcbgs); - foregroundMaskAnalysis->process(frameNumber, "SigmaDeltaBGS", img_sdbgs); - foregroundMaskAnalysis->process(frameNumber, "SuBSENSEBGS", img_ssbgs); - foregroundMaskAnalysis->process(frameNumber, "LOBSTERBGS", img_lobgs); + 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; @@ -341,8 +353,8 @@ namespace bgslibrary void FrameProcessor::finish(void) { - /*if(enableMultiLayerBGS) - multiLayerBGS->finish(); + /*if(enableMultiLayer) + multiLayer->finish(); if(enableLBSimpleGaussian) lbSimpleGaussian->finish(); @@ -362,17 +374,17 @@ namespace bgslibrary if (enableForegroundMaskAnalysis) delete foregroundMaskAnalysis; - if (enableLOBSTERBGS) - delete lobgs; + if (enableLOBSTER) + delete lobster; - if (enableSuBSENSEBGS) - delete ssbgs; + if (enableSuBSENSE) + delete subSENSE; - if (enableSigmaDeltaBGS) - delete sdbgs; + if (enableSigmaDelta) + delete sigmaDelta; - if (enableMultiCueBGS) - delete mcbgs; + if (enableMultiCue) + delete multiCue; if (enableIMBS) delete imbs; @@ -383,11 +395,13 @@ namespace bgslibrary if (enableVuMeter) delete vuMeter; - //if(enablePBAS) - // delete pixelBasedAdaptiveSegmenter; + if (enablePBAS) + delete pixelBasedAdaptiveSegmenter; - if (enableMultiLayerBGS) - delete multiLayerBGS; +#if CV_MAJOR_VERSION == 2 + if (enableMultiLayer) + delete multiLayer; +#endif if (enableLBFuzzyAdaptiveSOM) delete lbFuzzyAdaptiveSOM; @@ -409,7 +423,7 @@ namespace bgslibrary delete lbpMrf; #endif - if(enableFuzzyChoquetIntegral) + if (enableFuzzyChoquetIntegral) delete fuzzyChoquetIntegral; if (enableFuzzySugenoIntegral) @@ -427,29 +441,29 @@ namespace bgslibrary if (enableT2FGMM_UM) delete type2FuzzyGMM_UM; - if (enableDPTextureBGS) - delete textureBGS; + if (enableDPTexture) + delete dpTexture; - if (enableDPEigenbackgroundBGS) - delete eigenBackground; + if (enableDPEigenbackground) + delete dpEigenBackground; - if (enableDPPratiMediodBGS) - delete pratiMediod; + if (enableDPPratiMediod) + delete dpPratiMediod; - if (enableDPWrenGABGS) - delete wrenGA; + if (enableDPWrenGA) + delete dpWrenGA; - if (enableDPMeanBGS) - delete temporalMean; + if (enableDPMean) + delete dpTemporalMean; - if (enableDPZivkovicAGMMBGS) - delete zivkovicAGMM; + if (enableDPZivkovicAGMM) + delete dpZivkovicAGMM; - if (enableDPGrimsonGMMBGS) - delete grimsonGMM; + if (enableDPGrimsonGMM) + delete dpGrimsonGMM; - if (enableDPAdaptiveMedianBGS) - delete adaptiveMedian; + if (enableDPAdaptiveMedian) + delete dpAdaptiveMedian; #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 if (enableGMG) @@ -459,22 +473,24 @@ namespace bgslibrary if (enableAdaptiveBackgroundLearning) delete adaptiveBackgroundLearning; - if (enableMixtureOfGaussianV2BGS) - delete mixtureOfGaussianV2BGS; + if (enableMixtureOfGaussianV2) + delete mixtureOfGaussianV2; - if (enableMixtureOfGaussianV1BGS) - delete mixtureOfGaussianV1BGS; +#if CV_MAJOR_VERSION == 2 + if (enableMixtureOfGaussianV1) + delete mixtureOfGaussianV1; +#endif - if (enableWeightedMovingVarianceBGS) + if (enableWeightedMovingVariance) delete weightedMovingVariance; - if (enableWeightedMovingMeanBGS) + if (enableWeightedMovingMean) delete weightedMovingMean; - if (enableStaticFrameDifferenceBGS) + if (enableStaticFrameDifference) delete staticFrameDifference; - if (enableFrameDifferenceBGS) + if (enableFrameDifference) delete frameDifference; if (enablePreProcessor) @@ -503,25 +519,27 @@ namespace bgslibrary cvWriteInt(fs, "enableForegroundMaskAnalysis", enableForegroundMaskAnalysis); - cvWriteInt(fs, "enableFrameDifferenceBGS", enableFrameDifferenceBGS); - cvWriteInt(fs, "enableStaticFrameDifferenceBGS", enableStaticFrameDifferenceBGS); - cvWriteInt(fs, "enableWeightedMovingMeanBGS", enableWeightedMovingMeanBGS); - cvWriteInt(fs, "enableWeightedMovingVarianceBGS", enableWeightedMovingVarianceBGS); - cvWriteInt(fs, "enableMixtureOfGaussianV1BGS", enableMixtureOfGaussianV1BGS); - cvWriteInt(fs, "enableMixtureOfGaussianV2BGS", enableMixtureOfGaussianV2BGS); + 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, "enableDPAdaptiveMedianBGS", enableDPAdaptiveMedianBGS); - cvWriteInt(fs, "enableDPGrimsonGMMBGS", enableDPGrimsonGMMBGS); - cvWriteInt(fs, "enableDPZivkovicAGMMBGS", enableDPZivkovicAGMMBGS); - cvWriteInt(fs, "enableDPMeanBGS", enableDPMeanBGS); - cvWriteInt(fs, "enableDPWrenGABGS", enableDPWrenGABGS); - cvWriteInt(fs, "enableDPPratiMediodBGS", enableDPPratiMediodBGS); - cvWriteInt(fs, "enableDPEigenbackgroundBGS", enableDPEigenbackgroundBGS); - cvWriteInt(fs, "enableDPTextureBGS", enableDPTextureBGS); + 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); @@ -538,15 +556,17 @@ namespace bgslibrary cvWriteInt(fs, "enableLbpMrf", enableLbpMrf); - cvWriteInt(fs, "enableMultiLayerBGS", enableMultiLayerBGS); - //cvWriteInt(fs, "enablePBAS", enablePBAS); +#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, "enableMultiCueBGS", enableMultiCueBGS); - cvWriteInt(fs, "enableSigmaDeltaBGS", enableSigmaDeltaBGS); - cvWriteInt(fs, "enableSuBSENSEBGS", enableSuBSENSEBGS); - cvWriteInt(fs, "enableLOBSTERBGS", enableLOBSTERBGS); + cvWriteInt(fs, "enableMultiCue", enableMultiCue); + cvWriteInt(fs, "enableSigmaDelta", enableSigmaDelta); + cvWriteInt(fs, "enableSuBSENSE", enableSuBSENSE); + cvWriteInt(fs, "enableLOBSTER", enableLOBSTER); cvReleaseFileStorage(&fs); } @@ -561,25 +581,27 @@ namespace bgslibrary enableForegroundMaskAnalysis = cvReadIntByName(fs, 0, "enableForegroundMaskAnalysis", false); - enableFrameDifferenceBGS = cvReadIntByName(fs, 0, "enableFrameDifferenceBGS", false); - enableStaticFrameDifferenceBGS = cvReadIntByName(fs, 0, "enableStaticFrameDifferenceBGS", false); - enableWeightedMovingMeanBGS = cvReadIntByName(fs, 0, "enableWeightedMovingMeanBGS", false); - enableWeightedMovingVarianceBGS = cvReadIntByName(fs, 0, "enableWeightedMovingVarianceBGS", false); - enableMixtureOfGaussianV1BGS = cvReadIntByName(fs, 0, "enableMixtureOfGaussianV1BGS", false); - enableMixtureOfGaussianV2BGS = cvReadIntByName(fs, 0, "enableMixtureOfGaussianV2BGS", 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 - enableDPAdaptiveMedianBGS = cvReadIntByName(fs, 0, "enableDPAdaptiveMedianBGS", false); - enableDPGrimsonGMMBGS = cvReadIntByName(fs, 0, "enableDPGrimsonGMMBGS", false); - enableDPZivkovicAGMMBGS = cvReadIntByName(fs, 0, "enableDPZivkovicAGMMBGS", false); - enableDPMeanBGS = cvReadIntByName(fs, 0, "enableDPMeanBGS", false); - enableDPWrenGABGS = cvReadIntByName(fs, 0, "enableDPWrenGABGS", false); - enableDPPratiMediodBGS = cvReadIntByName(fs, 0, "enableDPPratiMediodBGS", false); - enableDPEigenbackgroundBGS = cvReadIntByName(fs, 0, "enableDPEigenbackgroundBGS", false); - enableDPTextureBGS = cvReadIntByName(fs, 0, "enableDPTextureBGS", false); + 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); @@ -596,15 +618,17 @@ namespace bgslibrary enableLbpMrf = cvReadIntByName(fs, 0, "enableLbpMrf", false); - enableMultiLayerBGS = cvReadIntByName(fs, 0, "enableMultiLayerBGS", false); - //enablePBAS = cvReadIntByName(fs, 0, "enablePBAS", 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); - enableMultiCueBGS = cvReadIntByName(fs, 0, "enableMultiCueBGS", false); - enableSigmaDeltaBGS = cvReadIntByName(fs, 0, "enableSigmaDeltaBGS", false); - enableSuBSENSEBGS = cvReadIntByName(fs, 0, "enableSuBSENSEBGS", false); - enableLOBSTERBGS = cvReadIntByName(fs, 0, "enableLOBSTERBGS", 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 index 0bb854ee48d5f30285aeb51369ca5646b03eebcd..228fa4c0e8a8b57f0d1a345f0d35700c25a60715 100644 --- a/FrameProcessor.h +++ b/FrameProcessor.h @@ -21,56 +21,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include "PreProcessor.h" #include "package_bgs/IBGS.h" - -#include "package_bgs/FrameDifferenceBGS.h" -#include "package_bgs/StaticFrameDifferenceBGS.h" -#include "package_bgs/WeightedMovingMeanBGS.h" -#include "package_bgs/WeightedMovingVarianceBGS.h" -#include "package_bgs/MixtureOfGaussianV1BGS.h" -#include "package_bgs/MixtureOfGaussianV2BGS.h" -#include "package_bgs/AdaptiveBackgroundLearning.h" -#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 -#include "package_bgs/GMG.h" -#endif - -#include "package_bgs/dp/DPAdaptiveMedianBGS.h" -#include "package_bgs/dp/DPGrimsonGMMBGS.h" -#include "package_bgs/dp/DPZivkovicAGMMBGS.h" -#include "package_bgs/dp/DPMeanBGS.h" -#include "package_bgs/dp/DPWrenGABGS.h" -#include "package_bgs/dp/DPPratiMediodBGS.h" -#include "package_bgs/dp/DPEigenbackgroundBGS.h" -#include "package_bgs/dp/DPTextureBGS.h" - -#include "package_bgs/tb/T2FGMM_UM.h" -#include "package_bgs/tb/T2FGMM_UV.h" -#include "package_bgs/tb/T2FMRF_UM.h" -#include "package_bgs/tb/T2FMRF_UV.h" -#include "package_bgs/tb/FuzzySugenoIntegral.h" -#include "package_bgs/tb/FuzzyChoquetIntegral.h" - -#include "package_bgs/lb/LBSimpleGaussian.h" -#include "package_bgs/lb/LBFuzzyGaussian.h" -#include "package_bgs/lb/LBMixtureOfGaussians.h" -#include "package_bgs/lb/LBAdaptiveSOM.h" -#include "package_bgs/lb/LBFuzzyAdaptiveSOM.h" - -#include "package_bgs/ck/LbpMrf.h" - -#include "package_bgs/jmo/MultiLayerBGS.h" -// The PBAS algorithm was removed from BGSLibrary because it is -// based on patented algorithm ViBE -// http://www2.ulg.ac.be/telecom/research/vibe/ -//#include "package_bgs/pt/PixelBasedAdaptiveSegmenter.h" -#include "package_bgs/av/VuMeter.h" -#include "package_bgs/ae/KDE.h" -#include "package_bgs/db/IndependentMultimodalBGS.h" -#include "package_bgs/sjn/SJN_MultiCueBGS.h" -#include "package_bgs/bl/SigmaDeltaBGS.h" - -#include "package_bgs/pl/SuBSENSE.h" -#include "package_bgs/pl/LOBSTER.h" - +#include "package_bgs/bgslibrary.h" #include "package_analysis/ForegroundMaskAnalysis.h" namespace bgslibrary @@ -84,35 +35,37 @@ namespace bgslibrary double duration; std::string tictoc; - cv::Mat img_prep; + cv::Mat img_preProcessor; PreProcessor* preProcessor; bool enablePreProcessor; - cv::Mat img_framediff; - FrameDifferenceBGS* frameDifference; - bool enableFrameDifferenceBGS; + cv::Mat img_frameDifference; + FrameDifference* frameDifference; + bool enableFrameDifference; - cv::Mat img_staticfdiff; - StaticFrameDifferenceBGS* staticFrameDifference; - bool enableStaticFrameDifferenceBGS; + cv::Mat img_staticFrameDifference; + StaticFrameDifference* staticFrameDifference; + bool enableStaticFrameDifference; - cv::Mat img_wmovmean; - WeightedMovingMeanBGS* weightedMovingMean; - bool enableWeightedMovingMeanBGS; + cv::Mat img_weightedMovingMean; + WeightedMovingMean* weightedMovingMean; + bool enableWeightedMovingMean; - cv::Mat img_movvar; - WeightedMovingVarianceBGS* weightedMovingVariance; - bool enableWeightedMovingVarianceBGS; + cv::Mat img_weightedMovingVariance; + WeightedMovingVariance* weightedMovingVariance; + bool enableWeightedMovingVariance; - cv::Mat img_mog1; - MixtureOfGaussianV1BGS* mixtureOfGaussianV1BGS; - bool enableMixtureOfGaussianV1BGS; +#if CV_MAJOR_VERSION == 2 + cv::Mat img_mixtureOfGaussianV1; + MixtureOfGaussianV1* mixtureOfGaussianV1; + bool enableMixtureOfGaussianV1; +#endif - cv::Mat img_mog2; - MixtureOfGaussianV2BGS* mixtureOfGaussianV2BGS; - bool enableMixtureOfGaussianV2BGS; + cv::Mat img_mixtureOfGaussianV2; + MixtureOfGaussianV2* mixtureOfGaussianV2; + bool enableMixtureOfGaussianV2; - cv::Mat img_bkgl_fgmask; + cv::Mat img_adaptiveBackgroundLearning; AdaptiveBackgroundLearning* adaptiveBackgroundLearning; bool enableAdaptiveBackgroundLearning; @@ -122,93 +75,95 @@ namespace bgslibrary bool enableGMG; #endif - cv::Mat img_adpmed; - DPAdaptiveMedianBGS* adaptiveMedian; - bool enableDPAdaptiveMedianBGS; + cv::Mat img_dpAdaptiveMedian; + DPAdaptiveMedian* dpAdaptiveMedian; + bool enableDPAdaptiveMedian; - cv::Mat img_grigmm; - DPGrimsonGMMBGS* grimsonGMM; - bool enableDPGrimsonGMMBGS; + cv::Mat img_dpGrimsonGMM; + DPGrimsonGMM* dpGrimsonGMM; + bool enableDPGrimsonGMM; - cv::Mat img_zivgmm; - DPZivkovicAGMMBGS* zivkovicAGMM; - bool enableDPZivkovicAGMMBGS; + cv::Mat img_dpZivkovicAGMM; + DPZivkovicAGMM* dpZivkovicAGMM; + bool enableDPZivkovicAGMM; - cv::Mat img_tmpmean; - DPMeanBGS* temporalMean; - bool enableDPMeanBGS; + cv::Mat img_dpTemporalMean; + DPMean* dpTemporalMean; + bool enableDPMean; - cv::Mat img_wrenga; - DPWrenGABGS* wrenGA; - bool enableDPWrenGABGS; + cv::Mat img_dpWrenGA; + DPWrenGA* dpWrenGA; + bool enableDPWrenGA; - cv::Mat img_pramed; - DPPratiMediodBGS* pratiMediod; - bool enableDPPratiMediodBGS; + cv::Mat img_dpPratiMediod; + DPPratiMediod* dpPratiMediod; + bool enableDPPratiMediod; - cv::Mat img_eigbkg; - DPEigenbackgroundBGS* eigenBackground; - bool enableDPEigenbackgroundBGS; + cv::Mat img_dpEigenBackground; + DPEigenbackground* dpEigenBackground; + bool enableDPEigenbackground; - cv::Mat img_texbgs; - DPTextureBGS* textureBGS; - bool enableDPTextureBGS; + cv::Mat img_dpTexture; + DPTexture* dpTexture; + bool enableDPTexture; - cv::Mat img_t2fgmm_um; + cv::Mat img_type2FuzzyGMM_UM; T2FGMM_UM* type2FuzzyGMM_UM; bool enableT2FGMM_UM; - cv::Mat img_t2fgmm_uv; + cv::Mat img_type2FuzzyGMM_UV; T2FGMM_UV* type2FuzzyGMM_UV; bool enableT2FGMM_UV; - cv::Mat img_t2fmrf_um; + cv::Mat img_type2FuzzyMRF_UM; T2FMRF_UM* type2FuzzyMRF_UM; bool enableT2FMRF_UM; - cv::Mat img_t2fmrf_uv; + cv::Mat img_type2FuzzyMRF_UV; T2FMRF_UV* type2FuzzyMRF_UV; bool enableT2FMRF_UV; - cv::Mat img_fsi; + cv::Mat img_fuzzySugenoIntegral; FuzzySugenoIntegral* fuzzySugenoIntegral; bool enableFuzzySugenoIntegral; - cv::Mat img_fci; + cv::Mat img_fuzzyChoquetIntegral; FuzzyChoquetIntegral* fuzzyChoquetIntegral; bool enableFuzzyChoquetIntegral; - cv::Mat img_lb_sg; + cv::Mat img_lbSimpleGaussian; LBSimpleGaussian* lbSimpleGaussian; bool enableLBSimpleGaussian; - cv::Mat img_lb_fg; + cv::Mat img_lbFuzzyGaussian; LBFuzzyGaussian* lbFuzzyGaussian; bool enableLBFuzzyGaussian; - cv::Mat img_lb_mog; + cv::Mat img_lbMixtureOfGaussians; LBMixtureOfGaussians* lbMixtureOfGaussians; bool enableLBMixtureOfGaussians; - cv::Mat img_lb_som; + cv::Mat img_lbAdaptiveSOM; LBAdaptiveSOM* lbAdaptiveSOM; bool enableLBAdaptiveSOM; - cv::Mat img_lb_fsom; + cv::Mat img_lbFuzzyAdaptiveSOM; LBFuzzyAdaptiveSOM* lbFuzzyAdaptiveSOM; bool enableLBFuzzyAdaptiveSOM; - cv::Mat img_lbp_mrf; - LbpMrf* lbpMrf; + cv::Mat img_lbpMrf; + LBP_MRF* lbpMrf; bool enableLbpMrf; - cv::Mat img_mlbgs; - MultiLayerBGS* multiLayerBGS; - bool enableMultiLayerBGS; +#if CV_MAJOR_VERSION == 2 + cv::Mat img_multiLayer; + MultiLayer* multiLayer; + bool enableMultiLayer; +#endif - //cv::Mat img_pt_pbas; - //PixelBasedAdaptiveSegmenter* pixelBasedAdaptiveSegmenter; - //bool enablePBAS; + cv::Mat img_pixelBasedAdaptiveSegmenter; + PixelBasedAdaptiveSegmenter* pixelBasedAdaptiveSegmenter; + bool enablePBAS; cv::Mat img_vumeter; VuMeter* vuMeter; @@ -219,24 +174,24 @@ namespace bgslibrary bool enableKDE; cv::Mat img_imbs; - IndependentMultimodalBGS* imbs; + IndependentMultimodal* imbs; bool enableIMBS; - cv::Mat img_mcbgs; - SJN_MultiCueBGS* mcbgs; - bool enableMultiCueBGS; + cv::Mat img_multiCue; + MultiCue* multiCue; + bool enableMultiCue; - cv::Mat img_sdbgs; - SigmaDeltaBGS* sdbgs; - bool enableSigmaDeltaBGS; + cv::Mat img_sigmaDelta; + SigmaDelta* sigmaDelta; + bool enableSigmaDelta; - cv::Mat img_ssbgs; - SuBSENSEBGS* ssbgs; - bool enableSuBSENSEBGS; + cv::Mat img_subSENSE; + SuBSENSE* subSENSE; + bool enableSuBSENSE; - cv::Mat img_lobgs; - LOBSTERBGS* lobgs; - bool enableLOBSTERBGS; + cv::Mat img_lobster; + LOBSTER* lobster; + bool enableLOBSTER; ForegroundMaskAnalysis* foregroundMaskAnalysis; bool enableForegroundMaskAnalysis; diff --git a/Main.cpp b/Main.cpp index 1d170adf54d9500116d598f2b1e390cb4e21e304..7a406d9a859c56c6603c76f09d48cf08e326fc97 100644 --- a/Main.cpp +++ b/Main.cpp @@ -29,7 +29,7 @@ namespace bgslibrary static void start(int argc, const char **argv) { std::cout << "-----------------------------------------" << std::endl; - std::cout << "Background Subtraction Library v1.9.2 " << 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; diff --git a/PreProcessor.cpp b/PreProcessor.cpp index 6f4ebbe964c197f35c21654d6eeb15e85337a40a..4c13f7e4c3fcd39959b93cb8b6484f45e55e2733 100644 --- a/PreProcessor.cpp +++ b/PreProcessor.cpp @@ -95,7 +95,7 @@ namespace bgslibrary cv2DRotationMatrix(center, angle, 1.0, mapMatrix); cvWarpAffine(image, rotatedImage, mapMatrix, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); - cv::Mat img_rot(rotatedImage); + cv::Mat img_rot = cv::cvarrToMat(rotatedImage); img_rot.copyTo(img_output); cvReleaseImage(&image); diff --git a/PreProcessor.h b/PreProcessor.h index da46cce7e0955e19130499e159707d23f5f721d0..2e6e61c75ddd3d8e21362a83e800fe7ab846db48 100644 --- a/PreProcessor.h +++ b/PreProcessor.h @@ -19,7 +19,6 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - namespace bgslibrary { class PreProcessor diff --git a/README.md b/README.md index a35389ace6bb41579661f3032fc5fd7d05ff0f15..3b8a3cba5c0d19175ddfe3453e7e2a6e27daa0d7 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ A Background Subtraction Library [](https://youtu.be/_UbERwuQ0OU) -Last Page Update: **12/03/2017** +Last Page Update: **18/03/2017** -Latest Library Version: **1.9.2** (see [Release Notes](https://github.com/andrewssobral/bgslibrary/wiki/Release-notes) for more info) +Latest Library Version: **2.0.0** (see [Release Notes](https://github.com/andrewssobral/bgslibrary/wiki/Release-notes) for more info) -The **BGSLibrary** was developed by [Andrews Sobral](http://andrewssobral.wixsite.com/home) and provides an easy-to-use C++ framework based on [OpenCV](http://www.opencv.org/) to perform foreground-background separation in videos. The bgslibrary compiles under Windows, Linux, and Mac OS X. Currently the library contains **37** algorithms. The source code is available under [GNU GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html), the library is free and open source for academic purposes. +The **BGSLibrary** was developed 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. -Note: the BGSLibrary is based on OpenCV 2.X, if you want to use with OpenCV 3.x please check-out our [opencv3](https://github.com/andrewssobral/bgslibrary/tree/opencv3) branch. +***Note: The [opencv3](https://github.com/andrewssobral/bgslibrary/tree/opencv3) branch will be deprecated.*** * [List of available algorithms](https://github.com/andrewssobral/bgslibrary/wiki/List-of-available-algorithms) * [Algorithms benchmark](https://github.com/andrewssobral/bgslibrary/wiki/Algorithms-benchmark) @@ -77,6 +77,7 @@ Some algorithms of the BGSLibrary were used successfully in the following papers * (2013) Sobral, Andrews; Oliveira, Luciano; Schnitman, Leizer; Souza, Felippe. (**Best Paper Award**) Highway Traffic Congestion Classification Using Holistic Properties. In International Conference on Signal Processing, Pattern Recognition and Applications (SPPRA'2013), Innsbruck, Austria, Feb 2013. ([Online](http://dx.doi.org/10.2316/P.2013.798-105)) ([PDF](http://www.researchgate.net/publication/233427564_HIGHWAY_TRAFFIC_CONGESTION_CLASSIFICATION_USING_HOLISTIC_PROPERTIES)) + Videos ------ diff --git a/VideoAnalysis.cpp b/VideoAnalysis.cpp index 1e46542c9124cd69d3cb030659f236564e328d54..9c8020a8c2aef4a16c0bdc36c491d7d7030ba09a 100644 --- a/VideoAnalysis.cpp +++ b/VideoAnalysis.cpp @@ -18,7 +18,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. namespace bgslibrary { - VideoAnalysis::VideoAnalysis() : use_file(false), use_camera(false), cameraIndex(0), use_comp(false), frameToStop(0) + VideoAnalysis::VideoAnalysis() : + use_file(false), use_camera(false), cameraIndex(0), + use_comp(false), frameToStop(0) { std::cout << "VideoAnalysis()" << std::endl; } @@ -32,8 +34,9 @@ namespace bgslibrary { bool flag = false; +#if CV_MAJOR_VERSION == 2 const char* keys = - "{hp|help|false|Print help message}" + "{hp|help|false|Print this message}" "{uf|use_file|false|Use video file}" "{fn|filename||Specify video file}" "{uc|use_cam|false|Use camera}" @@ -42,21 +45,63 @@ namespace bgslibrary "{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 << "Avaible 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; - use_file = cmd.get<bool>("use_file"); if (use_file) { - filename = cmd.get<std::string>("filename"); - if (filename.empty()) { std::cout << "Specify filename" << std::endl; @@ -66,26 +111,15 @@ namespace bgslibrary flag = true; } - use_camera = cmd.get<bool>("use_cam"); if (use_camera) - { - cameraIndex = cmd.get<int>("camera"); flag = true; - } - if (flag == true) + if (flag && use_comp) { - use_comp = cmd.get<bool>("use_comp"); - if (use_comp) + if (imgref.empty()) { - frameToStop = cmd.get<int>("stopAt"); - imgref = cmd.get<std::string>("imgref"); - - if (imgref.empty()) - { - std::cout << "Specify image reference" << std::endl; - return false; - } + std::cout << "Specify image reference" << std::endl; + return false; } } diff --git a/VideoCapture.cpp b/VideoCapture.cpp index 4de5b90f9a1f02eadeba1a7760f40f51c1f996f5..b302a3f5e2921bef2c1424819f244efd5b76ac18 100644 --- a/VideoCapture.cpp +++ b/VideoCapture.cpp @@ -15,6 +15,7 @@ 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> namespace bgslibrary { @@ -74,8 +75,11 @@ 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) + 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) { std::cout << "VideoCapture()" << std::endl; } @@ -101,10 +105,10 @@ namespace bgslibrary void VideoCapture::setUpCamera() { std::cout << "Camera index:" << cameraIndex << std::endl; - capture = cvCaptureFromCAM(cameraIndex); + capture.open(cameraIndex); - if (!capture) - std::cerr << "Cannot open initialize webcam!\n" << std::endl; + if (!capture.isOpened()) + std::cerr << "Cannot initialize webcam!\n" << std::endl; } void VideoCapture::setVideo(std::string filename) @@ -117,10 +121,13 @@ namespace bgslibrary void VideoCapture::setUpVideo() { - capture = cvCaptureFromFile(videoFileName.c_str()); + std::cout << "Openning: " << videoFileName << std::endl; + capture.open(videoFileName.c_str()); - if (!capture) + if (!capture.isOpened()) std::cerr << "Cannot open video file " << videoFileName << std::endl; + else + std::cout << "OK" << std::endl; } void VideoCapture::start() @@ -129,17 +136,21 @@ namespace bgslibrary if (useCamera) setUpCamera(); if (useVideo) setUpVideo(); - if (!capture) std::cerr << "Capture error..." << std::endl; + //if (!capture) std::cerr << "Capture error..." << std::endl; - int input_fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); + int input_fps = capture.get(CV_CAP_PROP_FPS); std::cout << "input->fps:" << input_fps << 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); + 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) @@ -152,13 +163,14 @@ namespace bgslibrary { frameNumber++; - frame1 = cvQueryFrame(capture); - if (!frame1) break; + cv::Mat frame; + capture >> frame; + if (frame.empty()) break; - cvResize(frame1, frame); + //cvResize(frame1, frame); - if (enableFlip) - cvFlip(frame, frame, 0); + //if (enableFlip) + // cvFlip(frame, frame, 0); if (VC_ROI::use_roi == true && VC_ROI::roi_defined == false && firstTime == true) { @@ -166,7 +178,9 @@ namespace bgslibrary do { - cv::Mat img_input(frame); + //cv::Mat img_input = cv::cvarrToMat(frame); + cv::Mat img_input; + frame.copyTo(img_input); if (showOutput) { @@ -202,11 +216,13 @@ namespace bgslibrary if (VC_ROI::use_roi == true && VC_ROI::roi_defined == true) { - CvRect rect = cvRect(VC_ROI::roi_x0, VC_ROI::roi_y0, VC_ROI::roi_x1 - VC_ROI::roi_x0, VC_ROI::roi_y1 - VC_ROI::roi_y0); - cvSetImageROI(frame, rect); + cv::Rect roi(VC_ROI::roi_x0, VC_ROI::roi_y0, VC_ROI::roi_x1 - VC_ROI::roi_x0, VC_ROI::roi_y1 - VC_ROI::roi_y0); + frame = frame(roi); } - cv::Mat img_input(frame); + //cv::Mat img_input = cv::cvarrToMat(frame); + cv::Mat img_input; + frame.copyTo(img_input); if (showOutput) cv::imshow("Input", img_input); @@ -221,7 +237,7 @@ namespace bgslibrary fps = freq / delta_time; //std::cout << "FPS: " << fps << std::endl; - cvResetImageROI(frame); + //cvResetImageROI(frame); key = cvWaitKey(loopDelay); //std::cout << "key: " << key << std::endl; @@ -238,7 +254,7 @@ namespace bgslibrary firstTime = false; } while (1); - cvReleaseCapture(&capture); + capture.release(); } void VideoCapture::saveConfig() diff --git a/VideoCapture.h b/VideoCapture.h index a8ba2ff25017203d9b800006515675ec5766ed7a..0e88c87023b8fedbb4f089e0bf19dfc0222c3d28 100644 --- a/VideoCapture.h +++ b/VideoCapture.h @@ -18,7 +18,8 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - +#include <opencv2/imgproc/imgproc_c.h> +#include <opencv2/imgproc/types_c.h> #include "Config.h" #include "IFrameProcessor.h" @@ -29,7 +30,7 @@ namespace bgslibrary { private: IFrameProcessor* frameProcessor; - CvCapture* capture; + cv::VideoCapture capture; IplImage* frame; int key; int64 start_time; diff --git a/config/FrameProcessor.xml b/config/FrameProcessor.xml index 5155bbf218b7a34466a2ab7b190ed97eac1a5b97..3cf398cc4f421bd0c42bf3a19631c425af5add42 100644 --- a/config/FrameProcessor.xml +++ b/config/FrameProcessor.xml @@ -3,22 +3,22 @@ <tictoc>""</tictoc> <enablePreProcessor>1</enablePreProcessor> <enableForegroundMaskAnalysis>0</enableForegroundMaskAnalysis> -<enableFrameDifferenceBGS>1</enableFrameDifferenceBGS> -<enableStaticFrameDifferenceBGS>0</enableStaticFrameDifferenceBGS> -<enableWeightedMovingMeanBGS>0</enableWeightedMovingMeanBGS> -<enableWeightedMovingVarianceBGS>0</enableWeightedMovingVarianceBGS> -<enableMixtureOfGaussianV1BGS>0</enableMixtureOfGaussianV1BGS> -<enableMixtureOfGaussianV2BGS>0</enableMixtureOfGaussianV2BGS> +<enableFrameDifference>1</enableFrameDifference> +<enableStaticFrameDifference>0</enableStaticFrameDifference> +<enableWeightedMovingMean>0</enableWeightedMovingMean> +<enableWeightedMovingVariance>0</enableWeightedMovingVariance> +<enableMixtureOfGaussianV1>0</enableMixtureOfGaussianV1> +<enableMixtureOfGaussianV2>0</enableMixtureOfGaussianV2> <enableAdaptiveBackgroundLearning>0</enableAdaptiveBackgroundLearning> <enableGMG>0</enableGMG> -<enableDPAdaptiveMedianBGS>0</enableDPAdaptiveMedianBGS> -<enableDPGrimsonGMMBGS>0</enableDPGrimsonGMMBGS> -<enableDPZivkovicAGMMBGS>0</enableDPZivkovicAGMMBGS> -<enableDPMeanBGS>0</enableDPMeanBGS> -<enableDPWrenGABGS>0</enableDPWrenGABGS> -<enableDPPratiMediodBGS>0</enableDPPratiMediodBGS> -<enableDPEigenbackgroundBGS>0</enableDPEigenbackgroundBGS> -<enableDPTextureBGS>0</enableDPTextureBGS> +<enableDPAdaptiveMedian>0</enableDPAdaptiveMedian> +<enableDPGrimsonGMM>0</enableDPGrimsonGMM> +<enableDPZivkovicAGMM>0</enableDPZivkovicAGMM> +<enableDPMean>0</enableDPMean> +<enableDPWrenGA>0</enableDPWrenGA> +<enableDPPratiMediod>0</enableDPPratiMediod> +<enableDPEigenbackground>0</enableDPEigenbackground> +<enableDPTexture>0</enableDPTexture> <enableT2FGMM_UM>0</enableT2FGMM_UM> <enableT2FGMM_UV>0</enableT2FGMM_UV> <enableT2FMRF_UM>0</enableT2FMRF_UM> @@ -31,12 +31,13 @@ <enableLBAdaptiveSOM>0</enableLBAdaptiveSOM> <enableLBFuzzyAdaptiveSOM>0</enableLBFuzzyAdaptiveSOM> <enableLbpMrf>0</enableLbpMrf> -<enableMultiLayerBGS>0</enableMultiLayerBGS> +<enableMultiLayer>0</enableMultiLayer> +<enablePBAS>0</enablePBAS> <enableVuMeter>0</enableVuMeter> <enableKDE>0</enableKDE> <enableIMBS>0</enableIMBS> -<enableMultiCueBGS>0</enableMultiCueBGS> -<enableSigmaDeltaBGS>0</enableSigmaDeltaBGS> -<enableSuBSENSEBGS>0</enableSuBSENSEBGS> -<enableLOBSTERBGS>0</enableLOBSTERBGS> +<enableMultiCue>0</enableMultiCue> +<enableSigmaDelta>0</enableSigmaDelta> +<enableSuBSENSE>0</enableSuBSENSE> +<enableLOBSTER>0</enableLOBSTER> </opencv_storage> diff --git a/dataset/demo.avi b/dataset/demo.avi new file mode 100644 index 0000000000000000000000000000000000000000..df20707af3b0a2cbcaaae127b982e1886b1d2aa7 Binary files /dev/null and b/dataset/demo.avi differ diff --git a/frames/1.png b/dataset/frames/1.png similarity index 100% rename from frames/1.png rename to dataset/frames/1.png diff --git a/frames/10.png b/dataset/frames/10.png similarity index 100% rename from frames/10.png rename to dataset/frames/10.png diff --git a/frames/11.png b/dataset/frames/11.png similarity index 100% rename from frames/11.png rename to dataset/frames/11.png diff --git a/frames/12.png b/dataset/frames/12.png similarity index 100% rename from frames/12.png rename to dataset/frames/12.png diff --git a/frames/13.png b/dataset/frames/13.png similarity index 100% rename from frames/13.png rename to dataset/frames/13.png diff --git a/frames/14.png b/dataset/frames/14.png similarity index 100% rename from frames/14.png rename to dataset/frames/14.png diff --git a/frames/15.png b/dataset/frames/15.png similarity index 100% rename from frames/15.png rename to dataset/frames/15.png diff --git a/frames/16.png b/dataset/frames/16.png similarity index 100% rename from frames/16.png rename to dataset/frames/16.png diff --git a/frames/17.png b/dataset/frames/17.png similarity index 100% rename from frames/17.png rename to dataset/frames/17.png diff --git a/frames/18.png b/dataset/frames/18.png similarity index 100% rename from frames/18.png rename to dataset/frames/18.png diff --git a/frames/19.png b/dataset/frames/19.png similarity index 100% rename from frames/19.png rename to dataset/frames/19.png diff --git a/frames/2.png b/dataset/frames/2.png similarity index 100% rename from frames/2.png rename to dataset/frames/2.png diff --git a/frames/20.png b/dataset/frames/20.png similarity index 100% rename from frames/20.png rename to dataset/frames/20.png diff --git a/frames/21.png b/dataset/frames/21.png similarity index 100% rename from frames/21.png rename to dataset/frames/21.png diff --git a/frames/22.png b/dataset/frames/22.png similarity index 100% rename from frames/22.png rename to dataset/frames/22.png diff --git a/frames/23.png b/dataset/frames/23.png similarity index 100% rename from frames/23.png rename to dataset/frames/23.png diff --git a/frames/24.png b/dataset/frames/24.png similarity index 100% rename from frames/24.png rename to dataset/frames/24.png diff --git a/frames/25.png b/dataset/frames/25.png similarity index 100% rename from frames/25.png rename to dataset/frames/25.png diff --git a/frames/26.png b/dataset/frames/26.png similarity index 100% rename from frames/26.png rename to dataset/frames/26.png diff --git a/frames/27.png b/dataset/frames/27.png similarity index 100% rename from frames/27.png rename to dataset/frames/27.png diff --git a/frames/28.png b/dataset/frames/28.png similarity index 100% rename from frames/28.png rename to dataset/frames/28.png diff --git a/frames/29.png b/dataset/frames/29.png similarity index 100% rename from frames/29.png rename to dataset/frames/29.png diff --git a/frames/3.png b/dataset/frames/3.png similarity index 100% rename from frames/3.png rename to dataset/frames/3.png diff --git a/frames/30.png b/dataset/frames/30.png similarity index 100% rename from frames/30.png rename to dataset/frames/30.png diff --git a/frames/31.png b/dataset/frames/31.png similarity index 100% rename from frames/31.png rename to dataset/frames/31.png diff --git a/frames/32.png b/dataset/frames/32.png similarity index 100% rename from frames/32.png rename to dataset/frames/32.png diff --git a/frames/33.png b/dataset/frames/33.png similarity index 100% rename from frames/33.png rename to dataset/frames/33.png diff --git a/frames/34.png b/dataset/frames/34.png similarity index 100% rename from frames/34.png rename to dataset/frames/34.png diff --git a/frames/35.png b/dataset/frames/35.png similarity index 100% rename from frames/35.png rename to dataset/frames/35.png diff --git a/frames/36.png b/dataset/frames/36.png similarity index 100% rename from frames/36.png rename to dataset/frames/36.png diff --git a/frames/37.png b/dataset/frames/37.png similarity index 100% rename from frames/37.png rename to dataset/frames/37.png diff --git a/frames/38.png b/dataset/frames/38.png similarity index 100% rename from frames/38.png rename to dataset/frames/38.png diff --git a/frames/39.png b/dataset/frames/39.png similarity index 100% rename from frames/39.png rename to dataset/frames/39.png diff --git a/frames/4.png b/dataset/frames/4.png similarity index 100% rename from frames/4.png rename to dataset/frames/4.png diff --git a/frames/40.png b/dataset/frames/40.png similarity index 100% rename from frames/40.png rename to dataset/frames/40.png diff --git a/frames/41.png b/dataset/frames/41.png similarity index 100% rename from frames/41.png rename to dataset/frames/41.png diff --git a/frames/42.png b/dataset/frames/42.png similarity index 100% rename from frames/42.png rename to dataset/frames/42.png diff --git a/frames/43.png b/dataset/frames/43.png similarity index 100% rename from frames/43.png rename to dataset/frames/43.png diff --git a/frames/44.png b/dataset/frames/44.png similarity index 100% rename from frames/44.png rename to dataset/frames/44.png diff --git a/frames/45.png b/dataset/frames/45.png similarity index 100% rename from frames/45.png rename to dataset/frames/45.png diff --git a/frames/46.png b/dataset/frames/46.png similarity index 100% rename from frames/46.png rename to dataset/frames/46.png diff --git a/frames/47.png b/dataset/frames/47.png similarity index 100% rename from frames/47.png rename to dataset/frames/47.png diff --git a/frames/48.png b/dataset/frames/48.png similarity index 100% rename from frames/48.png rename to dataset/frames/48.png diff --git a/frames/49.png b/dataset/frames/49.png similarity index 100% rename from frames/49.png rename to dataset/frames/49.png diff --git a/frames/5.png b/dataset/frames/5.png similarity index 100% rename from frames/5.png rename to dataset/frames/5.png diff --git a/frames/50.png b/dataset/frames/50.png similarity index 100% rename from frames/50.png rename to dataset/frames/50.png diff --git a/frames/51.png b/dataset/frames/51.png similarity index 100% rename from frames/51.png rename to dataset/frames/51.png diff --git a/frames/6.png b/dataset/frames/6.png similarity index 100% rename from frames/6.png rename to dataset/frames/6.png diff --git a/frames/7.png b/dataset/frames/7.png similarity index 100% rename from frames/7.png rename to dataset/frames/7.png diff --git a/frames/8.png b/dataset/frames/8.png similarity index 100% rename from frames/8.png rename to dataset/frames/8.png diff --git a/frames/9.png b/dataset/frames/9.png similarity index 100% rename from frames/9.png rename to dataset/frames/9.png diff --git a/demos/DemoFrameDifferenceBGS.cpp b/demos/DemoFrameDifferenceBGS.cpp deleted file mode 100644 index 5a449e21dda93981e91b1a4758bb8247882cb897..0000000000000000000000000000000000000000 --- a/demos/DemoFrameDifferenceBGS.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "package_bgs/FrameDifferenceBGS.h" - -int main(int argc, char **argv) -{ - CvCapture *capture = 0; - - capture = cvCaptureFromCAM(0); - //capture = cvCaptureFromAVI("video.avi"); - - if(!capture){ - std::cerr << "Cannot open initialize webcam!" << std::endl; - return 1; - } - - IplImage *frame = cvQueryFrame(capture); - - FrameDifferenceBGS* bgs = new FrameDifferenceBGS; - - int key = 0; - while(key != 'q') - { - frame = cvQueryFrame(capture); - - if(!frame) break; - - cv::Mat img_input(frame,true); - cv::resize(img_input,img_input,cv::Size(320,240)); - cv::imshow("input", img_input); - - cv::Mat img_mask; - bgs->process(img_input, img_mask); // automatically shows the foreground mask image - - //if(!img_mask.empty()) - // do something - - key = cvWaitKey(1); - } - - delete bgs; - - cvDestroyAllWindows(); - cvReleaseCapture(&capture); - - return 0; -} diff --git a/demos/DemoMultiLayerBGS.cpp b/demos/DemoMultiLayerBGS.cpp deleted file mode 100644 index 08abe30df39d937e8210c1311fa5a89976d6fe1d..0000000000000000000000000000000000000000 --- a/demos/DemoMultiLayerBGS.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "package_bgs/jmo/MultiLayerBGS.h" - -int main(int argc, char **argv) -{ - CvCapture *capture = 0; - - capture = cvCaptureFromCAM(0); - //capture = cvCaptureFromAVI("video.avi"); - - if(!capture){ - std::cerr << "Cannot open initialize webcam!" << std::endl; - return 1; - } - - IplImage *frame = cvQueryFrame(capture); - - MultiLayerBGS* bgs = new MultiLayerBGS; - - int key = 0; - while(key != 'q') - { - frame = cvQueryFrame(capture); - - if(!frame) break; - - cv::Mat img_input(frame,true); - cv::resize(img_input,img_input,cv::Size(320,240)); - cv::imshow("input", img_input); - - cv::Mat img_mask; - bgs->process(img_input, img_mask); // automatically shows the foreground mask image - - //if(!img_mask.empty()) - // do something - - key = cvWaitKey(1); - } - - delete bgs; - - cvDestroyAllWindows(); - cvReleaseCapture(&capture); - - return 0; -} diff --git a/demos/linux_ubuntu/.gitignore b/demos/linux_ubuntu/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..46d4288c817cdfd5c83571222c2c43e4674d6c32 --- /dev/null +++ b/demos/linux_ubuntu/.gitignore @@ -0,0 +1,8 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore +!CMakeLists.txt +!FrameDifferenceTest.cpp +!README.txt +!config/ diff --git a/example_linux/CMakeLists.txt b/demos/linux_ubuntu/CMakeLists.txt similarity index 66% rename from example_linux/CMakeLists.txt rename to demos/linux_ubuntu/CMakeLists.txt index 9317e55f501298c9035145675a6f84a5e22366ff..8cc38e8852cd8facf728c49ca358e6a641feacd2 100644 --- a/example_linux/CMakeLists.txt +++ b/demos/linux_ubuntu/CMakeLists.txt @@ -9,15 +9,14 @@ find_package(OpenCV REQUIRED) file(GLOB source FrameDifferenceTest.cpp) -file(GLOB_RECURSE bgs_src ../package_bgs/*.cpp ../package_bgs/*.c) -file(GLOB_RECURSE bgs_include ../package_bgs/*.h) +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_include}) +set_property(TARGET bgs PROPERTY PUBLIC_HEADER ${bgs_inc}) add_executable(FrameDifferenceTest ${source}) target_link_libraries(FrameDifferenceTest ${OpenCV_LIBS} bgs) - diff --git a/example_macosx/FrameDifferenceTest.cpp b/demos/linux_ubuntu/FrameDifferenceTest.cpp similarity index 87% rename from example_macosx/FrameDifferenceTest.cpp rename to demos/linux_ubuntu/FrameDifferenceTest.cpp index 56f1e7cb3cc0c620bb0cdc2c1ca90a2725089a58..7ebe8b1aa19ef3495d0cf57868340577a83f9134 100644 --- a/example_macosx/FrameDifferenceTest.cpp +++ b/demos/linux_ubuntu/FrameDifferenceTest.cpp @@ -2,7 +2,9 @@ #include <cv.h> #include <highgui.h> -#include "../package_bgs/FrameDifferenceBGS.h" +#include "../../package_bgs/FrameDifference.h" + +using namespace bgslibrary::algorithms; int main(int argc, char **argv) { @@ -15,7 +17,7 @@ int main(int argc, char **argv) } IBGS *bgs; - bgs = new FrameDifferenceBGS; + bgs = new FrameDifference; IplImage *frame; while(1) diff --git a/example_linux/README.txt b/demos/linux_ubuntu/README.txt similarity index 100% rename from example_linux/README.txt rename to demos/linux_ubuntu/README.txt diff --git a/demos/linux_ubuntu/config/.gitignore b/demos/linux_ubuntu/config/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8ee04a01eb210a035d02f190538c5235aebc7277 --- /dev/null +++ b/demos/linux_ubuntu/config/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore \ No newline at end of file diff --git a/demos/macosx/.gitignore b/demos/macosx/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..46d4288c817cdfd5c83571222c2c43e4674d6c32 --- /dev/null +++ b/demos/macosx/.gitignore @@ -0,0 +1,8 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore +!CMakeLists.txt +!FrameDifferenceTest.cpp +!README.txt +!config/ diff --git a/example_macosx/CMakeLists.txt b/demos/macosx/CMakeLists.txt similarity index 79% rename from example_macosx/CMakeLists.txt rename to demos/macosx/CMakeLists.txt index 107303fdf769fda32d152e24c25343e9b24cd12a..a9775d850e56c7d5aa6669ae652980394f95a968 100644 --- a/example_macosx/CMakeLists.txt +++ b/demos/macosx/CMakeLists.txt @@ -20,15 +20,14 @@ find_package(OpenCV REQUIRED) file(GLOB source FrameDifferenceTest.cpp) -file(GLOB_RECURSE bgs_src ../package_bgs/*.cpp ../package_bgs/*.c) -file(GLOB_RECURSE bgs_include ../package_bgs/*.h) +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_include}) +set_property(TARGET bgs PROPERTY PUBLIC_HEADER ${bgs_inc}) add_executable(FrameDifferenceTest ${source}) target_link_libraries(FrameDifferenceTest ${OpenCV_LIBS} bgs) - diff --git a/example_linux/FrameDifferenceTest.cpp b/demos/macosx/FrameDifferenceTest.cpp similarity index 87% rename from example_linux/FrameDifferenceTest.cpp rename to demos/macosx/FrameDifferenceTest.cpp index 56f1e7cb3cc0c620bb0cdc2c1ca90a2725089a58..7ebe8b1aa19ef3495d0cf57868340577a83f9134 100644 --- a/example_linux/FrameDifferenceTest.cpp +++ b/demos/macosx/FrameDifferenceTest.cpp @@ -2,7 +2,9 @@ #include <cv.h> #include <highgui.h> -#include "../package_bgs/FrameDifferenceBGS.h" +#include "../../package_bgs/FrameDifference.h" + +using namespace bgslibrary::algorithms; int main(int argc, char **argv) { @@ -15,7 +17,7 @@ int main(int argc, char **argv) } IBGS *bgs; - bgs = new FrameDifferenceBGS; + bgs = new FrameDifference; IplImage *frame; while(1) diff --git a/example_macosx/README.txt b/demos/macosx/README.txt similarity index 100% rename from example_macosx/README.txt rename to demos/macosx/README.txt diff --git a/demos/macosx/config/.gitignore b/demos/macosx/config/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8ee04a01eb210a035d02f190538c5235aebc7277 --- /dev/null +++ b/demos/macosx/config/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore \ No newline at end of file diff --git a/README_CMAKE_USERS.txt b/docs/README_CMAKE_USERS_OPENCV2.txt similarity index 70% rename from README_CMAKE_USERS.txt rename to docs/README_CMAKE_USERS_OPENCV2.txt index 974e9416be37091a476b1c2f8421cb0e0e561097..26c69979c2b2f0d4610f1c8f903a7a9122f9f4db 100644 --- a/README_CMAKE_USERS.txt +++ b/docs/README_CMAKE_USERS_OPENCV2.txt @@ -15,18 +15,17 @@ Please follow the instructions below: 1) Go to Windows console. 2) Clone BGSLibrary git repository: -e.g.: git clone https://github.com/andrewssobral/bgslibrary.git +git clone https://github.com/andrewssobral/bgslibrary.git 3) Go to bgslibrary/build folder. -e.g.: C:\bgslibrary\build>_ -2) Set your OpenCV PATH: -e.g.: -\> setlocal -\> set OpenCV_DIR=C:\OpenCV2.4.10\build -\> cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 12" .. -or: -\> cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 12 Win64" .. +4) Set your OpenCV PATH: +setlocal +set OpenCV_DIR=C:\OpenCV2.4.10\build + +5) Launch CMAKE: +(For Windows x86 32bits) cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 12" .. +(For Windows x64 64bits) cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 12 Win64" .. Now, you will see something like (for win64): ------------------------------------------------- @@ -52,27 +51,25 @@ Now, you will see something like (for win64): -- Build files have been written to: C:/bgslibrary/build ------------------------------------------------- -3) Include OpenCV binaries in the system path: -\> set PATH=%PATH%;%OpenCV_DIR%\x86\vc12\bin -or: -\> set PATH=%PATH%;%OpenCV_DIR%\x64\vc12\bin +6) Include OpenCV binaries in the system path: +(For Windows x86 32bits) set PATH=%PATH%;%OpenCV_DIR%\x86\vc12\bin +(For Windows x64 64bits) set PATH=%PATH%;%OpenCV_DIR%\x64\vc12\bin -4) Open 'bgs.sln' in Visual Studio and switch to 'RELEASE' mode -4.1) Note if you are using a Visual Studio version superior than 2013, you will need to CANCEL the project wizard update. However, you can go to step (2) and change the Visual Studio version, e.g.: -G "Visual Studio XX", where XX is your Visual Studio version. +7) Open 'bgs.sln' in Visual Studio and switch to 'RELEASE' mode +7.1) Note if you are using a Visual Studio version superior than 2013, you will need to CANCEL the project wizard update. However, you can go to step (5) and change the Visual Studio version, e.g.: -G "Visual Studio XX", where XX is your Visual Studio version. -5) Click on 'ALL_BUILD' project and build! +8) Click on 'ALL_BUILD' project and build! -6) If everything goes well, you can run bgslibrary in the Windows console as follows: +9) If everything goes well, you can run bgslibrary in the Windows console as follows: -6.1) Running BGSLibrary with a webcamera: +9.1) Running BGSLibrary with a webcamera: C:\bgslibrary> build\bgslibrary.exe --use_cam --camera=0 -6.2) Running demo code: +9.2) Running demo code: C:\bgslibrary> build\bgs_demo.exe dataset/video.avi -6.3) Running demo2 code: +9.3) Running demo2 code: C:\bgslibrary> build\bgs_demo2.exe Additional information: * Note that bgslibrary requires a 'config' folder in the working directory. -e.g.: C:\bgslibrary\config diff --git a/docs/README_CMAKE_USERS_OPENCV3.txt b/docs/README_CMAKE_USERS_OPENCV3.txt new file mode 100644 index 0000000000000000000000000000000000000000..543fd86e39395c308cf8be8cf290fb92329c47bd --- /dev/null +++ b/docs/README_CMAKE_USERS_OPENCV3.txt @@ -0,0 +1,77 @@ +------------------------------------------------- +-------------- WINDOWS CMAKE USERS -------------- + +How to build BGSLibrary with OpenCV 3.2.0 and Visual Studio 2015 from CMAKE. + +For Linux users, please see the instruction in README_LINUX_USERS.txt file. + +Dependencies: +* GIT (tested with git version 2.7.2.windows.1). +* CMAKE for Windows (tested with cmake version 3.1.1). +* Microsoft Visual Studio (tested with VS2015). + +Please follow the instructions below: + +1) Go to Windows console. + +2) Clone BGSLibrary git repository: +git clone https://github.com/andrewssobral/bgslibrary.git + +3) Go to bgslibrary/build folder. + +4) Set your OpenCV PATH: +setlocal +set OpenCV_DIR=C:\OpenCV3.2.0\build + +5) Launch CMAKE: +cmake -DOpenCV_DIR=%OpenCV_DIR% -G "Visual Studio 14 Win64" .. + +Now, you will see something like: +------------------------------------------------- +-- The C compiler identification is MSVC 19.0.24215.1 +-- The CXX compiler identification is MSVC 19.0.24215.1 +-- Check for working C compiler using: Visual Studio 14 2015 Win64 +-- Check for working C compiler using: Visual Studio 14 2015 Win64 -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working CXX compiler using: Visual Studio 14 2015 Win64 +-- Check for working CXX compiler using: Visual Studio 14 2015 Win64 -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- OpenCV ARCH: x64 +-- OpenCV RUNTIME: vc14 +-- OpenCV STATIC: ON +-- Found OpenCV 3.2.0 in C:/OpenCV3.2.0/build/x64/vc14/lib +-- You might need to add C:\OpenCV3.2.0\build\x64\vc14\bin to your PATH to be able to run your applications. +-- OpenCV library status: +-- version: 3.2.0 +-- libraries: opencv_world;opencv_videostab;opencv_videoio;opencv_video;opencv_superres;opencv_stitching;opencv_shape;opencv_photo;opencv_objdetect;opencv_ml;opencv_imgproc;opencv_imgcodecs;opencv_highgui;opencv_flann;opencv_features2d;opencv_core;opencv_calib3d +-- include path: C:/OpenCV3.2.0/build/include;C:/OpenCV3.2.0/build/include/opencv +-- Configuring done +-- Generating done +-- Build files have been written to: C:/bgslibrary/build +------------------------------------------------- + +6) Include OpenCV binaries in the system path: +set PATH=%PATH%;%OpenCV_DIR%\x64\vc14\bin + +7) Open 'bgs.sln' in Visual Studio and switch to 'RELEASE' mode +7.1) Note if you are using a Visual Studio version superior than 2015, you will need to CANCEL the project wizard update. However, you can go to step (2) and change the Visual Studio version, e.g.: -G "Visual Studio XX", where XX is your Visual Studio version. + +8) Click on 'ALL_BUILD' project and build! + +9) If everything goes well, you can run bgslibrary in the Windows console as follows: + +9.1) Running BGSLibrary with a webcamera: +C:\bgslibrary> build\bgslibrary.exe --use_cam --camera=0 + +9.2) Running demo code: +C:\bgslibrary> build\bgs_demo.exe dataset/video.avi + +9.3) Running demo2 code: +C:\bgslibrary> build\bgs_demo2.exe + +Additional information: +* Note that bgslibrary requires a 'config' folder in the working directory. diff --git a/README_LINUX_USERS.txt b/docs/README_LINUX_USERS.txt similarity index 85% rename from README_LINUX_USERS.txt rename to docs/README_LINUX_USERS.txt index 5a2611faf296d01262d99bd5150900fc0000f35e..9482f33d3fe8210430eee55ad22080019a526d52 100644 --- a/README_LINUX_USERS.txt +++ b/docs/README_LINUX_USERS.txt @@ -4,6 +4,8 @@ # Requirements: # cmake >= 2.8 # opencv >= 2.3.1 +# +# Tested with: Ubuntu 14.04 and Ubuntu 16.04 cd build cmake .. @@ -17,7 +19,8 @@ export LD_LIBRARY_PATH # Now you can run bgslibrary by: bgs -i video.avi ######################## cd .. -chmod +x run_video.sh run_camera.sh run_demo.sh +chmod +x *.sh ./run_video.sh ./run_camera.sh ./run_demo.sh +./run_demo2.sh diff --git a/README_VISUAL_STUDIO_USERS.txt b/docs/README_VS2010_OPENCV2.txt similarity index 81% rename from README_VISUAL_STUDIO_USERS.txt rename to docs/README_VS2010_OPENCV2.txt index ee9fe126b80f698ba647cbb2d2b8e3b787747964..66ee0f43ec69342dc5dd051af18baf390a091850 100644 --- a/README_VISUAL_STUDIO_USERS.txt +++ b/docs/README_VS2010_OPENCV2.txt @@ -1,16 +1,13 @@ --------------------------------------------------- BGSLibrary with Visual Studio 2010 and Opencv 2.4.x --------------------------------------------------- - -1) Clone our VS2010 example project at [vs2010] folder -https://github.com/andrewssobral/bgslibrary/tree/master/vs2010 - -Or configure manually by: +--- Tutorial for Windows x86 32 bits --- +---------------------------------------- 1) Install OpenCV 1.a) Download OpenCV 2.4.x from http://opencv.org/ -2.b) Install in: C:\OpenCV2.4.x -2.c) Add OpenCV binaries in your Path +1.b) Install in: C:\OpenCV2.4.x +1.c) Add OpenCV binaries in your Path C:\OpenCV2.4.x\build\x86\vc10\bin 2) Download BGSLibrary @@ -22,7 +19,7 @@ C:\OpenCV2.4.x\build\x86\vc10\bin 3.c) Set project location: C:\bgslibrary 3.d) Set project name: bgslibrary 3.e) Set Empty project -3.f) Add Demo.cpp in [Source Files] +3.f) Add Main.cpp in [Source Files] 3.g) Add content of c:\bgslibrary\package_bgs\*.* in [Header Files] 3.h) Add content of c:\bgslibrary\package_analysis\*.* in [Header Files] 3.i) Change to [Release] [Win32] mode diff --git a/example_linux/config/KEEP_THIS_FOLDER b/example_linux/config/KEEP_THIS_FOLDER deleted file mode 100644 index 24353bcb3c57d58895a3c2500232445466fabd6b..0000000000000000000000000000000000000000 --- a/example_linux/config/KEEP_THIS_FOLDER +++ /dev/null @@ -1 +0,0 @@ -bgslibrary uses this folder to store the configuration files \ No newline at end of file diff --git a/example_macosx/config/KEEP_THIS_FOLDER b/example_macosx/config/KEEP_THIS_FOLDER deleted file mode 100644 index 24353bcb3c57d58895a3c2500232445466fabd6b..0000000000000000000000000000000000000000 --- a/example_macosx/config/KEEP_THIS_FOLDER +++ /dev/null @@ -1 +0,0 @@ -bgslibrary uses this folder to store the configuration files \ No newline at end of file diff --git a/java_gui/README.txt b/gui_java/README.txt similarity index 100% rename from java_gui/README.txt rename to gui_java/README.txt diff --git a/java_gui/_COPY_bgslibrary.exe_HERE_ b/gui_java/_COPY_bgslibrary.exe_HERE_ similarity index 100% rename from java_gui/_COPY_bgslibrary.exe_HERE_ rename to gui_java/_COPY_bgslibrary.exe_HERE_ diff --git a/java_gui/bgslibrary_gui.jar b/gui_java/bgslibrary_gui.jar similarity index 100% rename from java_gui/bgslibrary_gui.jar rename to gui_java/bgslibrary_gui.jar diff --git a/java_gui/bgslibrary_gui.properties b/gui_java/bgslibrary_gui.properties similarity index 100% rename from java_gui/bgslibrary_gui.properties rename to gui_java/bgslibrary_gui.properties diff --git a/java_gui/build.xml b/gui_java/build.xml similarity index 100% rename from java_gui/build.xml rename to gui_java/build.xml diff --git a/java_gui/config/.gitignore b/gui_java/config/.gitignore similarity index 100% rename from java_gui/config/.gitignore rename to gui_java/config/.gitignore diff --git a/java_gui/config/FrameProcessor.xml b/gui_java/config/FrameProcessor.xml similarity index 100% rename from java_gui/config/FrameProcessor.xml rename to gui_java/config/FrameProcessor.xml diff --git a/java_gui/config/PreProcessor.xml b/gui_java/config/PreProcessor.xml similarity index 100% rename from java_gui/config/PreProcessor.xml rename to gui_java/config/PreProcessor.xml diff --git a/java_gui/config/VideoCapture.xml b/gui_java/config/VideoCapture.xml similarity index 100% rename from java_gui/config/VideoCapture.xml rename to gui_java/config/VideoCapture.xml diff --git a/java_gui/images/bgslibrary_gui_screen01.png b/gui_java/images/bgslibrary_gui_screen01.png similarity index 100% rename from java_gui/images/bgslibrary_gui_screen01.png rename to gui_java/images/bgslibrary_gui_screen01.png diff --git a/java_gui/images/bgslibrary_gui_screen02.png b/gui_java/images/bgslibrary_gui_screen02.png similarity index 100% rename from java_gui/images/bgslibrary_gui_screen02.png rename to gui_java/images/bgslibrary_gui_screen02.png diff --git a/java_gui/images/bgslibrary_gui_screen03.png b/gui_java/images/bgslibrary_gui_screen03.png similarity index 100% rename from java_gui/images/bgslibrary_gui_screen03.png rename to gui_java/images/bgslibrary_gui_screen03.png diff --git a/java_gui/images/bgslibrary_gui_screen04.png b/gui_java/images/bgslibrary_gui_screen04.png similarity index 100% rename from java_gui/images/bgslibrary_gui_screen04.png rename to gui_java/images/bgslibrary_gui_screen04.png diff --git a/java_gui/images/logo.jpg b/gui_java/images/logo.jpg similarity index 100% rename from java_gui/images/logo.jpg rename to gui_java/images/logo.jpg diff --git a/java_gui/lib/commons-configuration-1.8.jar b/gui_java/lib/commons-configuration-1.8.jar similarity index 100% rename from java_gui/lib/commons-configuration-1.8.jar rename to gui_java/lib/commons-configuration-1.8.jar diff --git a/java_gui/lib/commons-io-2.3.jar b/gui_java/lib/commons-io-2.3.jar similarity index 100% rename from java_gui/lib/commons-io-2.3.jar rename to gui_java/lib/commons-io-2.3.jar diff --git a/java_gui/lib/commons-lang-2.6.jar b/gui_java/lib/commons-lang-2.6.jar similarity index 100% rename from java_gui/lib/commons-lang-2.6.jar rename to gui_java/lib/commons-lang-2.6.jar diff --git a/java_gui/lib/commons-logging-1.1.1.jar b/gui_java/lib/commons-logging-1.1.1.jar similarity index 100% rename from java_gui/lib/commons-logging-1.1.1.jar rename to gui_java/lib/commons-logging-1.1.1.jar diff --git a/java_gui/lib/swingx-all-1.6.3.jar b/gui_java/lib/swingx-all-1.6.3.jar similarity index 100% rename from java_gui/lib/swingx-all-1.6.3.jar rename to gui_java/lib/swingx-all-1.6.3.jar diff --git a/java_gui/lib/swingx-beaninfo-1.6.3.jar b/gui_java/lib/swingx-beaninfo-1.6.3.jar similarity index 100% rename from java_gui/lib/swingx-beaninfo-1.6.3.jar rename to gui_java/lib/swingx-beaninfo-1.6.3.jar diff --git a/java_gui/manifest.mf b/gui_java/manifest.mf similarity index 100% rename from java_gui/manifest.mf rename to gui_java/manifest.mf diff --git a/java_gui/nbproject/build-impl.xml b/gui_java/nbproject/build-impl.xml similarity index 100% rename from java_gui/nbproject/build-impl.xml rename to gui_java/nbproject/build-impl.xml diff --git a/java_gui/nbproject/genfiles.properties b/gui_java/nbproject/genfiles.properties similarity index 100% rename from java_gui/nbproject/genfiles.properties rename to gui_java/nbproject/genfiles.properties diff --git a/java_gui/nbproject/private/config.properties b/gui_java/nbproject/private/config.properties similarity index 100% rename from java_gui/nbproject/private/config.properties rename to gui_java/nbproject/private/config.properties diff --git a/java_gui/nbproject/private/private.properties b/gui_java/nbproject/private/private.properties similarity index 100% rename from java_gui/nbproject/private/private.properties rename to gui_java/nbproject/private/private.properties diff --git a/java_gui/nbproject/private/private.xml b/gui_java/nbproject/private/private.xml similarity index 100% rename from java_gui/nbproject/private/private.xml rename to gui_java/nbproject/private/private.xml diff --git a/java_gui/nbproject/project.properties b/gui_java/nbproject/project.properties similarity index 100% rename from java_gui/nbproject/project.properties rename to gui_java/nbproject/project.properties diff --git a/java_gui/nbproject/project.xml b/gui_java/nbproject/project.xml similarity index 100% rename from java_gui/nbproject/project.xml rename to gui_java/nbproject/project.xml diff --git a/java_gui/run_camera.bat b/gui_java/run_camera.bat similarity index 100% rename from java_gui/run_camera.bat rename to gui_java/run_camera.bat diff --git a/java_gui/run_java_gui.bat b/gui_java/run_java_gui.bat similarity index 100% rename from java_gui/run_java_gui.bat rename to gui_java/run_java_gui.bat diff --git a/java_gui/run_java_gui_with_console.bat b/gui_java/run_java_gui_with_console.bat similarity index 100% rename from java_gui/run_java_gui_with_console.bat rename to gui_java/run_java_gui_with_console.bat diff --git a/java_gui/run_video.bat b/gui_java/run_video.bat similarity index 100% rename from java_gui/run_video.bat rename to gui_java/run_video.bat diff --git a/java_gui/src/br/com/bgslibrary/Main.java b/gui_java/src/br/com/bgslibrary/Main.java similarity index 100% rename from java_gui/src/br/com/bgslibrary/Main.java rename to gui_java/src/br/com/bgslibrary/Main.java diff --git a/java_gui/src/br/com/bgslibrary/entity/Command.java b/gui_java/src/br/com/bgslibrary/entity/Command.java similarity index 100% rename from java_gui/src/br/com/bgslibrary/entity/Command.java rename to gui_java/src/br/com/bgslibrary/entity/Command.java diff --git a/java_gui/src/br/com/bgslibrary/entity/Configuration.java b/gui_java/src/br/com/bgslibrary/entity/Configuration.java similarity index 100% rename from java_gui/src/br/com/bgslibrary/entity/Configuration.java rename to gui_java/src/br/com/bgslibrary/entity/Configuration.java diff --git a/java_gui/src/br/com/bgslibrary/gui/AboutDialog.form b/gui_java/src/br/com/bgslibrary/gui/AboutDialog.form similarity index 100% rename from java_gui/src/br/com/bgslibrary/gui/AboutDialog.form rename to gui_java/src/br/com/bgslibrary/gui/AboutDialog.form diff --git a/java_gui/src/br/com/bgslibrary/gui/AboutDialog.java b/gui_java/src/br/com/bgslibrary/gui/AboutDialog.java similarity index 100% rename from java_gui/src/br/com/bgslibrary/gui/AboutDialog.java rename to gui_java/src/br/com/bgslibrary/gui/AboutDialog.java diff --git a/java_gui/src/br/com/bgslibrary/gui/MainFrame.form b/gui_java/src/br/com/bgslibrary/gui/MainFrame.form similarity index 100% rename from java_gui/src/br/com/bgslibrary/gui/MainFrame.form rename to gui_java/src/br/com/bgslibrary/gui/MainFrame.form diff --git a/java_gui/src/br/com/bgslibrary/gui/MainFrame.java b/gui_java/src/br/com/bgslibrary/gui/MainFrame.java similarity index 100% rename from java_gui/src/br/com/bgslibrary/gui/MainFrame.java rename to gui_java/src/br/com/bgslibrary/gui/MainFrame.java diff --git a/java_gui/src/br/com/bgslibrary/resources/logo.jpg b/gui_java/src/br/com/bgslibrary/resources/logo.jpg similarity index 100% rename from java_gui/src/br/com/bgslibrary/resources/logo.jpg rename to gui_java/src/br/com/bgslibrary/resources/logo.jpg diff --git a/vs2010mfc/.gitignore b/gui_mfc/.gitignore similarity index 100% rename from vs2010mfc/.gitignore rename to gui_mfc/.gitignore diff --git a/vs2013mfc/ReadMe.txt b/gui_mfc/ReadMe.txt similarity index 100% rename from vs2013mfc/ReadMe.txt rename to gui_mfc/ReadMe.txt diff --git a/vs2010mfc/config/AdaptiveBackgroundLearning.xml b/gui_mfc/config/AdaptiveBackgroundLearning.xml similarity index 100% rename from vs2010mfc/config/AdaptiveBackgroundLearning.xml rename to gui_mfc/config/AdaptiveBackgroundLearning.xml diff --git a/vs2010mfc/config/AdaptiveSelectiveBackgroundLearning.xml b/gui_mfc/config/AdaptiveSelectiveBackgroundLearning.xml similarity index 100% rename from vs2010mfc/config/AdaptiveSelectiveBackgroundLearning.xml rename to gui_mfc/config/AdaptiveSelectiveBackgroundLearning.xml diff --git a/vs2010mfc/config/DPAdaptiveMedianBGS.xml b/gui_mfc/config/DPAdaptiveMedianBGS.xml similarity index 100% rename from vs2010mfc/config/DPAdaptiveMedianBGS.xml rename to gui_mfc/config/DPAdaptiveMedianBGS.xml diff --git a/vs2010mfc/config/DPEigenbackgroundBGS.xml b/gui_mfc/config/DPEigenbackgroundBGS.xml similarity index 100% rename from vs2010mfc/config/DPEigenbackgroundBGS.xml rename to gui_mfc/config/DPEigenbackgroundBGS.xml diff --git a/vs2010mfc/config/DPGrimsonGMMBGS.xml b/gui_mfc/config/DPGrimsonGMMBGS.xml similarity index 100% rename from vs2010mfc/config/DPGrimsonGMMBGS.xml rename to gui_mfc/config/DPGrimsonGMMBGS.xml diff --git a/vs2010mfc/config/DPMeanBGS.xml b/gui_mfc/config/DPMeanBGS.xml similarity index 100% rename from vs2010mfc/config/DPMeanBGS.xml rename to gui_mfc/config/DPMeanBGS.xml diff --git a/vs2010mfc/config/DPPratiMediodBGS.xml b/gui_mfc/config/DPPratiMediodBGS.xml similarity index 100% rename from vs2010mfc/config/DPPratiMediodBGS.xml rename to gui_mfc/config/DPPratiMediodBGS.xml diff --git a/vs2010mfc/config/DPTextureBGS.xml b/gui_mfc/config/DPTextureBGS.xml similarity index 100% rename from vs2010mfc/config/DPTextureBGS.xml rename to gui_mfc/config/DPTextureBGS.xml diff --git a/vs2010mfc/config/DPWrenGABGS.xml b/gui_mfc/config/DPWrenGABGS.xml similarity index 100% rename from vs2010mfc/config/DPWrenGABGS.xml rename to gui_mfc/config/DPWrenGABGS.xml diff --git a/vs2010mfc/config/DPZivkovicAGMMBGS.xml b/gui_mfc/config/DPZivkovicAGMMBGS.xml similarity index 100% rename from vs2010mfc/config/DPZivkovicAGMMBGS.xml rename to gui_mfc/config/DPZivkovicAGMMBGS.xml diff --git a/vs2010mfc/config/FrameDifferenceBGS.xml b/gui_mfc/config/FrameDifferenceBGS.xml similarity index 100% rename from vs2010mfc/config/FrameDifferenceBGS.xml rename to gui_mfc/config/FrameDifferenceBGS.xml diff --git a/vs2010mfc/config/FuzzyChoquetIntegral.xml b/gui_mfc/config/FuzzyChoquetIntegral.xml similarity index 100% rename from vs2010mfc/config/FuzzyChoquetIntegral.xml rename to gui_mfc/config/FuzzyChoquetIntegral.xml diff --git a/vs2010mfc/config/FuzzySugenoIntegral.xml b/gui_mfc/config/FuzzySugenoIntegral.xml similarity index 100% rename from vs2010mfc/config/FuzzySugenoIntegral.xml rename to gui_mfc/config/FuzzySugenoIntegral.xml diff --git a/vs2010mfc/config/GMG.xml b/gui_mfc/config/GMG.xml similarity index 100% rename from vs2010mfc/config/GMG.xml rename to gui_mfc/config/GMG.xml diff --git a/vs2010mfc/config/IndependentMultimodalBGS.xml b/gui_mfc/config/IndependentMultimodalBGS.xml similarity index 100% rename from vs2010mfc/config/IndependentMultimodalBGS.xml rename to gui_mfc/config/IndependentMultimodalBGS.xml diff --git a/vs2010mfc/config/KDE.xml b/gui_mfc/config/KDE.xml similarity index 100% rename from vs2010mfc/config/KDE.xml rename to gui_mfc/config/KDE.xml diff --git a/vs2010mfc/config/LBAdaptiveSOM.xml b/gui_mfc/config/LBAdaptiveSOM.xml similarity index 100% rename from vs2010mfc/config/LBAdaptiveSOM.xml rename to gui_mfc/config/LBAdaptiveSOM.xml diff --git a/vs2010mfc/config/LBFuzzyAdaptiveSOM.xml b/gui_mfc/config/LBFuzzyAdaptiveSOM.xml similarity index 100% rename from vs2010mfc/config/LBFuzzyAdaptiveSOM.xml rename to gui_mfc/config/LBFuzzyAdaptiveSOM.xml diff --git a/vs2010mfc/config/LBFuzzyGaussian.xml b/gui_mfc/config/LBFuzzyGaussian.xml similarity index 100% rename from vs2010mfc/config/LBFuzzyGaussian.xml rename to gui_mfc/config/LBFuzzyGaussian.xml diff --git a/vs2010mfc/config/LBMixtureOfGaussians.xml b/gui_mfc/config/LBMixtureOfGaussians.xml similarity index 100% rename from vs2010mfc/config/LBMixtureOfGaussians.xml rename to gui_mfc/config/LBMixtureOfGaussians.xml diff --git a/vs2010mfc/config/LBSimpleGaussian.xml b/gui_mfc/config/LBSimpleGaussian.xml similarity index 100% rename from vs2010mfc/config/LBSimpleGaussian.xml rename to gui_mfc/config/LBSimpleGaussian.xml diff --git a/vs2010mfc/config/LOBSTERBGS.xml b/gui_mfc/config/LOBSTERBGS.xml similarity index 100% rename from vs2010mfc/config/LOBSTERBGS.xml rename to gui_mfc/config/LOBSTERBGS.xml diff --git a/vs2010mfc/config/MixtureOfGaussianV1BGS.xml b/gui_mfc/config/MixtureOfGaussianV1BGS.xml similarity index 100% rename from vs2010mfc/config/MixtureOfGaussianV1BGS.xml rename to gui_mfc/config/MixtureOfGaussianV1BGS.xml diff --git a/vs2010mfc/config/MixtureOfGaussianV2BGS.xml b/gui_mfc/config/MixtureOfGaussianV2BGS.xml similarity index 100% rename from vs2010mfc/config/MixtureOfGaussianV2BGS.xml rename to gui_mfc/config/MixtureOfGaussianV2BGS.xml diff --git a/vs2010mfc/config/MultiCueBGS.xml b/gui_mfc/config/MultiCueBGS.xml similarity index 100% rename from vs2010mfc/config/MultiCueBGS.xml rename to gui_mfc/config/MultiCueBGS.xml diff --git a/vs2010mfc/config/MultiLayerBGS.xml b/gui_mfc/config/MultiLayerBGS.xml similarity index 100% rename from vs2010mfc/config/MultiLayerBGS.xml rename to gui_mfc/config/MultiLayerBGS.xml diff --git a/vs2010mfc/config/SigmaDeltaBGS.xml b/gui_mfc/config/SigmaDeltaBGS.xml similarity index 100% rename from vs2010mfc/config/SigmaDeltaBGS.xml rename to gui_mfc/config/SigmaDeltaBGS.xml diff --git a/vs2010mfc/config/StaticFrameDifferenceBGS.xml b/gui_mfc/config/StaticFrameDifferenceBGS.xml similarity index 100% rename from vs2010mfc/config/StaticFrameDifferenceBGS.xml rename to gui_mfc/config/StaticFrameDifferenceBGS.xml diff --git a/vs2010mfc/config/SuBSENSEBGS.xml b/gui_mfc/config/SuBSENSEBGS.xml similarity index 100% rename from vs2010mfc/config/SuBSENSEBGS.xml rename to gui_mfc/config/SuBSENSEBGS.xml diff --git a/vs2010mfc/config/T2FGMM_UM.xml b/gui_mfc/config/T2FGMM_UM.xml similarity index 100% rename from vs2010mfc/config/T2FGMM_UM.xml rename to gui_mfc/config/T2FGMM_UM.xml diff --git a/vs2010mfc/config/T2FGMM_UV.xml b/gui_mfc/config/T2FGMM_UV.xml similarity index 100% rename from vs2010mfc/config/T2FGMM_UV.xml rename to gui_mfc/config/T2FGMM_UV.xml diff --git a/vs2010mfc/config/T2FMRF_UM.xml b/gui_mfc/config/T2FMRF_UM.xml similarity index 100% rename from vs2010mfc/config/T2FMRF_UM.xml rename to gui_mfc/config/T2FMRF_UM.xml diff --git a/vs2010mfc/config/T2FMRF_UV.xml b/gui_mfc/config/T2FMRF_UV.xml similarity index 100% rename from vs2010mfc/config/T2FMRF_UV.xml rename to gui_mfc/config/T2FMRF_UV.xml diff --git a/vs2010mfc/config/VuMeter.xml b/gui_mfc/config/VuMeter.xml similarity index 100% rename from vs2010mfc/config/VuMeter.xml rename to gui_mfc/config/VuMeter.xml diff --git a/vs2010mfc/config/WeightedMovingMeanBGS.xml b/gui_mfc/config/WeightedMovingMeanBGS.xml similarity index 100% rename from vs2010mfc/config/WeightedMovingMeanBGS.xml rename to gui_mfc/config/WeightedMovingMeanBGS.xml diff --git a/vs2010mfc/config/WeightedMovingVarianceBGS.xml b/gui_mfc/config/WeightedMovingVarianceBGS.xml similarity index 100% rename from vs2010mfc/config/WeightedMovingVarianceBGS.xml rename to gui_mfc/config/WeightedMovingVarianceBGS.xml diff --git a/vs2010mfc/dataset/video.avi b/gui_mfc/dataset/video.avi similarity index 100% rename from vs2010mfc/dataset/video.avi rename to gui_mfc/dataset/video.avi diff --git a/vs2013mfc/outputs/background/.gitignore b/gui_mfc/outputs/background/.gitignore similarity index 100% rename from vs2013mfc/outputs/background/.gitignore rename to gui_mfc/outputs/background/.gitignore diff --git a/vs2013mfc/outputs/foreground/.gitignore b/gui_mfc/outputs/foreground/.gitignore similarity index 100% rename from vs2013mfc/outputs/foreground/.gitignore rename to gui_mfc/outputs/foreground/.gitignore diff --git a/vs2013mfc/outputs/input/.gitignore b/gui_mfc/outputs/input/.gitignore similarity index 100% rename from vs2013mfc/outputs/input/.gitignore rename to gui_mfc/outputs/input/.gitignore diff --git a/vs2010mfc/src/.gitignore b/gui_mfc/src/.gitignore similarity index 100% rename from vs2010mfc/src/.gitignore rename to gui_mfc/src/.gitignore diff --git a/vs2010mfc/src/App.cpp b/gui_mfc/src/App.cpp similarity index 100% rename from vs2010mfc/src/App.cpp rename to gui_mfc/src/App.cpp diff --git a/vs2010mfc/src/App.h b/gui_mfc/src/App.h similarity index 100% rename from vs2010mfc/src/App.h rename to gui_mfc/src/App.h diff --git a/vs2010mfc/src/Dlg.cpp b/gui_mfc/src/Dlg.cpp similarity index 100% rename from vs2010mfc/src/Dlg.cpp rename to gui_mfc/src/Dlg.cpp diff --git a/vs2010mfc/src/Dlg.h b/gui_mfc/src/Dlg.h similarity index 100% rename from vs2010mfc/src/Dlg.h rename to gui_mfc/src/Dlg.h diff --git a/vs2013mfc/src/ReadMe.txt b/gui_mfc/src/ReadMe.txt similarity index 100% rename from vs2013mfc/src/ReadMe.txt rename to gui_mfc/src/ReadMe.txt diff --git a/vs2013mfc/src/bgslibrary_vs2013_mfc.rc b/gui_mfc/src/bgslibrary_vs2013_mfc.rc similarity index 100% rename from vs2013mfc/src/bgslibrary_vs2013_mfc.rc rename to gui_mfc/src/bgslibrary_vs2013_mfc.rc diff --git a/vs2013mfc/src/bgslibrary_vs2013_mfc.sln b/gui_mfc/src/bgslibrary_vs2013_mfc.sln similarity index 100% rename from vs2013mfc/src/bgslibrary_vs2013_mfc.sln rename to gui_mfc/src/bgslibrary_vs2013_mfc.sln diff --git a/vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj b/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj similarity index 100% rename from vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj rename to gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj diff --git a/vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters b/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters similarity index 100% rename from vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters rename to gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.filters diff --git a/vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj.user b/gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.user similarity index 100% rename from vs2013mfc/src/bgslibrary_vs2013_mfc.vcxproj.user rename to gui_mfc/src/bgslibrary_vs2013_mfc.vcxproj.user diff --git a/vs2013mfc/src/res/bgslibrary_vs2013_mfc.ico b/gui_mfc/src/res/bgslibrary_vs2013_mfc.ico similarity index 100% rename from vs2013mfc/src/res/bgslibrary_vs2013_mfc.ico rename to gui_mfc/src/res/bgslibrary_vs2013_mfc.ico diff --git a/vs2013mfc/src/res/bgslibrary_vs2013_mfc.rc2 b/gui_mfc/src/res/bgslibrary_vs2013_mfc.rc2 similarity index 100% rename from vs2013mfc/src/res/bgslibrary_vs2013_mfc.rc2 rename to gui_mfc/src/res/bgslibrary_vs2013_mfc.rc2 diff --git a/vs2010mfc/src/resource.h b/gui_mfc/src/resource.h similarity index 100% rename from vs2010mfc/src/resource.h rename to gui_mfc/src/resource.h diff --git a/vs2010mfc/src/stdafx.cpp b/gui_mfc/src/stdafx.cpp similarity index 100% rename from vs2010mfc/src/stdafx.cpp rename to gui_mfc/src/stdafx.cpp diff --git a/vs2010mfc/src/stdafx.h b/gui_mfc/src/stdafx.h similarity index 100% rename from vs2010mfc/src/stdafx.h rename to gui_mfc/src/stdafx.h diff --git a/vs2010mfc/src/targetver.h b/gui_mfc/src/targetver.h similarity index 100% rename from vs2010mfc/src/targetver.h rename to gui_mfc/src/targetver.h diff --git a/gui_qt/.gitignore b/gui_qt/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..9c28032b4c6631a5f27072a12901a0fecd324309 --- /dev/null +++ b/gui_qt/.gitignore @@ -0,0 +1,9 @@ +_*/ +debug/ +release/ +build_*/ +dataset*/ +binaries*/ +Makefile* +*.exe +*.dll diff --git a/gui_qt/CMakeLists.txt b/gui_qt/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..83c89202c63b6a0c15300ddaa017ef6e10606410 --- /dev/null +++ b/gui_qt/CMakeLists.txt @@ -0,0 +1,52 @@ +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 new file mode 100644 index 0000000000000000000000000000000000000000..41a4cd2b1548b7ee189911927559afa2aa58d922 --- /dev/null +++ b/gui_qt/README.txt @@ -0,0 +1,17 @@ +#------------------------------------------------- +# +# 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/application.qrc b/gui_qt/application.qrc new file mode 100644 index 0000000000000000000000000000000000000000..3e8687f0f14bf61aeb8f6f2b57859d0ad47545aa --- /dev/null +++ b/gui_qt/application.qrc @@ -0,0 +1,10 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>figs/copy.png</file> + <file>figs/cut.png</file> + <file>figs/new.png</file> + <file>figs/open.png</file> + <file>figs/paste.png</file> + <file>figs/save.png</file> +</qresource> +</RCC> \ No newline at end of file diff --git a/gui_qt/bgslibrary_gui.cpp b/gui_qt/bgslibrary_gui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e886262427295abddf30fd063ed4861a4bd9b16b --- /dev/null +++ b/gui_qt/bgslibrary_gui.cpp @@ -0,0 +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 "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 new file mode 100644 index 0000000000000000000000000000000000000000..feedbf6a8601455aaad465d68842e76928c92a3a --- /dev/null +++ b/gui_qt/bgslibrary_gui.pro @@ -0,0 +1,248 @@ +#------------------------------------------------- +# +# 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/gui_qt/build/.gitignore b/gui_qt/build/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e2a98bb114355ae964e78a929c12d44f75815de --- /dev/null +++ b/gui_qt/build/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore diff --git a/gui_qt/figs/copy.png b/gui_qt/figs/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..2aeb28288f58ddffdd1d75115f170c5bf2773814 Binary files /dev/null and b/gui_qt/figs/copy.png differ diff --git a/gui_qt/figs/cut.png b/gui_qt/figs/cut.png new file mode 100644 index 0000000000000000000000000000000000000000..54638e9386dc8af40dcc9a3ee2f57c62e248e406 Binary files /dev/null and b/gui_qt/figs/cut.png differ diff --git a/gui_qt/figs/new.png b/gui_qt/figs/new.png new file mode 100644 index 0000000000000000000000000000000000000000..12131b01008a3ec29ec69f8b3f65c4b3c15b60d6 Binary files /dev/null and b/gui_qt/figs/new.png differ diff --git a/gui_qt/figs/open.png b/gui_qt/figs/open.png new file mode 100644 index 0000000000000000000000000000000000000000..45fa2883a71fcb891f1ef7c0c217d71eeae284bc Binary files /dev/null and b/gui_qt/figs/open.png differ diff --git a/gui_qt/figs/paste.png b/gui_qt/figs/paste.png new file mode 100644 index 0000000000000000000000000000000000000000..c14425cad1ff1b2c5628be5769c9e9e52b78635f Binary files /dev/null and b/gui_qt/figs/paste.png differ diff --git a/gui_qt/figs/save.png b/gui_qt/figs/save.png new file mode 100644 index 0000000000000000000000000000000000000000..daba865fafd22fa18e7c0488eb699b79d3554170 Binary files /dev/null and b/gui_qt/figs/save.png differ diff --git a/gui_qt/mainwindow.cpp b/gui_qt/mainwindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb7eac8c0acbab9f27cfa9ffa59bd3649f0a76a8 --- /dev/null +++ b/gui_qt/mainwindow.cpp @@ -0,0 +1,571 @@ +/* +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" + +namespace bgslibrary +{ + //template<typename T> IBGS* createInstance() { return new T; } + //typedef std::map<std::string, IBGS*(*)()> map_ibgs; + + IBGS* get_alg(std::string alg_name) { + map_ibgs map; + map["FrameDifference"] = &createInstance<FrameDifference>; + map["StaticFrameDifference"] = &createInstance<StaticFrameDifference>; + map["WeightedMovingMean"] = &createInstance<WeightedMovingMean>; + map["WeightedMovingVariance"] = &createInstance<WeightedMovingVariance>; +#if CV_MAJOR_VERSION == 2 + map["MixtureOfGaussianV1"] = &createInstance<MixtureOfGaussianV1>; // only for OpenCV 2.x +#endif + map["MixtureOfGaussianV2"] = &createInstance<MixtureOfGaussianV2>; + map["AdaptiveBackgroundLearning"] = &createInstance<AdaptiveBackgroundLearning>; + map["AdaptiveSelectiveBackgroundLearning"] = &createInstance<AdaptiveSelectiveBackgroundLearning>; +#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 + map["KNN"] = &createInstance<KNN>; // only on OpenCV 3.x +#endif + map["DPAdaptiveMedian"] = &createInstance<DPAdaptiveMedian>; + map["DPGrimsonGMM"] = &createInstance<DPGrimsonGMM>; + map["DPZivkovicAGMM"] = &createInstance<DPZivkovicAGMM>; + map["DPMean"] = &createInstance<DPMean>; + map["DPWrenGA"] = &createInstance<DPWrenGA>; + map["DPPratiMediod"] = &createInstance<DPPratiMediod>; + map["DPEigenbackground"] = &createInstance<DPEigenbackground>; + map["DPTexture"] = &createInstance<DPTexture>; + map["T2FGMM_UM"] = &createInstance<T2FGMM_UM>; + map["T2FGMM_UV"] = &createInstance<T2FGMM_UV>; + map["T2FMRF_UM"] = &createInstance<T2FMRF_UM>; + map["T2FMRF_UV"] = &createInstance<T2FMRF_UV>; + map["FuzzySugenoIntegral"] = &createInstance<FuzzySugenoIntegral>; + map["FuzzyChoquetIntegral"] = &createInstance<FuzzyChoquetIntegral>; + map["MultiLayer"] = &createInstance<MultiLayer>; + map["PixelBasedAdaptiveSegmenter"] = &createInstance<PixelBasedAdaptiveSegmenter>; + map["LBSimpleGaussian"] = &createInstance<LBSimpleGaussian>; + map["LBFuzzyGaussian"] = &createInstance<LBFuzzyGaussian>; + map["LBMixtureOfGaussians"] = &createInstance<LBMixtureOfGaussians>; + map["LBAdaptiveSOM"] = &createInstance<LBAdaptiveSOM>; + map["LBFuzzyAdaptiveSOM"] = &createInstance<LBFuzzyAdaptiveSOM>; + map["LBP_MRF"] = &createInstance<LBP_MRF>; + map["VuMeter"] = &createInstance<VuMeter>; + map["KDE"] = &createInstance<KDE>; + map["IndependentMultimodal"] = &createInstance<IndependentMultimodal>; + map["MultiCue"] = &createInstance<MultiCue>; + map["SigmaDelta"] = &createInstance<SigmaDelta>; + map["SuBSENSE"] = &createInstance<SuBSENSE>; + map["LOBSTER"] = &createInstance<LOBSTER>; + map["PAWCS"] = &createInstance<PAWCS>; + map["TwoPoints"] = &createInstance<TwoPoints>; + map["ViBe"] = &createInstance<ViBe>; + + return map[alg_name](); + } + + QStringList get_algs_name() + { + QStringList stringList; + stringList.append("FrameDifference"); + stringList.append("StaticFrameDifference"); + stringList.append("WeightedMovingMean"); + stringList.append("WeightedMovingVariance"); +#if CV_MAJOR_VERSION == 2 + stringList.append("MixtureOfGaussianV1"); // only for OpenCV 2.x +#endif + stringList.append("MixtureOfGaussianV2"); + stringList.append("AdaptiveBackgroundLearning"); + stringList.append("AdaptiveSelectiveBackgroundLearning"); +#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 + stringList.append("KNN"); // only on OpenCV 3.x +#endif + stringList.append("DPAdaptiveMedian"); + stringList.append("DPGrimsonGMM"); + stringList.append("DPZivkovicAGMM"); + stringList.append("DPMean"); + stringList.append("DPWrenGA"); + stringList.append("DPPratiMediod"); + stringList.append("DPEigenbackground"); + stringList.append("DPTexture"); + stringList.append("T2FGMM_UM"); + stringList.append("T2FGMM_UV"); + stringList.append("T2FMRF_UM"); + stringList.append("T2FMRF_UV"); + stringList.append("FuzzySugenoIntegral"); + stringList.append("FuzzyChoquetIntegral"); + stringList.append("MultiLayer"); + stringList.append("PixelBasedAdaptiveSegmenter"); + stringList.append("LBSimpleGaussian"); + stringList.append("LBFuzzyGaussian"); + stringList.append("LBMixtureOfGaussians"); + stringList.append("LBAdaptiveSOM"); + stringList.append("LBFuzzyAdaptiveSOM"); + stringList.append("LBP_MRF"); + stringList.append("VuMeter"); + stringList.append("KDE"); + stringList.append("IndependentMultimodal"); + stringList.append("MultiCue"); + stringList.append("SigmaDelta"); + stringList.append("SuBSENSE"); + stringList.append("LOBSTER"); + stringList.append("PAWCS"); + stringList.append("TwoPoints"); + stringList.append("ViBe"); + return stringList; + } +} + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + //QDir applicationPath(QCoreApplication::applicationDirPath()); + fileName = QDir(".").filePath("dataset/video.avi"); + //fileName = applicationPath.absolutePath() + "dataset"; + 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); + listModel->sort(0); + ui->listView_algorithms->setModel(listModel); + QModelIndex index = listModel->index(0); + ui->listView_algorithms->selectionModel()->select(index, QItemSelectionModel::Select); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::on_actionExit_triggered() +{ + this->close(); +} + +void MainWindow::on_pushButton_inputdata_clicked() +{ + QFileDialog dialog(this); + + if (ui->checkBox_imageseq->isChecked()) + dialog.setFileMode(QFileDialog::Directory); + else + dialog.setFileMode(QFileDialog::ExistingFile); + //dialog.setFileMode(QFileDialog::AnyFile); + + dialog.exec(); + QStringList list = dialog.selectedFiles(); + /* + for(int index = 0; index < list.length(); index++) + std::cout << list.at(index).toStdString() << std::endl; + */ + if (list.size() > 0) + { + fileName = list.at(0); + ui->lineEdit_inputdata->setText(fileName); + } +} + +void MainWindow::on_pushButton_out_in_clicked() +{ + QFileDialog dialog(this); + dialog.setDirectory("."); + dialog.setFileMode(QFileDialog::Directory); + dialog.exec(); + QStringList list = dialog.selectedFiles(); + if (list.size() > 0) + { + fileName = list.at(0); + ui->lineEdit_out_in->setText(fileName); + } +} + +void MainWindow::on_pushButton_out_fg_clicked() +{ + QFileDialog dialog(this); + dialog.setDirectory("."); + dialog.setFileMode(QFileDialog::Directory); + dialog.exec(); + QStringList list = dialog.selectedFiles(); + if (list.size() > 0) + { + fileName = list.at(0); + ui->lineEdit_out_fg->setText(fileName); + } +} + +void MainWindow::on_pushButton_out_bg_clicked() +{ + QFileDialog dialog(this); + dialog.setDirectory("."); + dialog.setFileMode(QFileDialog::Directory); + dialog.exec(); + QStringList list = dialog.selectedFiles(); + if (list.size() > 0) + { + fileName = list.at(0); + ui->lineEdit_out_bg->setText(fileName); + } +} + +void MainWindow::on_pushButton_start_clicked() +{ + useCamera = false; + useVideo = false; + useSequence = false; + + if (ui->checkBox_webcamera->isChecked()) + useCamera = true; + else + { + if (ui->checkBox_imageseq->isChecked()) + useSequence = true; + else + useVideo = true; + } + + if (!timer->isActive() && setUpCapture()) + { + createBGS(); + startTimer(); + } +} + +void MainWindow::on_pushButton_stop_clicked() +{ + stopTimer(); +} + +void MainWindow::createBGS() +{ + QString algorithm_name = getSelectedAlgorithmName(); + bgs = bgslibrary::get_alg(algorithm_name.toStdString()); + bgs->setShowOutput(false); +} + +void MainWindow::destroyBGS() +{ + delete bgs; +} + +void MainWindow::startTimer() +{ + std::cout << "startTimer()" << std::endl; + + ui->progressBar->setValue(0); + setFrameNumber(0); + frameNumber_aux = 0; + timer->start(33); + + // disable options +} + +void MainWindow::stopTimer() +{ + if (!timer->isActive()) + return; + + std::cout << "stopTimer()" << std::endl; + + timer->stop(); + //setFrameNumber(0); + //ui->progressBar->setValue(0); + + destroyBGS(); + + if (useCamera || useVideo) + capture.release(); + + // enable options +} + +void MainWindow::setFrameNumber(long long _frameNumber) +{ + //std::cout << "setFrameNumber()" << std::endl; + frameNumber = _frameNumber; + QString txt_frameNumber = QString::fromStdString(its(frameNumber)); + ui->label_framenumber_txt->setText(txt_frameNumber); +} + +bool MainWindow::setUpCapture() +{ + capture_length = 0; + + if (useCamera && !setUpCamera()) { + std::cout << "Cannot initialize webcamera!" << std::endl; + return false; + } + + if (useVideo && !setUpVideo()) { + std::cout << "Cannot open video file " << fileName.toStdString() << std::endl; + return false; + } + + if (useSequence && !setUpSequence()) { + std::cout << "Cannot process images at " << fileName.toStdString() << std::endl; + return false; + } + + if (useCamera || useVideo) { + int capture_fps = 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); + std::cout << "capture_length: " << capture_length << std::endl; + } + + std::cout << "OK!" << std::endl; + return true; +} + +void MainWindow::startCapture() +{ + //std::cout << "startCapture()" << std::endl; + setFrameNumber(frameNumber + 1); + cv::Mat cv_frame; + + if (useCamera || useVideo) + capture >> cv_frame; + + if (useSequence && (frameNumber - 1) < entryList.length()) + { + QString file = entryList.at(frameNumber - 1); + QString filePath = QDir(fileName).filePath(file); + + std::cout << "Processing: " << filePath.toStdString() << std::endl; + if (fileExists(filePath)) + cv_frame = cv::imread(filePath.toStdString()); + } + + if (cv_frame.empty()) + { + stopTimer(); + return; + } + + if (frameNumber == 1) + { + 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))); + } + + if (useVideo && capture_length > 0) + { + double perc = (double(frameNumber) / double(capture_length)) * 100.0; + //std::cout << "perc: " << perc << std::endl; + ui->progressBar->setValue(perc); + } + + int startAt = ui->spinBox_startat->value(); + if (startAt > 0 && frameNumber < startAt) + { + timer->setInterval(1); + return; + } + else + timer->setInterval(33); + + int stopAt = ui->spinBox_stopat->value(); + if (stopAt > 0 && frameNumber >= stopAt) + { + stopTimer(); + return; + } + + cv::Mat cv_frame_small; + cv::resize(cv_frame, cv_frame_small, cv::Size(250, 250)); + + QImage qt_frame = cv2qimage(cv_frame_small); + ui->label_img_in->setPixmap(QPixmap::fromImage(qt_frame, Qt::MonoOnly)); + + processFrame(cv_frame); +} + +QImage MainWindow::cv2qimage(const cv::Mat &cv_frame) +{ + if (cv_frame.channels() == 3) + return Mat2QImage(cv_frame); + else + return GrayMat2QImage(cv_frame); +} + +void MainWindow::processFrame(const cv::Mat &cv_frame) +{ + cv::Mat cv_fg; + cv::Mat cv_bg; + tic(); + bgs->process(cv_frame, cv_fg, cv_bg); + toc(); + ui->label_fps_txt->setText(QString::fromStdString(its(fps()))); + + cv::Mat cv_fg_small; + cv::resize(cv_fg, cv_fg_small, cv::Size(250, 250)); + QImage qt_fg = cv2qimage(cv_fg_small); + ui->label_img_fg->setPixmap(QPixmap::fromImage(qt_fg, Qt::MonoOnly)); + + cv::Mat cv_bg_small; + cv::resize(cv_bg, cv_bg_small, cv::Size(250, 250)); + QImage qt_bg = cv2qimage(cv_bg_small); + ui->label_img_bg->setPixmap(QPixmap::fromImage(qt_bg, Qt::MonoOnly)); + + if (ui->checkBox_save_im->isChecked() || ui->checkBox_save_fg->isChecked() || ui->checkBox_save_bg->isChecked()) + { + if (ui->checkBox_kfn->isChecked()) + frameNumber_aux = frameNumber; + else + frameNumber_aux = frameNumber_aux + 1; + } + if (ui->checkBox_save_im->isChecked()) + { + QString out_im_path = ui->lineEdit_out_in->text(); + QString out_im_file = QDir(out_im_path).filePath(QString::number(frameNumber_aux) + ".png"); + cv::imwrite(out_im_file.toStdString(), cv_frame); + } + if (ui->checkBox_save_fg->isChecked()) + { + QString out_im_path = ui->lineEdit_out_fg->text(); + QString out_im_file = QDir(out_im_path).filePath(QString::number(frameNumber_aux) + ".png"); + cv::imwrite(out_im_file.toStdString(), cv_fg); + } + if (ui->checkBox_save_bg->isChecked()) + { + QString out_im_path = ui->lineEdit_out_bg->text(); + QString out_im_file = QDir(out_im_path).filePath(QString::number(frameNumber) + ".png"); + cv::imwrite(out_im_file.toStdString(), cv_bg); + } +} + +void MainWindow::tic() +{ + duration = static_cast<double>(cv::getTickCount()); +} + +void MainWindow::toc() +{ + duration = (static_cast<double>(cv::getTickCount()) - duration) / cv::getTickFrequency(); + //std::cout << "time(sec):" << std::fixed << std::setprecision(6) << duration << std::endl; + //std::cout << duration << std::endl; +} + +double MainWindow::fps() +{ + //double fps = frameNumber / duration; + double fps = 1 / duration; + //std::cout << "Estimated frames per second : " << fps << std::endl; + return fps; +} + +bool MainWindow::setUpCamera() +{ + int cameraIndex = ui->spinBox_webcamera->value(); + std::cout << "Camera index: " << cameraIndex << std::endl; + + capture.open(cameraIndex); + return capture.isOpened(); +} + +bool MainWindow::setUpVideo() +{ + std::string videoFileName = fileName.toStdString(); + std::cout << "Openning: " << videoFileName << std::endl; + capture.open(videoFileName.c_str()); + return capture.isOpened(); +} + +bool MainWindow::setUpSequence() +{ + std::cout << "Directory path: " << fileName.toStdString() << std::endl; + if (QDir(fileName).exists()) + { + QDir dir(fileName); + QStringList filters; + filters << "*.png" << "*.jpg" << "*.bmp" << "*.gif"; + dir.setNameFilters(filters); + //entryList = dir.entryList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst); + //entryList = dir.entryList(QDir::Filter::Files, QDir::SortFlag::NoSort); + dir.setFilter(QDir::Files | QDir::NoSymLinks); + dir.setSorting(QDir::NoSort); // will sort manually with std::sort + //dir.setSorting(QDir::LocaleAware); + entryList = dir.entryList(); + + std::cout << entryList.length() << std::endl; + if (entryList.length() == 0) + { + QMessageBox::warning(this, "Warning", "No image found! (png, jpg, bmp, gif)"); + return false; + } + + QCollator collator; + collator.setNumericMode(true); + std::sort( + entryList.begin(), + entryList.end(), + [&collator](const QString &file1, const QString &file2) + { + return collator.compare(file1, file2) < 0; + }); + + // for(int i = 0; i < entryList.length(); i++) + // { + // QString file = entryList.at(i); + // std::cout << file.toStdString() << std::endl; + // } + return true; + } + else + { + QMessageBox::warning(this, "Warning", "Directory path doesn't exist!"); + return false; + } +} + +QString MainWindow::getSelectedAlgorithmName() +{ + QModelIndex index = ui->listView_algorithms->currentIndex(); + QString algorithm_name = index.data(Qt::DisplayRole).toString(); + return algorithm_name; +} + +void MainWindow::on_listView_algorithms_doubleClicked(const QModelIndex &index) +{ + QString algorithm_name = index.data(Qt::DisplayRole).toString(); + std::cout << "Selected algorithm: " << algorithm_name.toStdString() << std::endl; + + // CodeEditor editor; + // editor.setWindowTitle(QObject::tr("Code Editor Example")); + // editor.show(); + + QString configFileName = QDir(".").filePath("config/" + algorithm_name + ".xml"); + std::cout << "Looking for: " << configFileName.toStdString() << std::endl; + + if (fileExists(configFileName)) + { + textEditor.loadFile(configFileName); + textEditor.show(); + } + else + { + QMessageBox::warning(this, "Warning", "XML configuration file not found!\nPlease run the algorithm first!"); + return; + } +} diff --git a/gui_qt/mainwindow.h b/gui_qt/mainwindow.h new file mode 100644 index 0000000000000000000000000000000000000000..a834882b7bc73683e53f6d0960f26209f82e9961 --- /dev/null +++ b/gui_qt/mainwindow.h @@ -0,0 +1,110 @@ +/* +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> +#include <QCommandLineParser> +#include <QCommandLineOption> +#include <QMainWindow> +#include <QFileDialog> +#include <QDebug> +#include <QFile> +#include <QMessageBox> +#include <QImage> +#include <QTimer> +#include <QStringList> +#include <QStringListModel> +#include <QCollator> + +#include <opencv2/opencv.hpp> + +#include "qt_utils.h" +#include "texteditor.h" +#include "../package_bgs/bgslibrary.h" + +namespace bgslibrary +{ + template<typename T> IBGS * createInstance() { return new T; } + typedef std::map<std::string, IBGS*(*)()> map_ibgs; + + IBGS* get_alg(std::string alg_name); + QStringList get_algs_name(); +} + +namespace Ui { + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + private slots: + void on_actionExit_triggered(); + + void on_pushButton_inputdata_clicked(); + + void on_pushButton_start_clicked(); + + void on_pushButton_stop_clicked(); + + void on_pushButton_out_in_clicked(); + + void on_pushButton_out_fg_clicked(); + + void on_pushButton_out_bg_clicked(); + + void on_listView_algorithms_doubleClicked(const QModelIndex &index); + +private: + Ui::MainWindow *ui; + QString fileName; + cv::VideoCapture capture; + bool useCamera = false; + bool useVideo = false; + bool useSequence = false; + QStringList entryList; + long long frameNumber = 0; + long long frameNumber_aux = 0; + bool setUpCapture(); + bool setUpCamera(); + bool setUpVideo(); + bool setUpSequence(); + QString getSelectedAlgorithmName(); + QTimer* timer; + void startTimer(); + void stopTimer(); + void setFrameNumber(long long frameNumber); + QImage cv2qimage(const cv::Mat &cv_frame); + void processFrame(const cv::Mat &cv_frame); + IBGS *bgs; + void createBGS(); + void destroyBGS(); + double duration = 0; + void tic(); + void toc(); + double fps(); + int capture_length = 0; + TextEditor textEditor; + + public slots: + void startCapture(); +}; diff --git a/gui_qt/mainwindow.ui b/gui_qt/mainwindow.ui new file mode 100644 index 0000000000000000000000000000000000000000..75e9e61a8081a9417d138d40149e10b6f2e5ea00 --- /dev/null +++ b/gui_qt/mainwindow.ui @@ -0,0 +1,631 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1070</width> + <height>559</height> + </rect> + </property> + <property name="windowTitle"> + <string>BGSLibrary QT GUI</string> + </property> + <widget class="QWidget" name="centralWidget"> + <widget class="QLabel" name="label_algorithms"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>251</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Algorithms</string> + </property> + </widget> + <widget class="QListView" name="listView_algorithms"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>256</width> + <height>361</height> + </rect> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + </widget> + <widget class="QLabel" name="label_inputdata"> + <property name="geometry"> + <rect> + <x>280</x> + <y>10</y> + <width>601</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Input (specify a video file or a directory path containing the sequence of images)</string> + </property> + </widget> + <widget class="QLineEdit" name="lineEdit_inputdata"> + <property name="geometry"> + <rect> + <x>280</x> + <y>30</y> + <width>721</width> + <height>22</height> + </rect> + </property> + <property name="text"> + <string>./dataset/video.avi</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_inputdata"> + <property name="geometry"> + <rect> + <x>1010</x> + <y>30</y> + <width>40</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_webcamera"> + <property name="geometry"> + <rect> + <x>280</x> + <y>60</y> + <width>131</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Use web camera</string> + </property> + </widget> + <widget class="QSpinBox" name="spinBox_webcamera"> + <property name="geometry"> + <rect> + <x>410</x> + <y>60</y> + <width>42</width> + <height>20</height> + </rect> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_imageseq"> + <property name="geometry"> + <rect> + <x>470</x> + <y>60</y> + <width>151</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Sequence of images?</string> + </property> + </widget> + <widget class="QLabel" name="label_startat"> + <property name="geometry"> + <rect> + <x>945</x> + <y>60</y> + <width>55</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Start at:</string> + </property> + </widget> + <widget class="QSpinBox" name="spinBox_startat"> + <property name="geometry"> + <rect> + <x>1000</x> + <y>60</y> + <width>50</width> + <height>20</height> + </rect> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + <widget class="QLabel" name="label_stopat"> + <property name="geometry"> + <rect> + <x>945</x> + <y>85</y> + <width>55</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Stop at:</string> + </property> + </widget> + <widget class="QSpinBox" name="spinBox_stopat"> + <property name="geometry"> + <rect> + <x>1000</x> + <y>85</y> + <width>50</width> + <height>20</height> + </rect> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + <widget class="QLabel" name="label_input"> + <property name="geometry"> + <rect> + <x>280</x> + <y>120</y> + <width>250</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Input</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_img_in"> + <property name="geometry"> + <rect> + <x>280</x> + <y>140</y> + <width>250</width> + <height>250</height> + </rect> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>IMG_INPUT</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_img_fg"> + <property name="geometry"> + <rect> + <x>540</x> + <y>140</y> + <width>250</width> + <height>250</height> + </rect> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>IMG_FOREGROUND</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_img_bg"> + <property name="geometry"> + <rect> + <x>800</x> + <y>140</y> + <width>250</width> + <height>250</height> + </rect> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>IMG_BACKGROUND</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_foreground"> + <property name="geometry"> + <rect> + <x>540</x> + <y>120</y> + <width>250</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Foreground mask</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_background"> + <property name="geometry"> + <rect> + <x>800</x> + <y>120</y> + <width>250</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Background model</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_save_im"> + <property name="geometry"> + <rect> + <x>280</x> + <y>400</y> + <width>52</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Save</string> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_save_fg"> + <property name="geometry"> + <rect> + <x>540</x> + <y>400</y> + <width>52</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Save</string> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_save_bg"> + <property name="geometry"> + <rect> + <x>800</x> + <y>400</y> + <width>52</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Save</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_stop"> + <property name="geometry"> + <rect> + <x>960</x> + <y>470</y> + <width>93</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>Stop</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_start"> + <property name="geometry"> + <rect> + <x>850</x> + <y>470</y> + <width>93</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>Start</string> + </property> + </widget> + <widget class="QProgressBar" name="progressBar"> + <property name="geometry"> + <rect> + <x>280</x> + <y>470</y> + <width>550</width> + <height>23</height> + </rect> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + <widget class="QLabel" name="label_exectime"> + <property name="geometry"> + <rect> + <x>10</x> + <y>400</y> + <width>121</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Estimated FPS:</string> + </property> + </widget> + <widget class="QLabel" name="label_fps_txt"> + <property name="geometry"> + <rect> + <x>210</x> + <y>400</y> + <width>55</width> + <height>16</height> + </rect> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_framenumber"> + <property name="geometry"> + <rect> + <x>10</x> + <y>420</y> + <width>121</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Frame number:</string> + </property> + </widget> + <widget class="QLabel" name="label_framenumber_txt"> + <property name="geometry"> + <rect> + <x>210</x> + <y>420</y> + <width>55</width> + <height>16</height> + </rect> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_status"> + <property name="geometry"> + <rect> + <x>209</x> + <y>470</y> + <width>61</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>Progress:</string> + </property> + </widget> + <widget class="QLabel" name="label_frameres"> + <property name="geometry"> + <rect> + <x>10</x> + <y>440</y> + <width>121</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Frame resolution:</string> + </property> + </widget> + <widget class="QLabel" name="label_frameresw_txt"> + <property name="geometry"> + <rect> + <x>140</x> + <y>440</y> + <width>55</width> + <height>16</height> + </rect> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_frameresh_txt"> + <property name="geometry"> + <rect> + <x>210</x> + <y>440</y> + <width>55</width> + <height>16</height> + </rect> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QLabel" name="label_frameres_2"> + <property name="geometry"> + <rect> + <x>193</x> + <y>440</y> + <width>21</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>x</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QLineEdit" name="lineEdit_out_in"> + <property name="geometry"> + <rect> + <x>348</x> + <y>400</y> + <width>140</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>./output/in/</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_out_in"> + <property name="geometry"> + <rect> + <x>490</x> + <y>400</y> + <width>40</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QLineEdit" name="lineEdit_out_fg"> + <property name="geometry"> + <rect> + <x>608</x> + <y>400</y> + <width>140</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>./output/fg/</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_out_fg"> + <property name="geometry"> + <rect> + <x>750</x> + <y>400</y> + <width>40</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_out_bg"> + <property name="geometry"> + <rect> + <x>1010</x> + <y>400</y> + <width>40</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QLineEdit" name="lineEdit_out_bg"> + <property name="geometry"> + <rect> + <x>868</x> + <y>400</y> + <width>140</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>./output/bg/</string> + </property> + </widget> + <widget class="QCheckBox" name="checkBox_kfn"> + <property name="geometry"> + <rect> + <x>280</x> + <y>420</y> + <width>141</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Keep frame number</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </widget> + <widget class="QMenuBar" name="menuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1070</width> + <height>26</height> + </rect> + </property> + <widget class="QMenu" name="menuBGSLibrary"> + <property name="title"> + <string>BGSLibrary</string> + </property> + <addaction name="actionExit"/> + </widget> + <addaction name="menuBGSLibrary"/> + </widget> + <widget class="QStatusBar" name="statusBar"/> + <action name="actionExit"> + <property name="text"> + <string>Exit</string> + </property> + </action> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources/> + <connections/> +</ui> diff --git a/gui_qt/qt_utils.cpp b/gui_qt/qt_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2464d7896aa7bc9d72a47cff3971b925feab6f3b --- /dev/null +++ b/gui_qt/qt_utils.cpp @@ -0,0 +1,74 @@ +/* +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); + 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); + 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 result; + cvtColor(tmp, result, CV_RGB2BGR); + return result; +} + +QString base64_encode(const QString string) { + QByteArray ba; + 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 i; + std::stringstream ss; + ss << s; + ss >> i; + return i; +} +std::string its(int i) { + std::stringstream ss; + ss << i; + return ss.str(); +} + +bool fileExists(QString path) { + QFileInfo check_file(path); + // check if file exists and if yes: Is it really a file and no directory? + return check_file.exists() && check_file.isFile(); +} diff --git a/gui_qt/qt_utils.h b/gui_qt/qt_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..84128c5676e8b969e76c749d85bf750bbd7a2dbf --- /dev/null +++ b/gui_qt/qt_utils.h @@ -0,0 +1,99 @@ +/* +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> + +QImage GrayMat2QImage(cv::Mat const& src); +QImage Mat2QImage(cv::Mat const& src); +cv::Mat QImage2Mat(QImage const& src); + +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); + +bool fileExists(QString path); + +/* +#include <QFileDialog> +#include <QApplication> +#include <QWidget> +#include <QTreeWidget> +#include <QPushButton> +#include <QStringList> +#include <QModelIndex> +#include <QDir> +#include <QDebug> + +class FileDialog : public QFileDialog +{ + Q_OBJECT + public: + explicit FileDialog(QWidget *parent = Q_NULLPTR) + : QFileDialog(parent) + { + setOption(QFileDialog::DontUseNativeDialog); + setFileMode(QFileDialog::Directory); + //setFileMode(QFileDialog::ExistingFiles); + //setFileMode(QFileDialog::Directory|QFileDialog::ExistingFiles); + for (auto *pushButton : findChildren<QPushButton*>()) { + qDebug() << pushButton->text(); + if (pushButton->text() == "&Open" || pushButton->text() == "&Choose") { + openButton = pushButton; + break; + } + } + disconnect(openButton, SIGNAL(clicked(bool))); + connect(openButton, &QPushButton::clicked, this, &FileDialog::openClicked); + treeView = findChild<QTreeView*>(); + } + + QStringList selected() const + { + return selectedFilePaths; + } + + public slots: + void openClicked() + { + selectedFilePaths.clear(); + qDebug() << treeView->selectionModel()->selection(); + for (const auto& modelIndex : treeView->selectionModel()->selectedIndexes()) { + qDebug() << modelIndex.column(); + if (modelIndex.column() == 0) + selectedFilePaths.append(directory().absolutePath() + modelIndex.data().toString()); + } + emit filesSelected(selectedFilePaths); + hide(); + qDebug() << selectedFilePaths; + } + + private: + QTreeView *treeView; + QPushButton *openButton; + QStringList selectedFilePaths; +}; +*/ diff --git a/gui_qt/texteditor.cpp b/gui_qt/texteditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80f45e118ed842cb231898dbc3128c11ec7f4f8f --- /dev/null +++ b/gui_qt/texteditor.cpp @@ -0,0 +1,320 @@ +/* +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" + +TextEditor::TextEditor() + : textEdit(new QPlainTextEdit) +{ + setCentralWidget(textEdit); + + createActions(); + createStatusBar(); + + readSettings(); + + connect(textEdit->document(), &QTextDocument::contentsChanged, + this, &TextEditor::documentWasModified); + +#ifndef QT_NO_SESSIONMANAGER + QGuiApplication::setFallbackSessionManagementEnabled(false); + connect(qApp, &QGuiApplication::commitDataRequest, + this, &TextEditor::commitData); +#endif + + setCurrentFile(QString()); + setUnifiedTitleAndToolBarOnMac(true); +} + +void TextEditor::closeEvent(QCloseEvent *event) +{ + if (maybeSave()) { + writeSettings(); + event->accept(); + } + else { + event->ignore(); + } +} + +void TextEditor::newFile() +{ + if (maybeSave()) { + textEdit->clear(); + setCurrentFile(QString()); + } +} + +void TextEditor::open() +{ + if (maybeSave()) { + QString fileName = QFileDialog::getOpenFileName(this); + if (!fileName.isEmpty()) + loadFile(fileName); + } +} + +bool TextEditor::save() +{ + if (curFile.isEmpty()) { + return saveAs(); + } + else { + return saveFile(curFile); + } +} + +bool TextEditor::saveAs() +{ + QFileDialog dialog(this); + dialog.setWindowModality(Qt::WindowModal); + dialog.setAcceptMode(QFileDialog::AcceptSave); + if (dialog.exec() != QDialog::Accepted) + return false; + return saveFile(dialog.selectedFiles().first()); +} + +void TextEditor::about() +{ + QMessageBox::about(this, tr("About BGSLibrary"), + tr("The <b>BGSLibrary</b> provides an easy-to-use framework " + "to perform foreground-background separation in videos.")); +} + +void TextEditor::documentWasModified() +{ + setWindowModified(textEdit->document()->isModified()); +} + +void TextEditor::createActions() +{ + + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QToolBar *fileToolBar = addToolBar(tr("File")); + const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/figs/new.png")); + QAction *newAct = new QAction(newIcon, tr("&New"), this); + newAct->setShortcuts(QKeySequence::New); + newAct->setStatusTip(tr("Create a new file")); + connect(newAct, &QAction::triggered, this, &TextEditor::newFile); + fileMenu->addAction(newAct); + fileToolBar->addAction(newAct); + + const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/figs/open.png")); + QAction *openAct = new QAction(openIcon, tr("&Open..."), this); + openAct->setShortcuts(QKeySequence::Open); + openAct->setStatusTip(tr("Open an existing file")); + connect(openAct, &QAction::triggered, this, &TextEditor::open); + fileMenu->addAction(openAct); + fileToolBar->addAction(openAct); + + const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/figs/save.png")); + QAction *saveAct = new QAction(saveIcon, tr("&Save"), this); + saveAct->setShortcuts(QKeySequence::Save); + saveAct->setStatusTip(tr("Save the document to disk")); + connect(saveAct, &QAction::triggered, this, &TextEditor::save); + fileMenu->addAction(saveAct); + fileToolBar->addAction(saveAct); + + const QIcon saveAsIcon = QIcon::fromTheme("document-save-as"); + QAction *saveAsAct = fileMenu->addAction(saveAsIcon, tr("Save &As..."), this, &TextEditor::saveAs); + saveAsAct->setShortcuts(QKeySequence::SaveAs); + saveAsAct->setStatusTip(tr("Save the document under a new name")); + + + fileMenu->addSeparator(); + + const QIcon exitIcon = QIcon::fromTheme("application-exit"); + QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close); + exitAct->setShortcuts(QKeySequence::Quit); + exitAct->setStatusTip(tr("Exit the application")); + + QMenu *editMenu = menuBar()->addMenu(tr("&Edit")); + QToolBar *editToolBar = addToolBar(tr("Edit")); +#ifndef QT_NO_CLIPBOARD + const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/figs/cut.png")); + QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this); + cutAct->setShortcuts(QKeySequence::Cut); + cutAct->setStatusTip(tr("Cut the current selection's contents to the " + "clipboard")); + connect(cutAct, &QAction::triggered, textEdit, &QPlainTextEdit::cut); + editMenu->addAction(cutAct); + editToolBar->addAction(cutAct); + + const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/figs/copy.png")); + QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this); + copyAct->setShortcuts(QKeySequence::Copy); + copyAct->setStatusTip(tr("Copy the current selection's contents to the " + "clipboard")); + connect(copyAct, &QAction::triggered, textEdit, &QPlainTextEdit::copy); + editMenu->addAction(copyAct); + editToolBar->addAction(copyAct); + + const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(":/figs/paste.png")); + QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this); + pasteAct->setShortcuts(QKeySequence::Paste); + pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current " + "selection")); + connect(pasteAct, &QAction::triggered, textEdit, &QPlainTextEdit::paste); + editMenu->addAction(pasteAct); + editToolBar->addAction(pasteAct); + + menuBar()->addSeparator(); + +#endif // !QT_NO_CLIPBOARD + + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &TextEditor::about); + aboutAct->setStatusTip(tr("Show the application's About box")); + + + QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); + aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); + +#ifndef QT_NO_CLIPBOARD + cutAct->setEnabled(false); + copyAct->setEnabled(false); + connect(textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled); + connect(textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled); +#endif // !QT_NO_CLIPBOARD +} + +void TextEditor::createStatusBar() +{ + statusBar()->showMessage(tr("Ready")); +} + +void TextEditor::readSettings() +{ + QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray(); + if (geometry.isEmpty()) { + const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); + resize(availableGeometry.width() / 3, availableGeometry.height() / 2); + move((availableGeometry.width() - width()) / 2, + (availableGeometry.height() - height()) / 2); + } + else { + restoreGeometry(geometry); + } +} + +void TextEditor::writeSettings() +{ + QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + settings.setValue("geometry", saveGeometry()); +} + +bool TextEditor::maybeSave() +{ + if (!textEdit->document()->isModified()) + return true; + const QMessageBox::StandardButton ret + = QMessageBox::warning(this, tr("Application"), + tr("The document has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + switch (ret) { + case QMessageBox::Save: + return save(); + case QMessageBox::Cancel: + return false; + default: + break; + } + return true; +} + +void TextEditor::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("Application"), + tr("Cannot read file %1:\n%2.") + .arg(QDir::toNativeSeparators(fileName), file.errorString())); + return; + } + + QTextStream in(&file); +#ifndef QT_NO_CURSOR + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + textEdit->setPlainText(in.readAll()); +#ifndef QT_NO_CURSOR + QApplication::restoreOverrideCursor(); +#endif + + setCurrentFile(fileName); + statusBar()->showMessage(tr("File loaded"), 2000); +} + +bool TextEditor::saveFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("Application"), + tr("Cannot write file %1:\n%2.") + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); + return false; + } + + QTextStream out(&file); +#ifndef QT_NO_CURSOR + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + out << textEdit->toPlainText(); +#ifndef QT_NO_CURSOR + QApplication::restoreOverrideCursor(); +#endif + + setCurrentFile(fileName); + statusBar()->showMessage(tr("File saved"), 2000); + return true; +} + +void TextEditor::setCurrentFile(const QString &fileName) +{ + curFile = fileName; + textEdit->document()->setModified(false); + setWindowModified(false); + + QString shownName = curFile; + if (curFile.isEmpty()) + shownName = "untitled.txt"; + setWindowFilePath(shownName); +} + +QString TextEditor::strippedName(const QString &fullFileName) +{ + return QFileInfo(fullFileName).fileName(); +} +#ifndef QT_NO_SESSIONMANAGER +void TextEditor::commitData(QSessionManager &manager) +{ + if (manager.allowsInteraction()) { + if (!maybeSave()) + manager.cancel(); + } + else { + // Non-interactive: save without asking + if (textEdit->document()->isModified()) + save(); + } +} +#endif diff --git a/gui_qt/texteditor.h b/gui_qt/texteditor.h new file mode 100644 index 0000000000000000000000000000000000000000..c0d5d8f60d1d8a4ed859207f52349cd597a49c9a --- /dev/null +++ b/gui_qt/texteditor.h @@ -0,0 +1,64 @@ +/* +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 + +#include <QMainWindow> + +class QAction; +class QMenu; +class QPlainTextEdit; +class QSessionManager; + +class TextEditor : public QMainWindow +{ + Q_OBJECT + +public: + TextEditor(); + + void loadFile(const QString &fileName); + +protected: + void closeEvent(QCloseEvent *event) override; + + private slots: + void newFile(); + void open(); + bool save(); + bool saveAs(); + void about(); + void documentWasModified(); +#ifndef QT_NO_SESSIONMANAGER + void commitData(QSessionManager &); +#endif + +private: + void createActions(); + void createStatusBar(); + void readSettings(); + void writeSettings(); + bool maybeSave(); + bool saveFile(const QString &fileName); + void setCurrentFile(const QString &fileName); + QString strippedName(const QString &fullFileName); + + QPlainTextEdit *textEdit; + QString curFile; +}; + +#endif // TEXTEDITOR_H diff --git a/gui_qt/ui_mainwindow.h b/gui_qt/ui_mainwindow.h new file mode 100644 index 0000000000000000000000000000000000000000..eb3f468520af97f6eb605a2cc1e5feedd91e2545 --- /dev/null +++ b/gui_qt/ui_mainwindow.h @@ -0,0 +1,306 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created by: Qt User Interface Compiler version 5.6.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include <QtCore/QVariant> +#include <QtWidgets/QAction> +#include <QtWidgets/QApplication> +#include <QtWidgets/QButtonGroup> +#include <QtWidgets/QCheckBox> +#include <QtWidgets/QHeaderView> +#include <QtWidgets/QLabel> +#include <QtWidgets/QLineEdit> +#include <QtWidgets/QListView> +#include <QtWidgets/QMainWindow> +#include <QtWidgets/QMenu> +#include <QtWidgets/QMenuBar> +#include <QtWidgets/QProgressBar> +#include <QtWidgets/QPushButton> +#include <QtWidgets/QSpinBox> +#include <QtWidgets/QStatusBar> +#include <QtWidgets/QWidget> + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QAction *actionExit; + QWidget *centralWidget; + QLabel *label_algorithms; + QListView *listView_algorithms; + QLabel *label_inputdata; + QLineEdit *lineEdit_inputdata; + QPushButton *pushButton_inputdata; + QCheckBox *checkBox_webcamera; + QSpinBox *spinBox_webcamera; + QCheckBox *checkBox_imageseq; + QLabel *label_startat; + QSpinBox *spinBox_startat; + QLabel *label_stopat; + QSpinBox *spinBox_stopat; + QLabel *label_input; + QLabel *label_img_in; + QLabel *label_img_fg; + QLabel *label_img_bg; + QLabel *label_foreground; + QLabel *label_background; + QCheckBox *checkBox_save_im; + QCheckBox *checkBox_save_fg; + QCheckBox *checkBox_save_bg; + QPushButton *pushButton_stop; + QPushButton *pushButton_start; + QProgressBar *progressBar; + QLabel *label_exectime; + QLabel *label_fps_txt; + QLabel *label_framenumber; + QLabel *label_framenumber_txt; + QLabel *label_status; + QLabel *label_frameres; + QLabel *label_frameresw_txt; + QLabel *label_frameresh_txt; + QLabel *label_frameres_2; + QLineEdit *lineEdit_out_in; + QPushButton *pushButton_out_in; + QLineEdit *lineEdit_out_fg; + QPushButton *pushButton_out_fg; + QPushButton *pushButton_out_bg; + QLineEdit *lineEdit_out_bg; + QCheckBox *checkBox_kfn; + QMenuBar *menuBar; + QMenu *menuBGSLibrary; + QStatusBar *statusBar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QStringLiteral("MainWindow")); + MainWindow->resize(1070, 559); + actionExit = new QAction(MainWindow); + actionExit->setObjectName(QStringLiteral("actionExit")); + centralWidget = new QWidget(MainWindow); + centralWidget->setObjectName(QStringLiteral("centralWidget")); + label_algorithms = new QLabel(centralWidget); + label_algorithms->setObjectName(QStringLiteral("label_algorithms")); + label_algorithms->setGeometry(QRect(10, 10, 251, 16)); + listView_algorithms = new QListView(centralWidget); + listView_algorithms->setObjectName(QStringLiteral("listView_algorithms")); + listView_algorithms->setGeometry(QRect(10, 30, 256, 361)); + listView_algorithms->setEditTriggers(QAbstractItemView::NoEditTriggers); + label_inputdata = new QLabel(centralWidget); + label_inputdata->setObjectName(QStringLiteral("label_inputdata")); + label_inputdata->setGeometry(QRect(280, 10, 601, 16)); + lineEdit_inputdata = new QLineEdit(centralWidget); + lineEdit_inputdata->setObjectName(QStringLiteral("lineEdit_inputdata")); + lineEdit_inputdata->setGeometry(QRect(280, 30, 721, 22)); + pushButton_inputdata = new QPushButton(centralWidget); + pushButton_inputdata->setObjectName(QStringLiteral("pushButton_inputdata")); + pushButton_inputdata->setGeometry(QRect(1010, 30, 40, 21)); + checkBox_webcamera = new QCheckBox(centralWidget); + checkBox_webcamera->setObjectName(QStringLiteral("checkBox_webcamera")); + checkBox_webcamera->setGeometry(QRect(280, 60, 131, 20)); + spinBox_webcamera = new QSpinBox(centralWidget); + spinBox_webcamera->setObjectName(QStringLiteral("spinBox_webcamera")); + spinBox_webcamera->setGeometry(QRect(410, 60, 42, 20)); + checkBox_imageseq = new QCheckBox(centralWidget); + checkBox_imageseq->setObjectName(QStringLiteral("checkBox_imageseq")); + checkBox_imageseq->setGeometry(QRect(470, 60, 151, 20)); + label_startat = new QLabel(centralWidget); + label_startat->setObjectName(QStringLiteral("label_startat")); + label_startat->setGeometry(QRect(945, 60, 55, 20)); + spinBox_startat = new QSpinBox(centralWidget); + spinBox_startat->setObjectName(QStringLiteral("spinBox_startat")); + spinBox_startat->setGeometry(QRect(1000, 60, 50, 20)); + spinBox_startat->setMaximum(9999); + label_stopat = new QLabel(centralWidget); + label_stopat->setObjectName(QStringLiteral("label_stopat")); + label_stopat->setGeometry(QRect(945, 85, 55, 20)); + spinBox_stopat = new QSpinBox(centralWidget); + spinBox_stopat->setObjectName(QStringLiteral("spinBox_stopat")); + spinBox_stopat->setGeometry(QRect(1000, 85, 50, 20)); + spinBox_stopat->setMaximum(9999); + label_input = new QLabel(centralWidget); + label_input->setObjectName(QStringLiteral("label_input")); + label_input->setGeometry(QRect(280, 120, 250, 16)); + label_input->setAlignment(Qt::AlignCenter); + label_img_in = new QLabel(centralWidget); + label_img_in->setObjectName(QStringLiteral("label_img_in")); + label_img_in->setGeometry(QRect(280, 140, 250, 250)); + label_img_in->setFrameShape(QFrame::Box); + label_img_in->setAlignment(Qt::AlignCenter); + label_img_fg = new QLabel(centralWidget); + label_img_fg->setObjectName(QStringLiteral("label_img_fg")); + label_img_fg->setGeometry(QRect(540, 140, 250, 250)); + label_img_fg->setFrameShape(QFrame::Box); + label_img_fg->setAlignment(Qt::AlignCenter); + label_img_bg = new QLabel(centralWidget); + label_img_bg->setObjectName(QStringLiteral("label_img_bg")); + label_img_bg->setGeometry(QRect(800, 140, 250, 250)); + label_img_bg->setFrameShape(QFrame::Box); + label_img_bg->setAlignment(Qt::AlignCenter); + label_foreground = new QLabel(centralWidget); + label_foreground->setObjectName(QStringLiteral("label_foreground")); + label_foreground->setGeometry(QRect(540, 120, 250, 16)); + label_foreground->setAlignment(Qt::AlignCenter); + label_background = new QLabel(centralWidget); + label_background->setObjectName(QStringLiteral("label_background")); + label_background->setGeometry(QRect(800, 120, 250, 16)); + label_background->setAlignment(Qt::AlignCenter); + checkBox_save_im = new QCheckBox(centralWidget); + checkBox_save_im->setObjectName(QStringLiteral("checkBox_save_im")); + checkBox_save_im->setGeometry(QRect(280, 400, 52, 20)); + checkBox_save_fg = new QCheckBox(centralWidget); + checkBox_save_fg->setObjectName(QStringLiteral("checkBox_save_fg")); + checkBox_save_fg->setGeometry(QRect(540, 400, 52, 20)); + checkBox_save_bg = new QCheckBox(centralWidget); + checkBox_save_bg->setObjectName(QStringLiteral("checkBox_save_bg")); + checkBox_save_bg->setGeometry(QRect(800, 400, 52, 20)); + pushButton_stop = new QPushButton(centralWidget); + pushButton_stop->setObjectName(QStringLiteral("pushButton_stop")); + pushButton_stop->setGeometry(QRect(960, 470, 93, 23)); + pushButton_start = new QPushButton(centralWidget); + pushButton_start->setObjectName(QStringLiteral("pushButton_start")); + pushButton_start->setGeometry(QRect(850, 470, 93, 23)); + progressBar = new QProgressBar(centralWidget); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setGeometry(QRect(280, 470, 550, 23)); + progressBar->setValue(0); + label_exectime = new QLabel(centralWidget); + label_exectime->setObjectName(QStringLiteral("label_exectime")); + label_exectime->setGeometry(QRect(10, 400, 121, 16)); + label_fps_txt = new QLabel(centralWidget); + label_fps_txt->setObjectName(QStringLiteral("label_fps_txt")); + label_fps_txt->setGeometry(QRect(210, 400, 55, 16)); + label_fps_txt->setLayoutDirection(Qt::LeftToRight); + label_fps_txt->setFrameShape(QFrame::Box); + label_fps_txt->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + label_framenumber = new QLabel(centralWidget); + label_framenumber->setObjectName(QStringLiteral("label_framenumber")); + label_framenumber->setGeometry(QRect(10, 420, 121, 16)); + label_framenumber_txt = new QLabel(centralWidget); + label_framenumber_txt->setObjectName(QStringLiteral("label_framenumber_txt")); + label_framenumber_txt->setGeometry(QRect(210, 420, 55, 16)); + label_framenumber_txt->setLayoutDirection(Qt::LeftToRight); + label_framenumber_txt->setFrameShape(QFrame::Box); + label_framenumber_txt->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + label_status = new QLabel(centralWidget); + label_status->setObjectName(QStringLiteral("label_status")); + label_status->setGeometry(QRect(209, 470, 61, 23)); + label_frameres = new QLabel(centralWidget); + label_frameres->setObjectName(QStringLiteral("label_frameres")); + label_frameres->setGeometry(QRect(10, 440, 121, 16)); + label_frameresw_txt = new QLabel(centralWidget); + label_frameresw_txt->setObjectName(QStringLiteral("label_frameresw_txt")); + label_frameresw_txt->setGeometry(QRect(140, 440, 55, 16)); + label_frameresw_txt->setLayoutDirection(Qt::LeftToRight); + label_frameresw_txt->setFrameShape(QFrame::Box); + label_frameresw_txt->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + label_frameresh_txt = new QLabel(centralWidget); + label_frameresh_txt->setObjectName(QStringLiteral("label_frameresh_txt")); + label_frameresh_txt->setGeometry(QRect(210, 440, 55, 16)); + label_frameresh_txt->setLayoutDirection(Qt::LeftToRight); + label_frameresh_txt->setFrameShape(QFrame::Box); + label_frameresh_txt->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + label_frameres_2 = new QLabel(centralWidget); + label_frameres_2->setObjectName(QStringLiteral("label_frameres_2")); + label_frameres_2->setGeometry(QRect(193, 440, 21, 16)); + label_frameres_2->setAlignment(Qt::AlignCenter); + lineEdit_out_in = new QLineEdit(centralWidget); + lineEdit_out_in->setObjectName(QStringLiteral("lineEdit_out_in")); + lineEdit_out_in->setGeometry(QRect(348, 400, 140, 20)); + pushButton_out_in = new QPushButton(centralWidget); + pushButton_out_in->setObjectName(QStringLiteral("pushButton_out_in")); + pushButton_out_in->setGeometry(QRect(490, 400, 40, 20)); + lineEdit_out_fg = new QLineEdit(centralWidget); + lineEdit_out_fg->setObjectName(QStringLiteral("lineEdit_out_fg")); + lineEdit_out_fg->setGeometry(QRect(608, 400, 140, 20)); + pushButton_out_fg = new QPushButton(centralWidget); + pushButton_out_fg->setObjectName(QStringLiteral("pushButton_out_fg")); + pushButton_out_fg->setGeometry(QRect(750, 400, 40, 20)); + pushButton_out_bg = new QPushButton(centralWidget); + pushButton_out_bg->setObjectName(QStringLiteral("pushButton_out_bg")); + pushButton_out_bg->setGeometry(QRect(1010, 400, 40, 20)); + lineEdit_out_bg = new QLineEdit(centralWidget); + lineEdit_out_bg->setObjectName(QStringLiteral("lineEdit_out_bg")); + lineEdit_out_bg->setGeometry(QRect(868, 400, 140, 20)); + checkBox_kfn = new QCheckBox(centralWidget); + checkBox_kfn->setObjectName(QStringLiteral("checkBox_kfn")); + checkBox_kfn->setGeometry(QRect(280, 420, 141, 20)); + checkBox_kfn->setChecked(true); + MainWindow->setCentralWidget(centralWidget); + menuBar = new QMenuBar(MainWindow); + menuBar->setObjectName(QStringLiteral("menuBar")); + menuBar->setGeometry(QRect(0, 0, 1070, 26)); + menuBGSLibrary = new QMenu(menuBar); + menuBGSLibrary->setObjectName(QStringLiteral("menuBGSLibrary")); + MainWindow->setMenuBar(menuBar); + statusBar = new QStatusBar(MainWindow); + statusBar->setObjectName(QStringLiteral("statusBar")); + MainWindow->setStatusBar(statusBar); + + menuBar->addAction(menuBGSLibrary->menuAction()); + menuBGSLibrary->addAction(actionExit); + + retranslateUi(MainWindow); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "BGSLibrary QT GUI", 0)); + actionExit->setText(QApplication::translate("MainWindow", "Exit", 0)); + label_algorithms->setText(QApplication::translate("MainWindow", "Algorithms", 0)); + label_inputdata->setText(QApplication::translate("MainWindow", "Input (specify a video file or a directory path containing the sequence of images)", 0)); + lineEdit_inputdata->setText(QApplication::translate("MainWindow", "./dataset/video.avi", 0)); + pushButton_inputdata->setText(QApplication::translate("MainWindow", "...", 0)); + checkBox_webcamera->setText(QApplication::translate("MainWindow", "Use web camera", 0)); + checkBox_imageseq->setText(QApplication::translate("MainWindow", "Sequence of images?", 0)); + label_startat->setText(QApplication::translate("MainWindow", "Start at:", 0)); + label_stopat->setText(QApplication::translate("MainWindow", "Stop at:", 0)); + label_input->setText(QApplication::translate("MainWindow", "Input", 0)); + label_img_in->setText(QApplication::translate("MainWindow", "IMG_INPUT", 0)); + label_img_fg->setText(QApplication::translate("MainWindow", "IMG_FOREGROUND", 0)); + label_img_bg->setText(QApplication::translate("MainWindow", "IMG_BACKGROUND", 0)); + label_foreground->setText(QApplication::translate("MainWindow", "Foreground mask", 0)); + label_background->setText(QApplication::translate("MainWindow", "Background model", 0)); + checkBox_save_im->setText(QApplication::translate("MainWindow", "Save", 0)); + checkBox_save_fg->setText(QApplication::translate("MainWindow", "Save", 0)); + checkBox_save_bg->setText(QApplication::translate("MainWindow", "Save", 0)); + pushButton_stop->setText(QApplication::translate("MainWindow", "Stop", 0)); + pushButton_start->setText(QApplication::translate("MainWindow", "Start", 0)); + label_exectime->setText(QApplication::translate("MainWindow", "Estimated FPS:", 0)); + label_fps_txt->setText(QApplication::translate("MainWindow", "0", 0)); + label_framenumber->setText(QApplication::translate("MainWindow", "Frame number:", 0)); + label_framenumber_txt->setText(QApplication::translate("MainWindow", "0", 0)); + label_status->setText(QApplication::translate("MainWindow", "Progress:", 0)); + label_frameres->setText(QApplication::translate("MainWindow", "Frame resolution:", 0)); + label_frameresw_txt->setText(QApplication::translate("MainWindow", "0", 0)); + label_frameresh_txt->setText(QApplication::translate("MainWindow", "0", 0)); + label_frameres_2->setText(QApplication::translate("MainWindow", "x", 0)); + lineEdit_out_in->setText(QApplication::translate("MainWindow", "./output/in/", 0)); + pushButton_out_in->setText(QApplication::translate("MainWindow", "...", 0)); + lineEdit_out_fg->setText(QApplication::translate("MainWindow", "./output/fg/", 0)); + pushButton_out_fg->setText(QApplication::translate("MainWindow", "...", 0)); + pushButton_out_bg->setText(QApplication::translate("MainWindow", "...", 0)); + lineEdit_out_bg->setText(QApplication::translate("MainWindow", "./output/bg/", 0)); + checkBox_kfn->setText(QApplication::translate("MainWindow", "Keep frame number", 0)); + menuBGSLibrary->setTitle(QApplication::translate("MainWindow", "BGSLibrary", 0)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/output/bg/.gitignore b/output/bg/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e2a98bb114355ae964e78a929c12d44f75815de --- /dev/null +++ b/output/bg/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore diff --git a/output/fg/.gitignore b/output/fg/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e2a98bb114355ae964e78a929c12d44f75815de --- /dev/null +++ b/output/fg/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore diff --git a/output/in/.gitignore b/output/in/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e2a98bb114355ae964e78a929c12d44f75815de --- /dev/null +++ b/output/in/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore diff --git a/package_bgs/tb/PerformanceUtils.cpp b/package_analysis/PerformanceUtils.cpp similarity index 59% rename from package_bgs/tb/PerformanceUtils.cpp rename to package_analysis/PerformanceUtils.cpp index 0d7cf771dee40bc06b5192718710f78587d99441..6ad5e5faa64d7b746eba212fd2df8313dcb64365 100644 --- a/package_bgs/tb/PerformanceUtils.cpp +++ b/package_analysis/PerformanceUtils.cpp @@ -15,15 +15,16 @@ 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/legacy/compat.hpp> +//#include <opencv2/highgui/highgui_c.h> -PerformanceUtils::PerformanceUtils(void){} +PerformanceUtils::PerformanceUtils(void) {} -PerformanceUtils::~PerformanceUtils(void){} +PerformanceUtils::~PerformanceUtils(void) {} float PerformanceUtils::NrPixels(IplImage *image) { - return (float) (image->width * image->height); + return (float)(image->width * image->height); } float PerformanceUtils::NrAllDetectedPixNotNULL(IplImage *image, IplImage *ground_truth) @@ -31,19 +32,19 @@ float PerformanceUtils::NrAllDetectedPixNotNULL(IplImage *image, IplImage *groun //Nombre de tous les pixels non nuls dans Groundthruth et dans image float Union12 = 0.0; - unsigned char *pixelGT = (unsigned char*) malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char*) malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char*)malloc(1 * sizeof(unsigned char)); PixelUtils p; - for(int y = 0; y < image->height; y++) + 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); + 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)) Union12++; } } @@ -51,44 +52,44 @@ float PerformanceUtils::NrAllDetectedPixNotNULL(IplImage *image, IplImage *groun free(pixelGT); free(pixelI); - return Union12; + return Union12; } float PerformanceUtils::NrTruePositives(IplImage *image, IplImage *ground_truth, bool debug) { float nTP = 0.0; - unsigned char *pixelGT = (unsigned char*) malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char*) malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char*)malloc(1 * sizeof(unsigned char)); IplImage *TPimage = 0; - if(debug) + if (debug) { - TPimage = cvCreateImage(cvSize(image->width,image->height),image->depth,image->nChannels); - cvFillImage(TPimage,0.0); + 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 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); + 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); + if (debug) + p.PutGrayPixel(TPimage, x, y, *pixelI); nTP++; } } } - if(debug) + if (debug) { cvNamedWindow("TPImage", 0); cvShowImage("TPImage", TPimage); @@ -101,46 +102,46 @@ float PerformanceUtils::NrTruePositives(IplImage *image, IplImage *ground_truth, free(pixelGT); free(pixelI); - return nTP; + return nTP; } float PerformanceUtils::NrTrueNegatives(IplImage* image, IplImage* ground_truth, bool debug) { float nTN = 0.0; - unsigned char *pixelGT = (unsigned char *)malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char *)malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char *)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char *)malloc(1 * sizeof(unsigned char)); IplImage *TNimage = 0; - if(debug) + if (debug) { - TNimage = cvCreateImage(cvSize(image->width,image->height),image->depth,image->nChannels); - cvFillImage(TNimage, 0.0); + 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 y = 0; y < image->height; y++) { - for(int x = 0; x < image->width; x++) + for (int x = 0; x < image->width; x++) { - p.GetGrayPixel(ground_truth,x,y,pixelGT); - p.GetGrayPixel(image,x,y,pixelI); + 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); + if (debug) + p.PutGrayPixel(TNimage, x, y, *pixelI); nTN++; - } + } } } - if(debug) + if (debug) { cvNamedWindow("TNImage", 0); cvShowImage("TNImage", TNimage); @@ -156,41 +157,41 @@ float PerformanceUtils::NrTrueNegatives(IplImage* image, IplImage* ground_truth, return nTN; } -float PerformanceUtils::NrFalsePositives(IplImage *image, IplImage *ground_truth,bool debug) +float PerformanceUtils::NrFalsePositives(IplImage *image, IplImage *ground_truth, bool debug) { float nFP = 0.0; - unsigned char *pixelGT = (unsigned char*) malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char*) malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char*)malloc(1 * sizeof(unsigned char)); IplImage *FPimage = 0; - if(debug) + if (debug) { - FPimage = cvCreateImage(cvSize(image->width,image->height),image->depth,image->nChannels); - cvFillImage(FPimage, 0.0); + 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 y = 0; y < image->height; y++) { - for(int x = 0; x < image->width; x++) + for (int x = 0; x < image->width; x++) { - p.GetGrayPixel(ground_truth,x,y,pixelGT); - p.GetGrayPixel(image,x,y,pixelI); + 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); + if (debug) + p.PutGrayPixel(FPimage, x, y, *pixelI); nFP++; } } } - if(debug) + if (debug) { cvNamedWindow("FPImage", 0); cvShowImage("FPImage", FPimage); @@ -203,44 +204,44 @@ float PerformanceUtils::NrFalsePositives(IplImage *image, IplImage *ground_truth free(pixelGT); free(pixelI); - return nFP; + return nFP; } float PerformanceUtils::NrFalseNegatives(IplImage * image, IplImage *ground_truth, bool debug) { float nFN = 0.0; - unsigned char *pixelGT = (unsigned char*) malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char*) malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char*)malloc(1 * sizeof(unsigned char)); IplImage *FNimage = 0; - if(debug) + if (debug) { - FNimage = cvCreateImage(cvSize(image->width,image->height),image->depth,image->nChannels); - cvFillImage(FNimage, 0.0); + 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 y = 0; y < image->height; y++) { - for(int x = 0; x < image->width; x++) + for (int x = 0; x < image->width; x++) { - p.GetGrayPixel(ground_truth,x,y,pixelGT); - p.GetGrayPixel(image,x,y,pixelI); + 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); + if (debug) + p.PutGrayPixel(FNimage, x, y, *pixelGT); nFN++; } } } - if(debug) + if (debug) { cvNamedWindow("FNImage", 0); cvShowImage("FNImage", FNimage); @@ -253,19 +254,19 @@ float PerformanceUtils::NrFalseNegatives(IplImage * image, IplImage *ground_trut free(pixelGT); free(pixelI); - return nFN; + return nFN; } float PerformanceUtils::SimilarityMeasure(IplImage *image, IplImage *ground_truth, bool debug) { - cv::Mat img_input(image,true); - cv::Mat img_ref(ground_truth,true); + cv::Mat img_input = cv::cvarrToMat(image, true); + cv::Mat img_ref = cv::cvarrToMat(ground_truth, true); int rn = cv::countNonZero(img_ref); cv::Mat i; cv::Mat u; - if(rn > 0) + if (rn > 0) { i = img_input & img_ref; u = img_input | img_ref; @@ -278,16 +279,16 @@ float PerformanceUtils::SimilarityMeasure(IplImage *image, IplImage *ground_trut int in = cv::countNonZero(i); int un = cv::countNonZero(u); - + double s = (((double)in) / ((double)un)); - - if(debug) + + if (debug) { cv::imshow("A^B", i); cv::imshow("AvB", u); //std::cout << "Similarity Measure: " << s << std::endl; - + //<< " press ENTER to continue" << std::endl; //cv::waitKey(0); } @@ -295,45 +296,45 @@ float PerformanceUtils::SimilarityMeasure(IplImage *image, IplImage *ground_trut return s; } -void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool saveResults, char* filename) +void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool saveResults, std::string filename) { - unsigned char *pixelGT = (unsigned char*) malloc(1*sizeof(unsigned char)); - unsigned char *pixelI = (unsigned char*) malloc(1*sizeof(unsigned char)); + unsigned char *pixelGT = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelI = (unsigned char*)malloc(1 * sizeof(unsigned char)); - IplImage *ROCimage = cvCreateImage(cvSize(image->width,image->height),image->depth,image->nChannels); - cvFillImage(ROCimage, 0.0); + IplImage *ROCimage = cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels); + cvSetZero(ROCimage); PixelUtils p; - for(int y = 0; y < image->height; y++) + for (int y = 0; y < image->height; y++) { - for(int x = 0; x < image->width; x++) + for (int x = 0; x < image->width; x++) { - p.GetGrayPixel(ground_truth,x,y,pixelGT); - p.GetGrayPixel(image,x,y,pixelI); + 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); + 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); - } + 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); + 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); + p.PutGrayPixel(ROCimage, x, y, *pixelI); } } } @@ -341,10 +342,10 @@ 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)); + unsigned char *pixelOI = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char *pixelROC = (unsigned char*)malloc(1 * sizeof(unsigned char)); float** freq; float nTP = 0.0; @@ -352,45 +353,45 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa float nFP = 0.0; float nFN = 0.0; - freq = (float**) malloc(256*(sizeof(float*))); - for(int i = 0; i < 256; i++) - freq[i] = (float*) malloc(7 * (sizeof(float))); + freq = (float**)malloc(256 * (sizeof(float*))); + for (int i = 0; i < 256; i++) + freq[i] = (float*)malloc(7 * (sizeof(float))); - for(int i = 0; i < 256; i++) - for(int j = 0; j < 6; j++) + for (int i = 0; i < 256; i++) + for (int j = 0; j < 6; j++) freq[i][j] = 0.0; - for(int y = 0; y < image->height; y++) + for (int y = 0; y < image->height; y++) { - for(int x = 0; x < image->width; x++) + for (int x = 0; x < image->width; x++) { - for(int i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { - p.GetGrayPixel(image,x,y,pixelOI); - p.GetGrayPixel(ROCimage,x,y,pixelROC); + 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; @@ -409,17 +410,17 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa std::ofstream f(filename); - if(!f.is_open()) + if (!f.is_open()) std::cout << "Failed to open file " << filename << " for writing!" << std::endl; 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); @@ -429,12 +430,12 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa ////fprintf(f," %4d %1.6f %1.6f\n",i,freq[i][5],freq[i][4]); ////fprintf(f," %1.6f %1.6f\n",freq[i][5],freq[i][4]); char line[255]; - sprintf(line,"%3d %6.0f %6.0f %6.0f %6.0f %1.6f %1.6f %1.6f\n", + sprintf(line, "%3d %6.0f %6.0f %6.0f %6.0f %1.6f %1.6f %1.6f\n", i, freq[i][0], freq[i][1], freq[i][2], freq[i][3], freq[i][5], freq[i][4], freq[i][6]); f << line; } //else - //printf("\n"); + //printf("\n"); } std::cout << "Results saved in " << filename << std::endl; @@ -454,36 +455,36 @@ void PerformanceUtils::ImageROC(IplImage *image, IplImage* ground_truth, bool sa free(pixelI); } -void PerformanceUtils::PerformanceEvaluation(IplImage *image, IplImage *ground_truth, bool saveResults, char* filename, bool debug) +void PerformanceUtils::PerformanceEvaluation(IplImage *image, IplImage *ground_truth, bool saveResults, std::string filename, bool debug) { float N = 0; N = NrPixels(image); float U = 0; U = NrAllDetectedPixNotNULL(image, ground_truth); - + float TP = 0; TP = NrTruePositives(image, ground_truth, debug); - + float TN = 0; TN = NrTrueNegatives(image, ground_truth, debug); - + float FP = 0; FP = NrFalsePositives(image, ground_truth, debug); - + float FN = 0; FN = NrFalseNegatives(image, ground_truth, debug); - + float DetectionRate = TP / (TP + FN); float Precision = TP / (TP + FP); float Fmeasure = (2 * DetectionRate * Precision) / (DetectionRate + Precision); float Accuracy = (TN + TP) / N; float FalseNegativeRate = FN / (TP + FN); - + float FalsePositiveRate = FP / (FP + TN); float TruePositiveRate = TP / (TP + FN); - + float SM = 0; SM = SimilarityMeasure(image, ground_truth, debug); @@ -506,11 +507,11 @@ 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()) + if (!f.is_open()) std::cout << "Failed to open file " << filename << " for writing!" << std::endl; else { diff --git a/package_bgs/tb/PerformanceUtils.h b/package_analysis/PerformanceUtils.h similarity index 82% rename from package_bgs/tb/PerformanceUtils.h rename to package_analysis/PerformanceUtils.h index 9257098386e13a2d2a1cb61382affa074ab981a6..4be392f53a1b40fc1096d448809ff7a7919097a8 100644 --- a/package_bgs/tb/PerformanceUtils.h +++ b/package_analysis/PerformanceUtils.h @@ -15,23 +15,11 @@ 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 -/* -Code provided by Thierry BOUWMANS - -Maitre de Conf�rences -Laboratoire MIA -Universit� de La Rochelle -17000 La Rochelle -France -tbouwman@univ-lr.fr -http://sites.google.com/site/thierrybouwmans/ -*/ #include <stdio.h> #include <fstream> #include <opencv2/opencv.hpp> - #include "PixelUtils.h" class PerformanceUtils @@ -48,7 +36,7 @@ public: 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, char* filename = ""); - void PerformanceEvaluation(IplImage *image, IplImage *ground_truth, bool saveResults = false, char* filename = "", 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/package_analysis/PixelUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adce122f642ec9260254921999f6954bce28dc03 --- /dev/null +++ b/package_analysis/PixelUtils.cpp @@ -0,0 +1,351 @@ +/* +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) {} + +void PixelUtils::ColorConversion(IplImage* RGBImage, IplImage* ConvertedImage, int color_space) +{ + // Space Color RGB - Nothing to do! + if (color_space == 1) + cvCopy(RGBImage, ConvertedImage); + + // Space Color Ohta + if (color_space == 2) + cvttoOTHA(RGBImage, ConvertedImage); + + // Space Color HSV - V Intensity - (H,S) Chromaticity + if (color_space == 3) + cvCvtColor(RGBImage, ConvertedImage, CV_BGR2HSV); + + // Space Color YCrCb - Y Intensity - (Cr,Cb) Chromaticity + if (color_space == 4) + cvCvtColor(RGBImage, ConvertedImage, CV_BGR2YCrCb); +} + +void PixelUtils::cvttoOTHA(IplImage* RGBImage, IplImage* OthaImage) +{ + float* OhtaPixel = (float*)malloc(3 * (sizeof(float))); + float* RGBPixel = (float*)malloc(3 * (sizeof(float))); + + for (int i = 0; i < RGBImage->width; i++) + { + for (int j = 0; j < RGBImage->height; j++) + { + GetPixel(RGBImage, i, j, RGBPixel); + + // I1 = (R + G + B) / 3 + *OhtaPixel = (*(RGBPixel)+(*(RGBPixel + 1)) + (*(RGBPixel + 2))) / 3.0; + + // I2 = (R - B) / 2 + *(OhtaPixel + 1) = (*RGBPixel - (*(RGBPixel + 2))) / 2.0; + + // I3 = (2G - R - B) / 4 + *(OhtaPixel + 2) = (2 * (*(RGBPixel + 1)) - (*RGBPixel) - (*(RGBPixel + 2))) / 4.0; + + PutPixel(OthaImage, i, j, OhtaPixel); + } + } + + free(OhtaPixel); + free(RGBPixel); +} + +void PixelUtils::PostProcessing(IplImage *InputImage) +{ + IplImage *ResultImage = cvCreateImage(cvSize(InputImage->width, InputImage->height), IPL_DEPTH_32F, 3); + + cvErode(InputImage, ResultImage, NULL, 1); + cvDilate(ResultImage, InputImage, NULL, 0); + + cvReleaseImage(&ResultImage); +} + +void PixelUtils::GetPixel(IplImage *image, int m, int n, unsigned char *pixelcourant) +{ + for (int k = 0; k < 3; k++) + pixelcourant[k] = ((unsigned char*)(image->imageData + image->widthStep*n))[m * 3 + k]; +} + +void PixelUtils::GetGrayPixel(IplImage *image, int m, int n, unsigned char *pixelcourant) +{ + *pixelcourant = ((unsigned char*)(image->imageData + image->widthStep*n))[m]; +} + +void PixelUtils::PutPixel(IplImage *image, int p, int q, unsigned char *pixelcourant) +{ + for (int r = 0; r < 3; r++) + ((unsigned char*)(image->imageData + image->widthStep*q))[p * 3 + r] = pixelcourant[r]; +} + +void PixelUtils::PutGrayPixel(IplImage *image, int p, int q, unsigned char pixelcourant) +{ + ((unsigned char*)(image->imageData + image->widthStep*q))[p] = pixelcourant; +} + +void PixelUtils::GetPixel(IplImage *image, int m, int n, float *pixelcourant) +{ + for (int k = 0; k < 3; k++) + pixelcourant[k] = ((float*)(image->imageData + image->widthStep*n))[m * 3 + k]; +} + +void PixelUtils::GetGrayPixel(IplImage *image, int m, int n, float *pixelcourant) +{ + *pixelcourant = ((float*)(image->imageData + image->widthStep*n))[m]; +} + +void PixelUtils::PutPixel(IplImage *image, int p, int q, float *pixelcourant) +{ + for (int r = 0; r < 3; r++) + ((float*)(image->imageData + image->widthStep*q))[p * 3 + r] = pixelcourant[r]; +} + +void PixelUtils::PutGrayPixel(IplImage *image, int p, int q, float pixelcourant) +{ + ((float*)(image->imageData + image->widthStep*q))[p] = pixelcourant; +} + +void PixelUtils::getNeighberhoodGrayPixel(IplImage* InputImage, int x, int y, float* neighberPixel) +{ + int i, j, k; + + float* pixelCourant = (float*)malloc(1 * (sizeof(float))); + + //le calcul de voisinage pour les 4 coins; + /* 1.*/ + if (x == 0 && y == 0) + { + k = 0; + for (i = x; i < x + 2; i++) + for (j = y; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + /* 2.*/ + if (x == 0 && y == InputImage->width) + { + k = 0; + for (i = x; i < x + 2; i++) + for (j = y - 1; j < y + 1; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + /* 3.*/ + if (x == InputImage->height && y == 0) + { + k = 0; + for (i = x - 1; i < x + 1; i++) + for (j = y; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + /* 4.*/ + if (x == InputImage->height && y == InputImage->width) + { + k = 0; + for (i = x - 1; i < x + 1; i++) + for (j = y - 1; j < y + 1; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + // Voisinage de la premiere ligne : L(0) + if (x == 0 && (y != 0 && y != InputImage->width)) + { + k = 0; + for (i = x + 1; i >= x; i--) + for (j = y - 1; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + // Voisinage de la dernière colonne : C(w) + if ((x != 0 && x != InputImage->height) && y == InputImage->width) + { + k = 0; + for (i = x + 1; i > x - 2; i--) + for (j = y - 1; j < y + 1; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + // Voisinage de la dernière ligne : L(h) + if (x == InputImage->height && (y != 0 && y != InputImage->width)) + { + k = 0; + for (i = x; i > x - 2; i--) + for (j = y - 1; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + // Voisinage de la premiere colonne : C(0) + if ((x != 0 && x != InputImage->height) && y == 0) + { + k = 0; + for (i = x - 1; i < x + 2; i++) + for (j = y; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + //le calcul du voisinage pour le reste des elementes d'image + if ((x != 0 && x != InputImage->height) && (y != 0 && y != InputImage->width)) + { + k = 0; + for (i = x + 1; i > x - 2; i--) + for (j = y - 1; j < y + 2; j++) + { + GetGrayPixel(InputImage, i, j, pixelCourant); + *(neighberPixel + k) = *pixelCourant; + k++; + } + } + + free(pixelCourant); +} + +void PixelUtils::ForegroundMinimum(IplImage *Foreground, float *Minimum, int n) +{ + int i, j, k; + float *pixelcourant; + + pixelcourant = (float *)malloc(n * sizeof(float)); + + for (k = 0; k < n; k++) + *(Minimum + k) = 255; + + for (i = 0; i < Foreground->width; i++) + for (j = 0; j < Foreground->height; j++) + { + if (n == 3) + { + GetPixel(Foreground, i, j, pixelcourant); + + for (k = 0; k < n; k++) + if (*(pixelcourant + k) < *(Minimum + k)) + *(Minimum + k) = *(pixelcourant + k); + } + + if (n == 1) + { + GetGrayPixel(Foreground, i, j, pixelcourant); + + if (*pixelcourant < *Minimum) + *Minimum = *pixelcourant; + } + } + + free(pixelcourant); +} + +void PixelUtils::ForegroundMaximum(IplImage *Foreground, float *Maximum, int n) +{ + int i, j, k; + float *pixelcourant; + + pixelcourant = (float *)malloc(n * sizeof(float)); + + for (k = 0; k < n; k++) + *(Maximum + k) = 0; + + for (i = 0; i < Foreground->width; i++) + for (j = 0; j < Foreground->height; j++) + { + if (n == 3) + { + GetPixel(Foreground, i, j, pixelcourant); + + for (k = 0; k < n; k++) + if (*(pixelcourant + k) > *(Maximum + k)) + *(Maximum + k) = *(pixelcourant + k); + } + + if (n == 1) + { + GetGrayPixel(Foreground, i, j, pixelcourant); + + if (*pixelcourant > *Maximum) + *Maximum = *pixelcourant; + } + } + + free(pixelcourant); +} + +void PixelUtils::ComplementaryAlphaImageCreation(IplImage *AlphaImage, IplImage *ComplementaryAlphaImage, int n) +{ + int i, j, k; + float *pixelcourant, *pixelcourant1; + + pixelcourant = (float *)malloc(n * sizeof(float)); + pixelcourant1 = (float *)malloc(n * sizeof(float)); + + for (i = 0; i < AlphaImage->width; i++) + for (j = 0; j < AlphaImage->height; j++) + { + if (n == 1) + { + GetGrayPixel(AlphaImage, i, j, pixelcourant); + *pixelcourant1 = 1 - *(pixelcourant); + PutGrayPixel(ComplementaryAlphaImage, i, j, *pixelcourant1); + } + + if (n == 3) + { + GetPixel(AlphaImage, i, j, pixelcourant); + for (k = 0; k < 3; k++) + { + *pixelcourant1 = 1.0 - *(pixelcourant); + *(pixelcourant1 + 1) = 1.0 - *(pixelcourant + 1); + *(pixelcourant1 + 2) = 1.0 - *(pixelcourant + 2); + } + PutPixel(ComplementaryAlphaImage, i, j, pixelcourant1); + } + } + + free(pixelcourant); + free(pixelcourant1); +} diff --git a/package_bgs/tb/PixelUtils.h b/package_analysis/PixelUtils.h similarity index 90% rename from package_bgs/tb/PixelUtils.h rename to package_analysis/PixelUtils.h index a2d3a4af3d5838fc0e1b870507ecacbcacf9d955..0e35c4055421c76d5bdb0af91fee4c6008b98253 100644 --- a/package_bgs/tb/PixelUtils.h +++ b/package_analysis/PixelUtils.h @@ -15,22 +15,10 @@ 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 -/* -Code provided by Thierry BOUWMANS - -Maitre de Conf�rences -Laboratoire MIA -Universit� de La Rochelle -17000 La Rochelle -France -tbouwman@univ-lr.fr -http://sites.google.com/site/thierrybouwmans/ -*/ #include <stdio.h> #include <opencv2/opencv.hpp> - class PixelUtils { public: @@ -39,9 +27,9 @@ public: 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); @@ -58,4 +46,4 @@ public: void ForegroundMaximum(IplImage *Foreground, float *Maximum, int n); void ForegroundMinimum(IplImage *Foreground, float *Minimum, int n); void ComplementaryAlphaImageCreation(IplImage *AlphaImage, IplImage *ComplementaryAlphaImage, int n); -}; \ No newline at end of file +}; diff --git a/package_bgs/AdaptiveBackgroundLearning.cpp b/package_bgs/AdaptiveBackgroundLearning.cpp index b111e65be5ca7b12274af2f91dcd1672f1bd3e36..d2cb8a0ac5fee164454b10b18d2886706987c90c 100644 --- a/package_bgs/AdaptiveBackgroundLearning.cpp +++ b/package_bgs/AdaptiveBackgroundLearning.cpp @@ -16,10 +16,14 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "AdaptiveBackgroundLearning.h" -AdaptiveBackgroundLearning::AdaptiveBackgroundLearning() : firstTime(true), alpha(0.05), limit(-1), counter(0), minVal(0.0), maxVal(1.0), - enableThreshold(true), threshold(15), showForeground(true), showBackground(true) +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() @@ -29,52 +33,48 @@ AdaptiveBackgroundLearning::~AdaptiveBackgroundLearning() void AdaptiveBackgroundLearning::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); - if(img_background.empty()) + 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.); + 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.); + 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) + if ((limit > 0 && limit < counter) || limit == -1) { - img_background_f = alpha*img_input_f + (1-alpha)*img_background_f; - + 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_background_f.convertTo(img_new_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); img_new_background.copyTo(img_background); - if(limit > 0 && limit < counter) + if (limit > 0 && limit < counter) counter++; } - - cv::Mat img_foreground(img_input.size(), CV_8U); - img_diff_f.convertTo(img_foreground, CV_8U, 255.0/(maxVal - minVal), -minVal); - if(img_foreground.channels() == 3) + //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) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - - if(showForeground) - cv::imshow("A-Learning FG", img_foreground); - if(showBackground) +#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); @@ -84,28 +84,26 @@ void AdaptiveBackgroundLearning::process(const cv::Mat &img_input, cv::Mat &img_ void AdaptiveBackgroundLearning::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/AdaptiveBackgroundLearning.xml", 0, CV_STORAGE_WRITE); + 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, "showForeground", showForeground); - cvWriteInt(fs, "showBackground", showBackground); + cvWriteInt(fs, "showOutput", showOutput); cvReleaseFileStorage(&fs); } void AdaptiveBackgroundLearning::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/AdaptiveBackgroundLearning.xml", 0, CV_STORAGE_READ); - - alpha = cvReadRealByName(fs, 0, "alpha", 0.05); - limit = cvReadIntByName(fs, 0, "limit", -1); - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showForeground = cvReadIntByName(fs, 0, "showForeground", true); - showBackground = cvReadIntByName(fs, 0, "showBackground", true); + 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 index 4bbac54ae0f4c3e42499a9878afd764e9c34ab48..3cfc686296ecdda4f582cbf5e1795032273d23fc 100644 --- a/package_bgs/AdaptiveBackgroundLearning.h +++ b/package_bgs/AdaptiveBackgroundLearning.h @@ -16,35 +16,32 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - #include "IBGS.h" -class AdaptiveBackgroundLearning : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Mat img_background; - double alpha; - long limit; - long counter; - double minVal; - double maxVal; - bool enableThreshold; - int threshold; - bool showForeground; - bool showBackground; - -public: - AdaptiveBackgroundLearning(); - ~AdaptiveBackgroundLearning(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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 index cd3e7d3d966ec6b2e2850d21305f15e1341889df..2f6f9fe89ba9adf4b595c05cc05a3b5fb3c51985 100644 --- a/package_bgs/AdaptiveSelectiveBackgroundLearning.cpp +++ b/package_bgs/AdaptiveSelectiveBackgroundLearning.cpp @@ -16,11 +16,14 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "AdaptiveSelectiveBackgroundLearning.h" -AdaptiveSelectiveBackgroundLearning::AdaptiveSelectiveBackgroundLearning() : firstTime(true), -alphaLearn(0.05), alphaDetection(0.05), learningFrames(-1), counter(0), minVal(0.0), maxVal(1.0), -threshold(15), showOutput(true) +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() @@ -30,8 +33,7 @@ AdaptiveSelectiveBackgroundLearning::~AdaptiveSelectiveBackgroundLearning() void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input_.empty()) - return; + init(img_input_, img_output, img_bgmodel); cv::Mat img_input; if (img_input_.channels() == 3) @@ -39,24 +41,19 @@ void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv: else img_input_.copyTo(img_input); - loadConfig(); - - if(firstTime) - saveConfig(); - - if(img_background.empty()) + 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.); + 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.); + 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); + //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); @@ -88,15 +85,17 @@ void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv: } } - 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(showOutput) + //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); @@ -106,7 +105,7 @@ void AdaptiveSelectiveBackgroundLearning::process(const cv::Mat &img_input_, cv: void AdaptiveSelectiveBackgroundLearning::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/AdaptiveSelectiveBackgroundLearning.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "learningFrames", learningFrames); cvWriteReal(fs, "alphaLearn", alphaLearn); @@ -119,13 +118,13 @@ void AdaptiveSelectiveBackgroundLearning::saveConfig() void AdaptiveSelectiveBackgroundLearning::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/AdaptiveSelectiveBackgroundLearning.xml", 0, CV_STORAGE_READ); - - learningFrames = cvReadIntByName(fs, 0, "learningFrames", 90); - alphaLearn = cvReadRealByName(fs, 0, "alphaLearn", 0.05); - alphaDetection = cvReadRealByName(fs, 0, "alphaDetection", 0.05); - threshold = cvReadIntByName(fs, 0, "threshold", 25); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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 index 227674751ae4eccf452094f680c43adf72dca961..24da44c7e025c848d5761f84eb9a95c6c96e23f5 100644 --- a/package_bgs/AdaptiveSelectiveBackgroundLearning.h +++ b/package_bgs/AdaptiveSelectiveBackgroundLearning.h @@ -16,34 +16,32 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - #include "IBGS.h" -class AdaptiveSelectiveBackgroundLearning : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Mat img_background; - double alphaLearn; - double alphaDetection; - long learningFrames; - long counter; - double minVal; - double maxVal; - int threshold; - bool showOutput; - -public: - AdaptiveSelectiveBackgroundLearning(); - ~AdaptiveSelectiveBackgroundLearning(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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 new file mode 100644 index 0000000000000000000000000000000000000000..0885580a9ce809d5d03eb978236722a4ab451bd5 --- /dev/null +++ b/package_bgs/DPAdaptiveMedian.cpp @@ -0,0 +1,110 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..7d2b7fa88bb173e2dc08413660c74a507bf7e0bd --- /dev/null +++ b/package_bgs/DPAdaptiveMedian.h @@ -0,0 +1,53 @@ +/* +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/dp/DPEigenbackgroundBGS.cpp b/package_bgs/DPEigenbackground.cpp similarity index 53% rename from package_bgs/dp/DPEigenbackgroundBGS.cpp rename to package_bgs/DPEigenbackground.cpp index 630d9cce521211c62f16408e9f3deb5f964a59c6..75763cec252faa1ef6a28fa202d201ed93213c65 100644 --- a/package_bgs/dp/DPEigenbackgroundBGS.cpp +++ b/package_bgs/DPEigenbackground.cpp @@ -14,37 +14,35 @@ 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 "DPEigenbackgroundBGS.h" +#include "DPEigenbackground.h" -DPEigenbackgroundBGS::DPEigenbackgroundBGS() : firstTime(true), frameNumber(0), threshold(225), historySize(20), embeddedDim(10), showOutput(true) +using namespace bgslibrary::algorithms; + +DPEigenbackground::DPEigenbackground() : + frameNumber(0), threshold(225), historySize(20), embeddedDim(10) { - std::cout << "DPEigenbackgroundBGS()" << std::endl; + std::cout << "DPEigenbackground()" << std::endl; + setup("./config/DPEigenbackground.xml"); } -DPEigenbackgroundBGS::~DPEigenbackgroundBGS() +DPEigenbackground::~DPEigenbackground() { - std::cout << "~DPEigenbackgroundBGS()" << std::endl; + std::cout << "~DPEigenbackground()" << std::endl; } -void DPEigenbackgroundBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPEigenbackground::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPEigenbackgroundBGS::process(const cv::Mat &img_input, cv::Mat &img_output params.SetFrameSize(width, height); params.LowThreshold() = threshold; //15*15; - params.HighThreshold() = 2*params.LowThreshold(); // Note: high threshold is used by post-processing + params.HighThreshold() = 2 * params.LowThreshold(); // Note: high threshold is used by post-processing //params.HistorySize() = 100; params.HistorySize() = historySize; //params.EmbeddedDim() = 20; @@ -68,22 +66,27 @@ void DPEigenbackgroundBGS::process(const cv::Mat &img_input, cv::Mat &img_output bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("Eigenbackground (Oliver)", foreground); + 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 - foreground.copyTo(img_output); + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); delete frame; firstTime = false; frameNumber++; } -void DPEigenbackgroundBGS::saveConfig() +void DPEigenbackground::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPEigenbackgroundBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "threshold", threshold); cvWriteInt(fs, "historySize", historySize); @@ -93,14 +96,14 @@ void DPEigenbackgroundBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPEigenbackgroundBGS::loadConfig() +void DPEigenbackground::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPEigenbackgroundBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadIntByName(fs, 0, "threshold", 225); - historySize = cvReadIntByName(fs, 0, "historySize", 20); - embeddedDim = cvReadIntByName(fs, 0, "embeddedDim", 10); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..f84fee765028a7d1c12e55e44dd1239843b5f159 --- /dev/null +++ b/package_bgs/DPEigenbackground.h @@ -0,0 +1,55 @@ +/* +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/dp/DPGrimsonGMMBGS.cpp b/package_bgs/DPGrimsonGMM.cpp similarity index 54% rename from package_bgs/dp/DPGrimsonGMMBGS.cpp rename to package_bgs/DPGrimsonGMM.cpp index ae5486024289ce9582028d10b00eded772100c73..c72b4d218303bf796340d5a3b6f5131c4c595860 100644 --- a/package_bgs/dp/DPGrimsonGMMBGS.cpp +++ b/package_bgs/DPGrimsonGMM.cpp @@ -14,37 +14,35 @@ 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 "DPGrimsonGMMBGS.h" +#include "DPGrimsonGMM.h" -DPGrimsonGMMBGS::DPGrimsonGMMBGS() : firstTime(true), frameNumber(0), threshold(9.0), alpha(0.01), gaussians(3), showOutput(true) +using namespace bgslibrary::algorithms; + +DPGrimsonGMM::DPGrimsonGMM() : + frameNumber(0), threshold(9.0), alpha(0.01), gaussians(3) { - std::cout << "DPGrimsonGMMBGS()" << std::endl; + std::cout << "DPGrimsonGMM()" << std::endl; + setup("./config/DPGrimsonGMM.xml"); } -DPGrimsonGMMBGS::~DPGrimsonGMMBGS() +DPGrimsonGMM::~DPGrimsonGMM() { - std::cout << "~DPGrimsonGMMBGS()" << std::endl; + std::cout << "~DPGrimsonGMM()" << std::endl; } -void DPGrimsonGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPGrimsonGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPGrimsonGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv: 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.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; @@ -67,22 +65,27 @@ void DPGrimsonGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv: bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("GMM (Grimson)", foreground); - - foreground.copyTo(img_output); + 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 DPGrimsonGMMBGS::saveConfig() +void DPGrimsonGMM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPGrimsonGMMBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -92,14 +95,14 @@ void DPGrimsonGMMBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPGrimsonGMMBGS::loadConfig() +void DPGrimsonGMM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPGrimsonGMMBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 9.0); - alpha = cvReadRealByName(fs, 0, "alpha", 0.01); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/dp/DPEigenbackgroundBGS.h b/package_bgs/DPGrimsonGMM.h similarity index 53% rename from package_bgs/dp/DPEigenbackgroundBGS.h rename to package_bgs/DPGrimsonGMM.h index cd4e54c3eb433640ff58895e1349660ce5ee3089..dcc05eb1b3b79c46f207898b0668508670eb6d3d 100644 --- a/package_bgs/dp/DPEigenbackgroundBGS.h +++ b/package_bgs/DPGrimsonGMM.h @@ -16,41 +16,40 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "Eigenbackground.h" +#include "IBGS.h" +#include "dp/GrimsonGMM.h" using namespace Algorithms::BackgroundSubtraction; -class DPEigenbackgroundBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - EigenbackgroundParams params; - Eigenbackground bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - int threshold; - int historySize; - int embeddedDim; - bool showOutput; - -public: - DPEigenbackgroundBGS(); - ~DPEigenbackgroundBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/dp/DPMeanBGS.cpp b/package_bgs/DPMean.cpp similarity index 55% rename from package_bgs/dp/DPMeanBGS.cpp rename to package_bgs/DPMean.cpp index 13260b469c9d8eb50d05d9218513b46983162a37..3af1fb644ead27c5597c3bfdbe047c5f6270537e 100644 --- a/package_bgs/dp/DPMeanBGS.cpp +++ b/package_bgs/DPMean.cpp @@ -14,37 +14,35 @@ 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 "DPMeanBGS.h" +#include "DPMean.h" -DPMeanBGS::DPMeanBGS() : firstTime(true), frameNumber(0), threshold(2700), alpha(1e-6f), learningFrames(30), showOutput(true) +using namespace bgslibrary::algorithms; + +DPMean::DPMean() : + frameNumber(0), threshold(2700), alpha(1e-6f), learningFrames(30) { - std::cout << "DPMeanBGS()" << std::endl; + std::cout << "DPMean()" << std::endl; + setup("./config/DPMean.xml"); } -DPMeanBGS::~DPMeanBGS() +DPMean::~DPMean() { - std::cout << "~DPMeanBGS()" << std::endl; + std::cout << "~DPMean()" << std::endl; } -void DPMeanBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPMean::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPMeanBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & 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.HighThreshold() = 2 * params.LowThreshold(); // Note: high threshold is used by post-processing //params.Alpha() = 1e-6f; params.Alpha() = alpha; params.LearningFrames() = learningFrames;//30; @@ -67,22 +65,27 @@ void DPMeanBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("Temporal Mean (Donovan Parks)", foreground); + 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 - foreground.copyTo(img_output); + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); delete frame; firstTime = false; frameNumber++; } -void DPMeanBGS::saveConfig() +void DPMean::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPMeanBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -92,14 +95,14 @@ void DPMeanBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPMeanBGS::loadConfig() +void DPMean::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPMeanBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadIntByName(fs, 0, "threshold", 2700); - alpha = cvReadRealByName(fs, 0, "alpha", 1e-6f); - learningFrames = cvReadIntByName(fs, 0, "learningFrames", 30); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/dp/DPZivkovicAGMMBGS.h b/package_bgs/DPMean.h similarity index 56% rename from package_bgs/dp/DPZivkovicAGMMBGS.h rename to package_bgs/DPMean.h index 775226a3807311224ea66b48c9f33ac05820b4b4..60299680675ba0c711055109e2ed59eebde018c5 100644 --- a/package_bgs/dp/DPZivkovicAGMMBGS.h +++ b/package_bgs/DPMean.h @@ -16,41 +16,40 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "ZivkovicAGMM.h" +#include "IBGS.h" +#include "dp/MeanBGS.h" using namespace Algorithms::BackgroundSubtraction; -class DPZivkovicAGMMBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - ZivkovicParams params; - ZivkovicAGMM bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - double threshold; - double alpha; - int gaussians; - bool showOutput; - -public: - DPZivkovicAGMMBGS(); - ~DPZivkovicAGMMBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/dp/DPPratiMediodBGS.cpp b/package_bgs/DPPratiMediod.cpp similarity index 53% rename from package_bgs/dp/DPPratiMediodBGS.cpp rename to package_bgs/DPPratiMediod.cpp index ba1d6be81fa337f44e6f9126646112d358622f02..d1942c53ce2f4fe758ced5f5631239e4f6dff925 100644 --- a/package_bgs/dp/DPPratiMediodBGS.cpp +++ b/package_bgs/DPPratiMediod.cpp @@ -14,37 +14,35 @@ 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 "DPPratiMediodBGS.h" +#include "DPPratiMediod.h" -DPPratiMediodBGS::DPPratiMediodBGS() : firstTime(true), frameNumber(0), threshold(30), samplingRate(5), historySize(16), weight(5), showOutput(true) +using namespace bgslibrary::algorithms; + +DPPratiMediod::DPPratiMediod() : + frameNumber(0), threshold(30), samplingRate(5), historySize(16), weight(5) { - std::cout << "DPPratiMediodBGS()" << std::endl; + std::cout << "DPPratiMediod()" << std::endl; + setup("./config/DPPratiMediod.xml"); } -DPPratiMediodBGS::~DPPratiMediodBGS() +DPPratiMediod::~DPPratiMediod() { - std::cout << "~DPPratiMediodBGS()" << std::endl; + std::cout << "~DPPratiMediod()" << std::endl; } -void DPPratiMediodBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPPratiMediod::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPPratiMediodBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv params.SetFrameSize(width, height); params.LowThreshold() = threshold; - params.HighThreshold() = 2*params.LowThreshold(); // Note: high threshold is used by post-processing + params.HighThreshold() = 2 * params.LowThreshold(); // Note: high threshold is used by post-processing params.SamplingRate() = samplingRate; params.HistorySize() = historySize; params.Weight() = weight; @@ -67,26 +65,29 @@ void DPPratiMediodBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - cv::Mat background(bgs.Background()->Ptr()); - if(showOutput){ - cv::imshow("Temporal Median FG (Cucchiara&Calderara)", foreground); - cv::imshow("Temporal Median BG (Cucchiara&Calderara)", background); + 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 - foreground.copyTo(img_output); - background.copyTo(img_bgmodel); + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); delete frame; firstTime = false; frameNumber++; } -void DPPratiMediodBGS::saveConfig() +void DPPratiMediod::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPPratiMediodBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "threshold", threshold); cvWriteInt(fs, "samplingRate", samplingRate); @@ -97,15 +98,15 @@ void DPPratiMediodBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPPratiMediodBGS::loadConfig() +void DPPratiMediod::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPPratiMediodBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadIntByName(fs, 0, "threshold", 30); - samplingRate = cvReadIntByName(fs, 0, "samplingRate", 5); - historySize = cvReadIntByName(fs, 0, "historySize", 16); - weight = cvReadIntByName(fs, 0, "weight", 5); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/dp/DPMeanBGS.h b/package_bgs/DPPratiMediod.h similarity index 52% rename from package_bgs/dp/DPMeanBGS.h rename to package_bgs/DPPratiMediod.h index 88296860f11f1462df6bbfbc8a31b097cc57c24b..d37a77abd018547f519dcd244b96e970a590bdc1 100644 --- a/package_bgs/dp/DPMeanBGS.h +++ b/package_bgs/DPPratiMediod.h @@ -16,41 +16,41 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "MeanBGS.h" +#include "IBGS.h" +#include "dp/PratiMediodBGS.h" using namespace Algorithms::BackgroundSubtraction; -class DPMeanBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - MeanParams params; - MeanBGS bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - int threshold; - double alpha; - int learningFrames; - bool showOutput; - -public: - DPMeanBGS(); - ~DPMeanBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/dp/DPTextureBGS.cpp b/package_bgs/DPTexture.cpp similarity index 65% rename from package_bgs/dp/DPTextureBGS.cpp rename to package_bgs/DPTexture.cpp index 2d34342e1151fb8c174a9291781622a63fc10a0a..3285ccf83ecdcd0698bcfcfb9622188784144050 100644 --- a/package_bgs/dp/DPTextureBGS.cpp +++ b/package_bgs/DPTexture.cpp @@ -14,15 +14,18 @@ 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 "DPTextureBGS.h" +#include "DPTexture.h" -DPTextureBGS::DPTextureBGS() : firstTime(true), showOutput(true) - //, enableFiltering(true) +using namespace bgslibrary::algorithms; + +DPTexture::DPTexture() +// : enableFiltering(true) { - std::cout << "DPTextureBGS()" << std::endl; + std::cout << "DPTexture()" << std::endl; + setup("./config/DPTexture.xml"); } -DPTextureBGS::~DPTextureBGS() +DPTexture::~DPTexture() { delete[] bgModel; // ~10Kb (25.708-15.968) delete[] modeArray; @@ -33,34 +36,31 @@ DPTextureBGS::~DPTextureBGS() fgMask.ReleaseImage(); tempMask.ReleaseImage(); texture.ReleaseImage(); - std::cout << "~DPTextureBGS()" << std::endl; + std::cout << "~DPTexture()" << std::endl; } -void DPTextureBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPTexture::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) { - width = img_input.size().width; + width = img_input.size().width; height = img_input.size().height; size = width * height; // input image image = cvCreateImage(cvSize(width, height), 8, 3); - cvCopy(frame, image.Ptr()); + cvCopy(frame, image.Ptr()); // foreground masks fgMask = cvCreateImage(cvSize(width, height), 8, 1); tempMask = cvCreateImage(cvSize(width, height), 8, 1); cvZero(fgMask.Ptr()); cvZero(tempMask.Ptr()); - + // create background model bgModel = new TextureArray[size]; texture = cvCreateImage(cvSize(width, height), 8, 3); @@ -71,16 +71,16 @@ void DPTextureBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Ma // 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 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 x = REGION_R + TEXTURE_R; x < width - REGION_R - TEXTURE_R; ++x) { - int index = x+y*width; - - for(int m = 0; m < NUM_MODES; ++m) + int index = x + y*width; + + for (int m = 0; m < NUM_MODES; ++m) { - for(int i = 0; i < NUM_BINS; ++i) - { + for (int i = 0; i < 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]; @@ -91,18 +91,16 @@ void DPTextureBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Ma //dilateElement = cvCreateStructuringElementEx(7, 7, 3, 3, CV_SHAPE_RECT); //erodeElement = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT); - - saveConfig(); firstTime = false; } - - cvCopy(frame, image.Ptr()); + + cvCopy(frame, image.Ptr()); // perform background subtraction bgs.LBP(image, texture); bgs.Histogram(texture, curTextureHist); bgs.BgsCompare(bgModel, curTextureHist, modeArray, THRESHOLD, fgMask); - + //if(enableFiltering) //{ // // size filtering @@ -120,22 +118,27 @@ void DPTextureBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Ma // cvErode(fgMask.Ptr(), fgMask.Ptr(), erodeElement, 1); //} - cv::Mat foreground(fgMask.Ptr()); - if(!foreground.empty()) - foreground.copyTo(img_output); - - if(showOutput) - cv::imshow("Texture BGS (Donovan Parks)", foreground); + img_foreground = cv::cvarrToMat(fgMask.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("Texture BGS (Donovan Parks)", img_foreground); +#endif - // update background subtraction + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); + + // update background subtraction bgs.UpdateModel(fgMask, bgModel, curTextureHist, modeArray); - + delete frame; } -void DPTextureBGS::saveConfig() +void DPTexture::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPTextureBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); //cvWriteReal(fs, "alpha", alpha); //cvWriteInt(fs, "enableFiltering", enableFiltering); @@ -144,13 +147,13 @@ void DPTextureBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPTextureBGS::loadConfig() +void DPTexture::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPTextureBGS.xml", 0, CV_STORAGE_READ); - - //alpha = cvReadRealByName(fs, 0, "alpha", 1e-6f); - //enableFiltering = cvReadIntByName(fs, 0, "enableFiltering", true); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); } diff --git a/package_bgs/DPTexture.h b/package_bgs/DPTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..3cfdcea4c0bb499c323f4ef6b0cb0e218eaf3fdf --- /dev/null +++ b/package_bgs/DPTexture.h @@ -0,0 +1,59 @@ +/* +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/dp/DPWrenGABGS.cpp b/package_bgs/DPWrenGA.cpp similarity index 54% rename from package_bgs/dp/DPWrenGABGS.cpp rename to package_bgs/DPWrenGA.cpp index d7241b1db6ce9ef0c219b5fbaa28e7cb2abc2963..7fc331379d1ef27ea223e43dea6384308aafd503 100644 --- a/package_bgs/dp/DPWrenGABGS.cpp +++ b/package_bgs/DPWrenGA.cpp @@ -14,37 +14,35 @@ 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 "DPWrenGABGS.h" +#include "DPWrenGA.h" -DPWrenGABGS::DPWrenGABGS() : firstTime(true), frameNumber(0), threshold(12.25f), alpha(0.005f), learningFrames(30), showOutput(true) +using namespace bgslibrary::algorithms; + +DPWrenGA::DPWrenGA() : + frameNumber(0), threshold(12.25f), alpha(0.005f), learningFrames(30) { - std::cout << "DPWrenGABGS()" << std::endl; + std::cout << "DPWrenGA()" << std::endl; + setup("./config/DPWrenGA.xml"); } -DPWrenGABGS::~DPWrenGABGS() +DPWrenGA::~DPWrenGA() { - std::cout << "~DPWrenGABGS()" << std::endl; + std::cout << "~DPWrenGA()" << std::endl; } -void DPWrenGABGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPWrenGA::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPWrenGABGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat 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.HighThreshold() = 2 * params.LowThreshold(); // Note: high threshold is used by post-processing params.Alpha() = alpha; //0.005f; params.LearningFrames() = learningFrames; //30; @@ -66,22 +64,27 @@ void DPWrenGABGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("Gaussian Average (Wren)", foreground); - - foreground.copyTo(img_output); + 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 DPWrenGABGS::saveConfig() +void DPWrenGA::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPWrenGABGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -91,15 +94,14 @@ void DPWrenGABGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPWrenGABGS::loadConfig() +void DPWrenGA::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPWrenGABGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 12.25f); - alpha = cvReadRealByName(fs, 0, "alpha", 0.005f); - learningFrames = cvReadIntByName(fs, 0, "learningFrames", 30); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/dp/DPWrenGABGS.h b/package_bgs/DPWrenGA.h similarity index 54% rename from package_bgs/dp/DPWrenGABGS.h rename to package_bgs/DPWrenGA.h index 30ab614b0789abbbbe432150b26c5991fdb4751c..e4b0b5fffbb22de9dbc1edcbc8d24929576b69fc 100644 --- a/package_bgs/dp/DPWrenGABGS.h +++ b/package_bgs/DPWrenGA.h @@ -16,41 +16,40 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "WrenGA.h" +#include "IBGS.h" +#include "dp/WrenGA.h" using namespace Algorithms::BackgroundSubtraction; -class DPWrenGABGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - WrenParams params; - WrenGA bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - double threshold; - double alpha; - int learningFrames; - bool showOutput; - -public: - DPWrenGABGS(); - ~DPWrenGABGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/dp/DPZivkovicAGMMBGS.cpp b/package_bgs/DPZivkovicAGMM.cpp similarity index 53% rename from package_bgs/dp/DPZivkovicAGMMBGS.cpp rename to package_bgs/DPZivkovicAGMM.cpp index e8276f6bd8ceaa328faedc971b842493f7e70edb..a5a973514783fdb7791cfdc571c8f0c9630df322 100644 --- a/package_bgs/dp/DPZivkovicAGMMBGS.cpp +++ b/package_bgs/DPZivkovicAGMM.cpp @@ -14,37 +14,35 @@ 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 "DPZivkovicAGMMBGS.h" +#include "DPZivkovicAGMM.h" -DPZivkovicAGMMBGS::DPZivkovicAGMMBGS() : firstTime(true), frameNumber(0), threshold(25.0f), alpha(0.001f), gaussians(3), showOutput(true) +using namespace bgslibrary::algorithms; + +DPZivkovicAGMM::DPZivkovicAGMM() : + frameNumber(0), threshold(25.0f), alpha(0.001f), gaussians(3) { - std::cout << "DPZivkovicAGMMBGS()" << std::endl; + std::cout << "DPZivkovicAGMM()" << std::endl; + setup("./config/DPZivkovicAGMM.xml"); } -DPZivkovicAGMMBGS::~DPZivkovicAGMMBGS() +DPZivkovicAGMM::~DPZivkovicAGMM() { - std::cout << "~DPZivkovicAGMMBGS()" << std::endl; + std::cout << "~DPZivkovicAGMM()" << std::endl; } -void DPZivkovicAGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void DPZivkovicAGMM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +53,7 @@ void DPZivkovicAGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, c 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.HighThreshold() = 2 * params.LowThreshold(); // Note: high threshold is used by post-processing params.Alpha() = alpha; //0.001f; params.MaxModes() = gaussians; //3; @@ -66,22 +64,27 @@ void DPZivkovicAGMMBGS::process(const cv::Mat &img_input, cv::Mat &img_output, c bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("Gaussian Mixture Model (Zivkovic)", foreground); - - foreground.copyTo(img_output); + 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 DPZivkovicAGMMBGS::saveConfig() +void DPZivkovicAGMM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPZivkovicAGMMBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -91,14 +94,14 @@ void DPZivkovicAGMMBGS::saveConfig() cvReleaseFileStorage(&fs); } -void DPZivkovicAGMMBGS::loadConfig() +void DPZivkovicAGMM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/DPZivkovicAGMMBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 25.0f); - alpha = cvReadRealByName(fs, 0, "alpha", 0.001f); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/dp/DPGrimsonGMMBGS.h b/package_bgs/DPZivkovicAGMM.h similarity index 53% rename from package_bgs/dp/DPGrimsonGMMBGS.h rename to package_bgs/DPZivkovicAGMM.h index 4f955b970e7557f9406d458ac5db0dc83abccb28..f35504bff012f395bfa86ad5b304442fcb2fc08b 100644 --- a/package_bgs/dp/DPGrimsonGMMBGS.h +++ b/package_bgs/DPZivkovicAGMM.h @@ -16,41 +16,40 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "GrimsonGMM.h" +#include "IBGS.h" +#include "dp/ZivkovicAGMM.h" using namespace Algorithms::BackgroundSubtraction; -class DPGrimsonGMMBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - GrimsonParams params; - GrimsonGMM bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - double threshold; - double alpha; - int gaussians; - bool showOutput; - -public: - DPGrimsonGMMBGS(); - ~DPGrimsonGMMBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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 new file mode 100644 index 0000000000000000000000000000000000000000..4d5c076ce380ad410f115c678d4b71a0a2ca354a --- /dev/null +++ b/package_bgs/FrameDifference.cpp @@ -0,0 +1,84 @@ +/* +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/FrameDifferenceBGS.h b/package_bgs/FrameDifference.h similarity index 61% rename from package_bgs/FrameDifferenceBGS.h rename to package_bgs/FrameDifference.h index 338979f1966eac943984eb1b326d58a63df0581a..07bed8ed5e36fa42a53e81b95ea9624349f820a6 100644 --- a/package_bgs/FrameDifferenceBGS.h +++ b/package_bgs/FrameDifference.h @@ -16,29 +16,28 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - #include "IBGS.h" -class FrameDifferenceBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Mat img_input_prev; - cv::Mat img_foreground; - bool enableThreshold; - int threshold; - bool showOutput; - -public: - FrameDifferenceBGS(); - ~FrameDifferenceBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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/FrameDifferenceBGS.cpp b/package_bgs/FrameDifferenceBGS.cpp deleted file mode 100644 index e87165120919861a03b54fd8066b073122bfdf59..0000000000000000000000000000000000000000 --- a/package_bgs/FrameDifferenceBGS.cpp +++ /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/>. -*/ -#include "FrameDifferenceBGS.h" - -FrameDifferenceBGS::FrameDifferenceBGS() : firstTime(true), enableThreshold(true), threshold(15), showOutput(true) -{ - std::cout << "FrameDifferenceBGS()" << std::endl; -} - -FrameDifferenceBGS::~FrameDifferenceBGS() -{ - std::cout << "~FrameDifferenceBGS()" << std::endl; -} - -void FrameDifferenceBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) -{ - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - - if(img_input_prev.empty()) - { - img_input.copyTo(img_input_prev); - return; - } - - cv::absdiff(img_input_prev, 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); - - if(showOutput) - cv::imshow("Frame Difference", img_foreground); - - img_foreground.copyTo(img_output); - - img_input.copyTo(img_input_prev); - - firstTime = false; -} - -void FrameDifferenceBGS::saveConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/FrameDifferenceBGS.xml", 0, CV_STORAGE_WRITE); - - cvWriteInt(fs, "enableThreshold", enableThreshold); - cvWriteInt(fs, "threshold", threshold); - cvWriteInt(fs, "showOutput", showOutput); - - cvReleaseFileStorage(&fs); -} - -void FrameDifferenceBGS::loadConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/FrameDifferenceBGS.xml", 0, CV_STORAGE_READ); - - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - cvReleaseFileStorage(&fs); -} \ No newline at end of file diff --git a/package_bgs/tb/FuzzyChoquetIntegral.cpp b/package_bgs/FuzzyChoquetIntegral.cpp similarity index 62% rename from package_bgs/tb/FuzzyChoquetIntegral.cpp rename to package_bgs/FuzzyChoquetIntegral.cpp index c97e1743e445220616a82f6de99f2d176770b6ee..3d24126b4a089ddb7b026786146529876637c1e5 100644 --- a/package_bgs/tb/FuzzyChoquetIntegral.cpp +++ b/package_bgs/FuzzyChoquetIntegral.cpp @@ -15,12 +15,15 @@ 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" -#include <opencv2/legacy/compat.hpp> -FuzzyChoquetIntegral::FuzzyChoquetIntegral() : firstTime(true), frameNumber(0), showOutput(true), - framesToLearn(10), alphaLearn(0.1), alphaUpdate(0.01), colorSpace(1), option(2), smooth(true), threshold(0.67) +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) { std::cout << "FuzzyChoquetIntegral()" << std::endl; + setup("./config/FuzzyChoquetIntegral.xml"); } FuzzyChoquetIntegral::~FuzzyChoquetIntegral() @@ -30,48 +33,52 @@ FuzzyChoquetIntegral::~FuzzyChoquetIntegral() void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); cv::Mat img_input_f3(img_input.size(), CV_32F); - img_input.convertTo(img_input_f3, CV_32F, 1./255.); - - loadConfig(); + img_input.convertTo(img_input_f3, CV_32F, 1. / 255.); - if(firstTime) + if (firstTime) { std::cout << "FuzzyChoquetIntegral parameters:" << std::endl; - + std::string colorSpaceName = ""; - switch(colorSpace) + switch (colorSpace) { - case 1: colorSpaceName = "RGB"; break; - case 2: colorSpaceName = "OHTA"; break; - case 3: colorSpaceName = "HSV"; break; - case 4: colorSpaceName = "YCrCb"; break; + case 1: colorSpaceName = "RGB"; break; + case 2: colorSpaceName = "OHTA"; break; + case 3: colorSpaceName = "HSV"; break; + case 4: colorSpaceName = "YCrCb"; break; } std::cout << "Color space: " << colorSpaceName << std::endl; - if(option == 1) + if (option == 1) std::cout << "Fuzzing by 3 color components" << std::endl; - if(option == 2) + if (option == 2) std::cout << "Fuzzing by 2 color components + 1 texture component" << std::endl; - - saveConfig(); } - if(frameNumber <= framesToLearn) + if (frameNumber <= framesToLearn) { - if(frameNumber == 0) + if (frameNumber == 0) std::cout << "FuzzyChoquetIntegral initializing background model by adaptive learning..." << std::endl; - if(img_background_f3.empty()) + if (img_background_f3.empty()) img_input_f3.copyTo(img_background_f3); else - img_background_f3 = alphaLearn*img_input_f3 + (1-alphaLearn)*img_background_f3; + img_background_f3 = alphaLearn*img_input_f3 + (1 - alphaLearn)*img_background_f3; + + double minVal = 0., maxVal = 1.; + img_background_f3.convertTo(img_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_background.copyTo(img_bgmodel); + + img_foreground = cv::Mat::zeros(img_input.size(), img_input.type()); + img_foreground.copyTo(img_output); - if(showOutput) - cv::imshow("CI BG Model", img_background_f3); +#ifndef MEX_COMPILE_FLAG + if (showOutput) + cv::imshow("CI BG Model", img_background); +#endif } else { @@ -87,72 +94,74 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output IplImage* background_f1 = new IplImage(img_background_f1); IplImage* lbp_input_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1); - cvFillImage(lbp_input_f1, 0.0); + cvSetZero(lbp_input_f1); fu.LBP(input_f1, lbp_input_f1); - IplImage* lbp_background_f1 = cvCreateImage(cvSize(background_f1->width, background_f1->height), IPL_DEPTH_32F , 1); - cvFillImage(lbp_background_f1, 0.0); + IplImage* lbp_background_f1 = cvCreateImage(cvSize(background_f1->width, background_f1->height), IPL_DEPTH_32F, 1); + cvSetZero(lbp_background_f1); fu.LBP(background_f1, lbp_background_f1); IplImage* sim_texture_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1); fu.SimilarityDegreesImage(lbp_input_f1, lbp_background_f1, sim_texture_f1, 1, colorSpace); IplImage* sim_color_f3 = cvCreateImage(cvSize(input_f3->width, input_f3->height), IPL_DEPTH_32F, 3); - fu.SimilarityDegreesImage(input_f3, background_f3, sim_color_f3, 3, colorSpace); + fu.SimilarityDegreesImage(input_f3, background_f3, sim_color_f3, 3, colorSpace); - float* measureG = (float*) malloc(3*(sizeof(float))); + float* measureG = (float*)malloc(3 * (sizeof(float))); 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); } free(measureG); - cv::Mat img_integral_choquet_f1(integral_choquet_f1); + cv::Mat img_integral_choquet_f1 = cv::cvarrToMat(integral_choquet_f1); - if(smooth) + if (smooth) cv::medianBlur(img_integral_choquet_f1, img_integral_choquet_f1, 3); cv::Mat img_foreground_f1(img_input.size(), CV_32F); cv::threshold(img_integral_choquet_f1, img_foreground_f1, threshold, 255, cv::THRESH_BINARY_INV); - cv::Mat img_foreground_u1(img_input.size(), CV_8U); + //cv::Mat img_foreground_u1(img_input.size(), CV_8U); double minVal = 0., maxVal = 1.; - img_foreground_f1.convertTo(img_foreground_u1, CV_8U, 255.0/(maxVal - minVal), -minVal); - img_foreground_u1.copyTo(img_output); + img_foreground_f1.convertTo(img_foreground, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_foreground.copyTo(img_output); - cv::Mat img_background_u3(img_input.size(), CV_8U); + //cv::Mat img_background_u3(img_input.size(), CV_8U); //double minVal = 0., maxVal = 1.; - img_background_f3.convertTo(img_background_u3, CV_8U, 255.0/(maxVal - minVal), -minVal); - img_background_u3.copyTo(img_bgmodel); + img_background_f3.convertTo(img_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_background.copyTo(img_bgmodel); - if(showOutput) +#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_f3); - cv::imshow("CI FG Mask", img_foreground_u1); + cv::imshow("CI BG Model", img_background); + cv::imshow("CI FG Mask", img_foreground); } +#endif - if(frameNumber == (framesToLearn + 1)) + if (frameNumber == (framesToLearn + 1)) std::cout << "FuzzyChoquetIntegral 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); - cvFillImage(updated_background_f3, 0.0); + cvSetZero(updated_background_f3); fu.AdaptativeSelectiveBackgroundModelUpdate(input_f3, background_f3, updated_background_f3, integral_choquet_f1, threshold, alphaUpdate); - cv::Mat img_updated_background_f3(updated_background_f3); + cv::Mat img_updated_background_f3 = cv::cvarrToMat(updated_background_f3); img_updated_background_f3.copyTo(img_background_f3); cvReleaseImage(&lbp_input_f1); @@ -161,7 +170,7 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output cvReleaseImage(&sim_color_f3); cvReleaseImage(&integral_choquet_f1); cvReleaseImage(&updated_background_f3); - + delete background_f1; delete background_f3; delete input_f1; @@ -174,8 +183,8 @@ void FuzzyChoquetIntegral::process(const cv::Mat &img_input, cv::Mat &img_output void FuzzyChoquetIntegral::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/FuzzyChoquetIntegral.xml", 0, CV_STORAGE_WRITE); - + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); + cvWriteInt(fs, "showOutput", showOutput); cvWriteInt(fs, "framesToLearn", framesToLearn); cvWriteReal(fs, "alphaLearn", alphaLearn); @@ -190,16 +199,16 @@ void FuzzyChoquetIntegral::saveConfig() void FuzzyChoquetIntegral::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/FuzzyChoquetIntegral.xml", 0, CV_STORAGE_READ); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - framesToLearn = cvReadIntByName(fs, 0, "framesToLearn", 10); - alphaLearn = cvReadRealByName(fs, 0, "alphaLearn", 0.1); - alphaUpdate = cvReadRealByName(fs, 0, "alphaUpdate", 0.01); - colorSpace = cvReadIntByName(fs, 0, "colorSpace", 1); - option = cvReadIntByName(fs, 0, "option", 2); - smooth = cvReadIntByName(fs, 0, "smooth", true); - threshold = cvReadRealByName(fs, 0, "threshold", 0.67); + 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); } diff --git a/package_bgs/FuzzyChoquetIntegral.h b/package_bgs/FuzzyChoquetIntegral.h new file mode 100644 index 0000000000000000000000000000000000000000..25681b0c49f4e86efbd35440410b06ba90c25e81 --- /dev/null +++ b/package_bgs/FuzzyChoquetIntegral.h @@ -0,0 +1,53 @@ +/* +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/tb/FuzzySugenoIntegral.cpp b/package_bgs/FuzzySugenoIntegral.cpp similarity index 62% rename from package_bgs/tb/FuzzySugenoIntegral.cpp rename to package_bgs/FuzzySugenoIntegral.cpp index 859f14e91d9707d26b61c4af8d47c00e2aa55284..e62fa029637af565142fdd70ae857e180f553ae6 100644 --- a/package_bgs/tb/FuzzySugenoIntegral.cpp +++ b/package_bgs/FuzzySugenoIntegral.cpp @@ -15,12 +15,15 @@ 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" -#include <opencv2/legacy/compat.hpp> -FuzzySugenoIntegral::FuzzySugenoIntegral() : firstTime(true), frameNumber(0), showOutput(true), - framesToLearn(10), alphaLearn(0.1), alphaUpdate(0.01), colorSpace(1), option(2), smooth(true), threshold(0.67) +using namespace bgslibrary::algorithms; + +FuzzySugenoIntegral::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"); } FuzzySugenoIntegral::~FuzzySugenoIntegral() @@ -30,48 +33,52 @@ FuzzySugenoIntegral::~FuzzySugenoIntegral() void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); cv::Mat img_input_f3(img_input.size(), CV_32F); - img_input.convertTo(img_input_f3, CV_32F, 1./255.); - - loadConfig(); + img_input.convertTo(img_input_f3, CV_32F, 1. / 255.); - if(firstTime) + if (firstTime) { std::cout << "FuzzySugenoIntegral parameters:" << std::endl; - + std::string colorSpaceName = ""; - switch(colorSpace) + switch (colorSpace) { - case 1: colorSpaceName = "RGB"; break; - case 2: colorSpaceName = "OHTA"; break; - case 3: colorSpaceName = "HSV"; break; - case 4: colorSpaceName = "YCrCb"; break; + case 1: colorSpaceName = "RGB"; break; + case 2: colorSpaceName = "OHTA"; break; + case 3: colorSpaceName = "HSV"; break; + case 4: colorSpaceName = "YCrCb"; break; } std::cout << "Color space: " << colorSpaceName << std::endl; - if(option == 1) + if (option == 1) std::cout << "Fuzzing by 3 color components" << std::endl; - if(option == 2) + if (option == 2) std::cout << "Fuzzing by 2 color components + 1 texture component" << std::endl; - - saveConfig(); } - if(frameNumber <= framesToLearn) + if (frameNumber <= framesToLearn) { - if(frameNumber == 0) + if (frameNumber == 0) std::cout << "FuzzySugenoIntegral initializing background model by adaptive learning..." << std::endl; - if(img_background_f3.empty()) + if (img_background_f3.empty()) img_input_f3.copyTo(img_background_f3); else - img_background_f3 = alphaLearn*img_input_f3 + (1-alphaLearn)*img_background_f3; + img_background_f3 = alphaLearn*img_input_f3 + (1 - alphaLearn)*img_background_f3; + + double minVal = 0., maxVal = 1.; + img_background_f3.convertTo(img_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_background.copyTo(img_bgmodel); + + img_foreground = cv::Mat::zeros(img_input.size(), img_input.type()); + img_foreground.copyTo(img_output); - if(showOutput) - cv::imshow("SI BG Model", img_background_f3); +#ifndef MEX_COMPILE_FLAG + if (showOutput) + cv::imshow("SI BG Model", img_background); +#endif } else { @@ -87,72 +94,74 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, IplImage* background_f1 = new IplImage(img_background_f1); IplImage* lbp_input_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1); - cvFillImage(lbp_input_f1, 0.0); + cvSetZero(lbp_input_f1); fu.LBP(input_f1, lbp_input_f1); - IplImage* lbp_background_f1 = cvCreateImage(cvSize(background_f1->width, background_f1->height), IPL_DEPTH_32F , 1); - cvFillImage(lbp_background_f1, 0.0); + IplImage* lbp_background_f1 = cvCreateImage(cvSize(background_f1->width, background_f1->height), IPL_DEPTH_32F, 1); + cvSetZero(lbp_background_f1); fu.LBP(background_f1, lbp_background_f1); IplImage* sim_texture_f1 = cvCreateImage(cvSize(input_f1->width, input_f1->height), IPL_DEPTH_32F, 1); fu.SimilarityDegreesImage(lbp_input_f1, lbp_background_f1, sim_texture_f1, 1, colorSpace); IplImage* sim_color_f3 = cvCreateImage(cvSize(input_f3->width, input_f3->height), IPL_DEPTH_32F, 3); - fu.SimilarityDegreesImage(input_f3, background_f3, sim_color_f3, 3, colorSpace); + fu.SimilarityDegreesImage(input_f3, background_f3, sim_color_f3, 3, colorSpace); - float* measureG = (float*) malloc(3*(sizeof(float))); + float* measureG = (float*)malloc(3 * (sizeof(float))); 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); } free(measureG); - cv::Mat img_integral_sugeno_f1(integral_sugeno_f1); + cv::Mat img_integral_sugeno_f1 = cv::cvarrToMat(integral_sugeno_f1); - if(smooth) + if (smooth) cv::medianBlur(img_integral_sugeno_f1, img_integral_sugeno_f1, 3); cv::Mat img_foreground_f1(img_input.size(), CV_32F); cv::threshold(img_integral_sugeno_f1, img_foreground_f1, threshold, 255, cv::THRESH_BINARY_INV); - cv::Mat img_foreground_u1(img_input.size(), CV_8U); + //cv::Mat img_foreground_u1(img_input.size(), CV_8U); double minVal = 0., maxVal = 1.; - img_foreground_f1.convertTo(img_foreground_u1, CV_8U, 255.0/(maxVal - minVal), -minVal); - img_foreground_u1.copyTo(img_output); - - cv::Mat img_background_u3(img_input.size(), CV_8U); + img_foreground_f1.convertTo(img_foreground, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_foreground.copyTo(img_output); + + //cv::Mat img_background_u3(img_input.size(), CV_8U); //double minVal = 0., maxVal = 1.; - img_background_f3.convertTo(img_background_u3, CV_8U, 255.0/(maxVal - minVal), -minVal); - img_background_u3.copyTo(img_bgmodel); + img_background_f3.convertTo(img_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); + img_background.copyTo(img_bgmodel); - if(showOutput) +#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_f3); - cv::imshow("SI FG Mask", img_foreground_u1); + cv::imshow("SI BG Model", img_background); + cv::imshow("SI FG Mask", img_foreground); } +#endif - if(frameNumber == (framesToLearn + 1)) + if (frameNumber == (framesToLearn + 1)) std::cout << "FuzzySugenoIntegral 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); - cvFillImage(updated_background_f3, 0.0); + cvSetZero(updated_background_f3); fu.AdaptativeSelectiveBackgroundModelUpdate(input_f3, background_f3, updated_background_f3, integral_sugeno_f1, threshold, alphaUpdate); - cv::Mat img_updated_background_f3(updated_background_f3); + cv::Mat img_updated_background_f3 = cv::cvarrToMat(updated_background_f3); img_updated_background_f3.copyTo(img_background_f3); cvReleaseImage(&lbp_input_f1); @@ -161,7 +170,7 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, cvReleaseImage(&sim_color_f3); cvReleaseImage(&integral_sugeno_f1); cvReleaseImage(&updated_background_f3); - + delete background_f1; delete background_f3; delete input_f1; @@ -174,8 +183,8 @@ void FuzzySugenoIntegral::process(const cv::Mat &img_input, cv::Mat &img_output, void FuzzySugenoIntegral::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/FuzzySugenoIntegral.xml", 0, CV_STORAGE_WRITE); - + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); + cvWriteInt(fs, "showOutput", showOutput); cvWriteInt(fs, "framesToLearn", framesToLearn); cvWriteReal(fs, "alphaLearn", alphaLearn); @@ -184,22 +193,22 @@ void FuzzySugenoIntegral::saveConfig() cvWriteInt(fs, "option", option); cvWriteInt(fs, "smooth", smooth); cvWriteReal(fs, "threshold", threshold); - + cvReleaseFileStorage(&fs); } void FuzzySugenoIntegral::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/FuzzySugenoIntegral.xml", 0, CV_STORAGE_READ); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - framesToLearn = cvReadIntByName(fs, 0, "framesToLearn", 10); - alphaLearn = cvReadRealByName(fs, 0, "alphaLearn", 0.1); - alphaUpdate = cvReadRealByName(fs, 0, "alphaUpdate", 0.01); - colorSpace = cvReadIntByName(fs, 0, "colorSpace", 1); - option = cvReadIntByName(fs, 0, "option", 2); - smooth = cvReadIntByName(fs, 0, "smooth", true); - threshold = cvReadRealByName(fs, 0, "threshold", 0.67); - + 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); } diff --git a/package_bgs/FuzzySugenoIntegral.h b/package_bgs/FuzzySugenoIntegral.h new file mode 100644 index 0000000000000000000000000000000000000000..70bde1591ea4338b1955edf81e72d4089e1d7342 --- /dev/null +++ b/package_bgs/FuzzySugenoIntegral.h @@ -0,0 +1,53 @@ +/* +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 index 675b23cba8f3a9f71a35bc99fa66d95c7094b456..19bd8abbbf858a3c9d893e03f7a34dc7f557ebb0 100644 --- a/package_bgs/GMG.cpp +++ b/package_bgs/GMG.cpp @@ -16,9 +16,14 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "GMG.h" -GMG::GMG() : firstTime(true), initializationFrames(20), decisionThreshold(0.7), showOutput(true) +#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); @@ -34,41 +39,33 @@ GMG::~GMG() void GMG::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - - if(firstTime) + if (firstTime) { fgbg->set("initializationFrames", initializationFrames); fgbg->set("decisionThreshold", decisionThreshold); - - saveConfig(); } - - if(fgbg.empty()) + + if (fgbg.empty()) { std::cerr << "Failed to create BackgroundSubtractor.GMG Algorithm." << std::endl; return; } (*fgbg)(img_input, img_foreground); - - cv::Mat img_background; (*fgbg).getBackgroundImage(img_background); img_input.copyTo(img_segmentation); cv::add(img_input, cv::Scalar(100, 100, 0), img_segmentation, img_foreground); - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) { - if (!img_foreground.empty()) - cv::imshow("GMG FG (Godbehere-Matsukawa-Goldberg)", img_foreground); - - if (!img_background.empty()) - cv::imshow("GMG BG (Godbehere-Matsukawa-Goldberg)", img_background); + 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); @@ -78,7 +75,7 @@ void GMG::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bg void GMG::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/GMG.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "initializationFrames", initializationFrames); cvWriteReal(fs, "decisionThreshold", decisionThreshold); @@ -89,11 +86,13 @@ void GMG::saveConfig() void GMG::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/GMG.xml", 0, CV_STORAGE_READ); - - initializationFrames = cvReadIntByName(fs, 0, "initializationFrames", 20); - decisionThreshold = cvReadRealByName(fs, 0, "decisionThreshold", 0.7); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - + 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 index 9da28adb7a40d2cb443d34372a6e6220c09f3af3..1b4af30b234f954ee80d5fa8554b0e945ba21976 100644 --- a/package_bgs/GMG.h +++ b/package_bgs/GMG.h @@ -16,30 +16,34 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> +#include "opencv2/core/version.hpp" +#if CV_MAJOR_VERSION == 2 #include "IBGS.h" -class GMG : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Ptr<cv::BackgroundSubtractorGMG> fgbg; - int initializationFrames; - double decisionThreshold; - cv::Mat img_foreground; - cv::Mat img_segmentation; - bool showOutput; - -public: - GMG(); - ~GMG(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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 index 073ce185b59734f2e8cfb25ab26051746386a3f0..718bf51ed20d35865d420c46aaa867cd446dcb2d 100644 --- a/package_bgs/IBGS.h +++ b/package_bgs/IBGS.h @@ -16,18 +16,59 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once +#include <iostream> +#include <fstream> #include <opencv2/opencv.hpp> -class IBGS +namespace bgslibrary { -public: - virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground, cv::Mat &img_background) = 0; - /*virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground){ - process(img_input, img_foreground, cv::Mat()); - }*/ - virtual ~IBGS(){} + 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() {} -private: - virtual void saveConfig() = 0; - virtual void loadConfig() = 0; -}; + 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/db/imbs.cpp b/package_bgs/IMBS/IMBS.cpp similarity index 74% rename from package_bgs/db/imbs.cpp rename to package_bgs/IMBS/IMBS.cpp index f5fc0d0235e3ad026c2990b04f9ce6c677ca05fd..b1e177b3e806a7e3a4302e9b370494d5b6d9d40a 100644 --- a/package_bgs/db/imbs.cpp +++ b/package_bgs/IMBS/IMBS.cpp @@ -1,5 +1,21 @@ /* -* IMBS Background Subtraction Library +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 @@ -8,8 +24,8 @@ * 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. +* +* 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 @@ -19,7 +35,7 @@ * */ -#include "imbs.hpp" +#include "IMBS.hpp" using namespace std; using namespace cv; @@ -29,15 +45,15 @@ BackgroundSubtractorIMBS::BackgroundSubtractorIMBS() fps = 0.; fgThreshold = 15; associationThreshold = 5; - samplingPeriod = 250.;//500.ms + samplingPeriod = 250;//500.ms minBinHeight = 2; numSamples = 10; //30 alpha = 0.65f; beta = 1.15f; - tau_s = 60.; - tau_h = 40.; + tau_s = 60; + tau_h = 40; minArea = 30.; - persistencePeriod = samplingPeriod*numSamples/3.;//ms + persistencePeriod = samplingPeriod*numSamples / 3.;//ms initial_tick_count = (double)getTickCount(); @@ -63,7 +79,7 @@ BackgroundSubtractorIMBS::BackgroundSubtractorIMBS( this->fps = fps; this->fgThreshold = fgThreshold; this->persistencePeriod = persistencePeriod; - if(minBinHeight <= 1){ + if (minBinHeight <= 1) { this->minBinHeight = 1; } else { @@ -79,7 +95,7 @@ BackgroundSubtractorIMBS::BackgroundSubtractorIMBS( this->tau_h = tau_h; this->minArea = minArea; - if(fps == 0.) + if (fps == 0.) initial_tick_count = (double)getTickCount(); else initial_tick_count = 0; @@ -106,7 +122,7 @@ void BackgroundSubtractorIMBS::initialize(Size frameSize, int frameType) this->numPixels = frameSize.width*frameSize.height; persistenceMap = new unsigned int[numPixels]; - for(unsigned int i = 0; i < numPixels; i++) { + for (unsigned int i = 0; i < numPixels; i++) { persistenceMap[i] = 0; } @@ -134,20 +150,20 @@ void BackgroundSubtractorIMBS::initialize(Size frameSize, int frameType) //initial message to be shown until the first fg mask is computed initialMsgGray = Mat::zeros(frameSize, CV_8UC1); - putText(initialMsgGray, "Creating", Point(10,20), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); - putText(initialMsgGray, "initial", Point(10,40), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); - putText(initialMsgGray, "background...", Point(10,60), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgGray, "Creating", Point(10, 20), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgGray, "initial", Point(10, 40), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgGray, "background...", Point(10, 60), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); initialMsgRGB = Mat::zeros(frameSize, CV_8UC3); - putText(initialMsgRGB, "Creating", Point(10,20), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); - putText(initialMsgRGB, "initial", Point(10,40), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); - putText(initialMsgRGB, "background...", Point(10,60), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgRGB, "Creating", Point(10, 20), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgRGB, "initial", Point(10, 40), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); + putText(initialMsgRGB, "background...", Point(10, 60), FONT_HERSHEY_SIMPLEX, 0.4, CV_RGB(255, 255, 255)); - if(minBinHeight <= 1){ + if (minBinHeight <= 1) { minBinHeight = 1; } - for(unsigned int p = 0; p < numPixels; ++p) + for (unsigned int p = 0; p < numPixels; ++p) { bgBins[p].binValues = new Vec3b[numSamples]; bgBins[p].binHeights = new uchar[numSamples]; @@ -169,7 +185,7 @@ void BackgroundSubtractorIMBS::apply(InputArray _frame, OutputArray _fgmask, dou CV_Assert(frame.channels() == 3); bool needToInitialize = nframes == 0 || frame.type() != frameType; - if( needToInitialize ) { + if (needToInitialize) { initialize(frame.size(), frame.type()); } @@ -179,29 +195,29 @@ void BackgroundSubtractorIMBS::apply(InputArray _frame, OutputArray _fgmask, dou //get current time prev_timestamp = timestamp; - if(fps == 0.) { + if (fps == 0.) { timestamp = getTimestamp();//ms } else { - timestamp += 1000./fps;//ms + timestamp += 1000. / fps;//ms } //check for global changes - if(sudden_change) { + if (sudden_change) { changeBg(); } //wait for the first model to be generated - if(bgModel[0].isValid[0]) { - getFg(); + if (bgModel[0].isValid[0]) { + getFg(); hsvSuppression(); filterFg(); - } + } //update the bg model updateBg(); //show an initial message if the first bg is not yet ready - if(!bgModel[0].isValid[0]) { + if (!bgModel[0].isValid[0]) { initialMsgGray.copyTo(fgmask); initialMsgRGB.copyTo(bgImage); } @@ -209,23 +225,23 @@ void BackgroundSubtractorIMBS::apply(InputArray _frame, OutputArray _fgmask, dou } void BackgroundSubtractorIMBS::updateBg() { - if(bg_reset) { - if(bg_frame_counter > numSamples - 1) { + if (bg_reset) { + if (bg_frame_counter > numSamples - 1) { bg_frame_counter = numSamples - 1; } } - if(prev_bg_frame_time > timestamp) { + if (prev_bg_frame_time > timestamp) { prev_bg_frame_time = timestamp; } - if(bg_frame_counter == numSamples - 1) { + if (bg_frame_counter == numSamples - 1) { createBg(bg_frame_counter); bg_frame_counter = 0; } else { //bg_frame_counter < (numSamples - 1) - if((timestamp - prev_bg_frame_time) >= samplingPeriod) + if ((timestamp - prev_bg_frame_time) >= samplingPeriod) { //get a new sample for creating the bg model prev_bg_frame_time = timestamp; @@ -237,7 +253,7 @@ void BackgroundSubtractorIMBS::updateBg() { } double BackgroundSubtractorIMBS::getTimestamp() { - return ((double)getTickCount() - initial_tick_count)*1000./getTickFrequency(); + return ((double)getTickCount() - initial_tick_count)*1000. / getTickFrequency(); } void BackgroundSubtractorIMBS::hsvSuppression() { @@ -251,35 +267,35 @@ void BackgroundSubtractorIMBS::hsvSuppression() { vector<Mat> imHSV; cv::split(convertImageRGBtoHSV(frame), imHSV); - for(unsigned int p = 0; p < numPixels; ++p) { - if(fgmask.data[p]) { + for (unsigned int p = 0; p < numPixels; ++p) { + if (fgmask.data[p]) { h_i = imHSV[0].data[p]; s_i = imHSV[1].data[p]; v_i = imHSV[2].data[p]; - for(unsigned int n = 0; n < maxBgBins; ++n) { - if(!bgModel[p].isValid[n]) { + for (unsigned int n = 0; n < maxBgBins; ++n) { + if (!bgModel[p].isValid[n]) { break; } - if(bgModel[p].isFg[n]) { + if (bgModel[p].isFg[n]) { continue; } - bgrPixel.at<cv::Vec3b>(0,0) = bgModel[p].values[n]; + bgrPixel.at<cv::Vec3b>(0, 0) = bgModel[p].values[n]; cv::Mat hsvPixel = convertImageRGBtoHSV(bgrPixel); - h_b = hsvPixel.at<cv::Vec3b>(0,0)[0]; - s_b = hsvPixel.at<cv::Vec3b>(0,0)[1]; - v_b = hsvPixel.at<cv::Vec3b>(0,0)[2]; + h_b = hsvPixel.at<cv::Vec3b>(0, 0)[0]; + s_b = hsvPixel.at<cv::Vec3b>(0, 0)[1]; + v_b = hsvPixel.at<cv::Vec3b>(0, 0)[2]; v_ratio = (float)v_i / (float)v_b; s_diff = std::abs(s_i - s_b); - h_diff = std::min( std::abs(h_i - h_b), 255 - std::abs(h_i - h_b)); + h_diff = std::min(std::abs(h_i - h_b), 255 - std::abs(h_i - h_b)); - if( h_diff <= tau_h && + if (h_diff <= tau_h && s_diff <= tau_s && v_ratio >= alpha && v_ratio < beta) @@ -293,7 +309,7 @@ void BackgroundSubtractorIMBS::hsvSuppression() { } void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { - if(!bgSample.data) { + if (!bgSample.data) { //cerr << "createBg -- an error occurred: " << // " unable to retrieve frame no. " << bg_sample_number << endl; @@ -305,18 +321,18 @@ void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { //split bgSample in channels cv::split(bgSample, bgSampleBGR); //create a statistical model for each pixel (a set of bins of variable size) - for(unsigned int p = 0; p < numPixels; ++p) { + for (unsigned int p = 0; p < numPixels; ++p) { //create an initial bin for each pixel from the first sample (bg_sample_number = 0) - if(bg_sample_number == 0) { - for(int k = 0; k < 3; ++k) { + if (bg_sample_number == 0) { + for (int k = 0; k < 3; ++k) { bgBins[p].binValues[0][k] = bgSampleBGR[k].data[p]; } bgBins[p].binHeights[0] = 1; - for(unsigned int s = 1; s < numSamples; ++s) { + for (unsigned int s = 1; s < numSamples; ++s) { bgBins[p].binHeights[s] = 0; } //if the sample pixel is from foreground keep track of that situation - if(fgmask.data[p] == FOREGROUND_LABEL) { + if (fgmask.data[p] == FOREGROUND_LABEL) { bgBins[p].isFg[0] = true; } else { @@ -324,32 +340,32 @@ void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { } }//if(bg_sample_number == 0) else { //bg_sample_number > 0 - for(int k = 0; k < 3; ++k) { + for (int k = 0; k < 3; ++k) { currentPixel[k] = bgSampleBGR[k].data[p]; } int den = 0; - for(unsigned int s = 0; s < bg_sample_number; ++s) { + for (unsigned int s = 0; s < bg_sample_number; ++s) { //try to associate the current pixel values to an existing bin - if( std::abs(currentPixel[2] - bgBins[p].binValues[s][2]) <= associationThreshold && + if (std::abs(currentPixel[2] - bgBins[p].binValues[s][2]) <= associationThreshold && std::abs(currentPixel[1] - bgBins[p].binValues[s][1]) <= associationThreshold && - std::abs(currentPixel[0] - bgBins[p].binValues[s][0]) <= associationThreshold ) + std::abs(currentPixel[0] - bgBins[p].binValues[s][0]) <= associationThreshold) { den = (bgBins[p].binHeights[s] + 1); - for(int k = 0; k < 3; ++k) { + for (int k = 0; k < 3; ++k) { bgBins[p].binValues[s][k] = (bgBins[p].binValues[s][k] * bgBins[p].binHeights[s] + currentPixel[k]) / den; } bgBins[p].binHeights[s]++; //increment the height of the bin - if(fgmask.data[p] == FOREGROUND_LABEL) { + if (fgmask.data[p] == FOREGROUND_LABEL) { bgBins[p].isFg[s] = true; } break; } //if the association is not possible, create a new bin - else if(bgBins[p].binHeights[s] == 0) { + else if (bgBins[p].binHeights[s] == 0) { bgBins[p].binValues[s] = currentPixel; bgBins[p].binHeights[s]++; - if(fgmask.data[p] == FOREGROUND_LABEL) { + if (fgmask.data[p] == FOREGROUND_LABEL) { bgBins[p].isFg[s] = true; } else { @@ -362,44 +378,44 @@ void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { //if all samples have been processed //it is time to compute the fg mask - if(bg_sample_number == (numSamples - 1)) { + if (bg_sample_number == (numSamples - 1)) { unsigned int index = 0; int max_height = -1; - for(unsigned int s = 0; s < numSamples; ++s){ - if(bgBins[p].binHeights[s] == 0) { + for (unsigned int s = 0; s < numSamples; ++s) { + if (bgBins[p].binHeights[s] == 0) { bgModel[p].isValid[index] = false; break; } - if(index == maxBgBins) { + if (index == maxBgBins) { break; } - else if(bgBins[p].binHeights[s] >= minBinHeight) { - if(fgmask.data[p] == PERSISTENCE_LABEL) { - for(unsigned int n = 0; n < maxBgBins; n++) { - if(!bgModel[p].isValid[n]) { + else if (bgBins[p].binHeights[s] >= minBinHeight) { + if (fgmask.data[p] == PERSISTENCE_LABEL) { + for (unsigned int n = 0; n < maxBgBins; n++) { + if (!bgModel[p].isValid[n]) { break; } unsigned int d = std::max((int)std::abs(bgModel[p].values[n][0] - bgBins[p].binValues[s][0]), - std::abs(bgModel[p].values[n][1] - bgBins[p].binValues[s][1]) ); - d = std::max((int)d, std::abs(bgModel[p].values[n][2] - bgBins[p].binValues[s][2]) ); - if(d < fgThreshold){ + std::abs(bgModel[p].values[n][1] - bgBins[p].binValues[s][1])); + d = std::max((int)d, std::abs(bgModel[p].values[n][2] - bgBins[p].binValues[s][2])); + if (d < fgThreshold) { bgModel[p].isFg[n] = false; bgBins[p].isFg[s] = false; } } } - if(bgBins[p].binHeights[s] > max_height) { + if (bgBins[p].binHeights[s] > max_height) { max_height = bgBins[p].binHeights[s]; - for(int k = 0; k < 3; ++k) { + for (int k = 0; k < 3; ++k) { bgModel[p].values[index][k] = bgModel[p].values[0][k]; } bgModel[p].isValid[index] = true; bgModel[p].isFg[index] = bgModel[p].isFg[0]; bgModel[p].counter[index] = bgModel[p].counter[0]; - for(int k = 0; k < 3; ++k) { + for (int k = 0; k < 3; ++k) { bgModel[p].values[0][k] = bgBins[p].binValues[s][k]; } bgModel[p].isValid[0] = true; @@ -407,7 +423,7 @@ void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { bgModel[p].counter[0] = bgBins[p].binHeights[s]; } else { - for(int k = 0; k < 3; ++k) { + for (int k = 0; k < 3; ++k) { bgModel[p].values[index][k] = bgBins[p].binValues[s][k]; } bgModel[p].isValid[index] = true; @@ -421,25 +437,25 @@ void BackgroundSubtractorIMBS::createBg(unsigned int bg_sample_number) { }//else --> if(frame_number == 0) }//numPixels - if(bg_sample_number == (numSamples - 1)) { - //std::cout << "new bg created" << std::endl; + if (bg_sample_number == (numSamples - 1)) { + //std::cout << "new bg created" << std::endl; persistenceImage = Scalar(0); bg_reset = false; - if(sudden_change) { + if (sudden_change) { numSamples *= 3.; samplingPeriod *= 2.; sudden_change = false; } - for(unsigned int i = 0; i < numPixels; i++) { + for (unsigned int i = 0; i < numPixels; i++) { persistenceMap[i] = 0; } unsigned int p = 0; - for(int i = 0; i < bgImage.rows; ++i) { - for(int j = 0; j < bgImage.cols; ++j, ++p) { - bgImage.at<cv::Vec3b>(i,j) = bgModel[p].values[0]; + for (int i = 0; i < bgImage.rows; ++i) { + for (int j = 0; j < bgImage.cols; ++j, ++p) { + bgImage.at<cv::Vec3b>(i, j) = bgModel[p].values[0]; } } } @@ -452,13 +468,13 @@ void BackgroundSubtractorIMBS::getFg() { bool isFg = true; bool conditionalUpdated = false; unsigned int d = 0; - for(unsigned int p = 0; p < numPixels; ++p) { + for (unsigned int p = 0; p < numPixels; ++p) { isFg = true; conditionalUpdated = false; d = 0; - for(unsigned int n = 0; n < maxBgBins; ++n) { - if(!bgModel[p].isValid[n]) { - if(n == 0) { + for (unsigned int n = 0; n < maxBgBins; ++n) { + if (!bgModel[p].isValid[n]) { + if (n == 0) { isFg = false; } break; @@ -466,13 +482,13 @@ void BackgroundSubtractorIMBS::getFg() { else { //the model is valid d = std::max( (int)std::abs(bgModel[p].values[n][0] - frameBGR[0].data[p]), - std::abs(bgModel[p].values[n][1] - frameBGR[1].data[p]) ); + std::abs(bgModel[p].values[n][1] - frameBGR[1].data[p])); d = std::max( - (int)d, std::abs(bgModel[p].values[n][2] - frameBGR[2].data[p]) ); - if(d < fgThreshold){ + (int)d, std::abs(bgModel[p].values[n][2] - frameBGR[2].data[p])); + if (d < fgThreshold) { //check if it is a potential background pixel //from stationary object - if(bgModel[p].isFg[n]) { + if (bgModel[p].isFg[n]) { conditionalUpdated = true; break; } @@ -483,13 +499,13 @@ void BackgroundSubtractorIMBS::getFg() { } } } - if(isFg) { - if(conditionalUpdated) { + if (isFg) { + if (conditionalUpdated) { fgmask.data[p] = PERSISTENCE_LABEL; persistenceMap[p] += (timestamp - prev_timestamp); - if(persistenceMap[p] > persistencePeriod) { - for(unsigned int n = 0; n < maxBgBins; ++n) { - if(!bgModel[p].isValid[n]) { + if (persistenceMap[p] > persistencePeriod) { + for (unsigned int n = 0; n < maxBgBins; ++n) { + if (!bgModel[p].isValid[n]) { break; } bgModel[p].isFg[n] = false; @@ -521,13 +537,13 @@ void BackgroundSubtractorIMBS::areaThresholding() if (area < minArea || area >= maxArea) continue; else { - drawContours( tmpBinaryImage, contours, contourIdx, Scalar(255), CV_FILLED ); + drawContours(tmpBinaryImage, contours, contourIdx, Scalar(255), CV_FILLED); } - } - for(int i = 0; i < fgfiltered.rows; ++i) { - for(int j = 0; j < fgfiltered.cols; ++j) { - if(!tmpBinaryImage.at<uchar>(i,j)) { - fgfiltered.at<uchar>(i,j) = 0; + } + for (int i = 0; i < fgfiltered.rows; ++i) { + for (int j = 0; j < fgfiltered.cols; ++j) { + if (!tmpBinaryImage.at<uchar>(i, j)) { + fgfiltered.at<uchar>(i, j) = 0; } } } @@ -560,9 +576,9 @@ Mat BackgroundSubtractorIMBS::convertImageRGBtoHSV(const Mat& imageRGB) for (int x = 0; x < w; ++x) { // Get the RGB pixel components. NOTE that OpenCV stores RGB pixels in B,G,R order. //uchar *pRGB = (uchar*)(imRGB + y*rowSizeRGB + x*3); - int bB = imageRGB.at<Vec3b>(y,x)[0]; //*(uchar*)(pRGB+0); // Blue component - int bG = imageRGB.at<Vec3b>(y,x)[1]; //*(uchar*)(pRGB+1); // Green component - int bR = imageRGB.at<Vec3b>(y,x)[2]; //*(uchar*)(pRGB+2); // Red component + int bB = imageRGB.at<Vec3b>(y, x)[0]; //*(uchar*)(pRGB+0); // Blue component + int bG = imageRGB.at<Vec3b>(y, x)[1]; //*(uchar*)(pRGB+1); // Green component + int bR = imageRGB.at<Vec3b>(y, x)[2]; //*(uchar*)(pRGB+2); // Red component // Convert from 8-bit integers to floats. fR = bR * BYTE_TO_FLOAT; @@ -619,10 +635,10 @@ Mat BackgroundSubtractorIMBS::convertImageRGBtoHSV(const Mat& imageRGB) fH = (fG - fB) * ANGLE_TO_UNIT; } else if (iMax == bG) { // between cyan and yellow. - fH = (2.0f/6.0f) + ( fB - fR ) * ANGLE_TO_UNIT; + fH = (2.0f / 6.0f) + (fB - fR) * ANGLE_TO_UNIT; } else { // between magenta and cyan. - fH = (4.0f/6.0f) + ( fR - fG ) * ANGLE_TO_UNIT; + fH = (4.0f / 6.0f) + (fR - fG) * ANGLE_TO_UNIT; } // Wrap outlier Hues around the circle. if (fH < 0.0f) @@ -666,14 +682,14 @@ Mat BackgroundSubtractorIMBS::convertImageRGBtoHSV(const Mat& imageRGB) void BackgroundSubtractorIMBS::getBackgroundImage(OutputArray backgroundImage) const { - bgImage.copyTo(backgroundImage); + bgImage.copyTo(backgroundImage); } void BackgroundSubtractorIMBS::filterFg() { unsigned int cnt = 0; - for(unsigned int p = 0; p < numPixels; ++p) { - if(fgmask.data[p] == (uchar)255) { + for (unsigned int p = 0; p < numPixels; ++p) { + if (fgmask.data[p] == (uchar)255) { fgfiltered.data[p] = 255; cnt++; } @@ -682,23 +698,23 @@ void BackgroundSubtractorIMBS::filterFg() { } } - if(cnt > numPixels*0.5) { + if (cnt > numPixels*0.5) { sudden_change = true; } - if(morphologicalFiltering) { - cv::Mat element3(3,3,CV_8U,cv::Scalar(1)); + if (morphologicalFiltering) { + cv::Mat element3(3, 3, CV_8U, cv::Scalar(1)); cv::morphologyEx(fgfiltered, fgfiltered, cv::MORPH_OPEN, element3); cv::morphologyEx(fgfiltered, fgfiltered, cv::MORPH_CLOSE, element3); } areaThresholding(); - for(unsigned int p = 0; p < numPixels; ++p) { - if(fgmask.data[p] == PERSISTENCE_LABEL) { + for (unsigned int p = 0; p < numPixels; ++p) { + if (fgmask.data[p] == PERSISTENCE_LABEL) { fgfiltered.data[p] = PERSISTENCE_LABEL; } - else if(fgmask.data[p] == SHADOW_LABEL) { + else if (fgmask.data[p] == SHADOW_LABEL) { fgfiltered.data[p] = SHADOW_LABEL; } } @@ -715,7 +731,7 @@ void BackgroundSubtractorIMBS::changeBg() { //bg_reset = true; //cout << "qua" << endl; - if(!bg_reset) { + if (!bg_reset) { numSamples /= 3.; samplingPeriod /= 2.; bg_frame_counter = 0; @@ -724,19 +740,19 @@ void BackgroundSubtractorIMBS::changeBg() { } void BackgroundSubtractorIMBS::getBgModel(BgModel bgModel_copy[], int size) { - if(size != numPixels) { + if (size != numPixels) { return; } - for(unsigned int i = 0; i < numPixels; ++i){ + for (unsigned int i = 0; i < numPixels; ++i) { bgModel_copy[i].values = new Vec3b[maxBgBins]; bgModel_copy[i].isValid = new bool[maxBgBins]; bgModel_copy[i].isValid[0] = false; bgModel_copy[i].isFg = new bool[maxBgBins]; bgModel_copy[i].counter = new uchar[maxBgBins]; } - for(unsigned int p = 0; p < numPixels; ++p) { - for(unsigned int n = 0; n < maxBgBins; ++n) { - if(!bgModel[p].isValid[n]) { + for (unsigned int p = 0; p < numPixels; ++p) { + for (unsigned int n = 0; n < maxBgBins; ++n) { + if (!bgModel[p].isValid[n]) { break; } bgModel_copy[p].values[n] = bgModel[p].values[n]; diff --git a/package_bgs/db/imbs.hpp b/package_bgs/IMBS/IMBS.hpp similarity index 77% rename from package_bgs/db/imbs.hpp rename to package_bgs/IMBS/IMBS.hpp index fd7faf17ce44bb26a5345984b5768df1a6bf8072..383e0ae27bdfc4b3a15dc703331b943f06d4c47f 100644 --- a/package_bgs/db/imbs.hpp +++ b/package_bgs/IMBS/IMBS.hpp @@ -1,5 +1,21 @@ /* -* IMBS Background Subtraction Library +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 @@ -8,8 +24,8 @@ * 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. +* +* 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 @@ -18,9 +34,7 @@ * domenico.bloisi@gmail.com * */ - -#ifndef __IMBS_HPP__ -#define __IMBS_HPP__ +#pragma once //OPENCV #include <opencv2/core/core.hpp> @@ -41,23 +55,23 @@ public: 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 - ); + 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.); + 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; @@ -73,7 +87,7 @@ private: //method for computing the foreground mask void getFg(); //method for suppressing shadows and highlights - void hsvSuppression(); + void hsvSuppression(); //method for refining foreground mask void filterFg(); //method for filtering out blobs smaller than a given area @@ -82,7 +96,7 @@ private: double getTimestamp(); //method for converting from RGB to HSV Mat convertImageRGBtoHSV(const Mat& imageRGB); - //method for changing the bg in case of sudden changes + //method for changing the bg in case of sudden changes void changeBg(); //current input RGB frame @@ -112,7 +126,7 @@ private: //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 + //initial message to be shown until the first bg model is ready Mat initialMsgGray; Mat initialMsgRGB; @@ -174,5 +188,3 @@ public: } void getBgModel(BgModel bgModel_copy[], int size); }; - -#endif //__IMBS_HPP__ diff --git a/package_bgs/IndependentMultimodal.cpp b/package_bgs/IndependentMultimodal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b4de4cc06f06b84a7d8d72050cbccf497b0ca9a --- /dev/null +++ b/package_bgs/IndependentMultimodal.cpp @@ -0,0 +1,74 @@ +/* +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/StaticFrameDifferenceBGS.h b/package_bgs/IndependentMultimodal.h similarity index 60% rename from package_bgs/StaticFrameDifferenceBGS.h rename to package_bgs/IndependentMultimodal.h index 55f7bf1e360419c1dd7bfce6f19facae07fd7431..4e2e3a38e4e71bf65e729e91f3c27717e07e48eb 100644 --- a/package_bgs/StaticFrameDifferenceBGS.h +++ b/package_bgs/IndependentMultimodal.h @@ -16,30 +16,28 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - #include "IBGS.h" +#include "IMBS/IMBS.hpp" -class StaticFrameDifferenceBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Mat img_background; - cv::Mat img_foreground; - bool enableThreshold; - int threshold; - bool showOutput; - -public: - StaticFrameDifferenceBGS(); - ~StaticFrameDifferenceBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/ae/KDE.cpp b/package_bgs/KDE.cpp similarity index 56% rename from package_bgs/ae/KDE.cpp rename to package_bgs/KDE.cpp index 2cbbd8c808066f8a6c30c7dc31f6ed90068caa84..28564a0c4be11c2d76c89082e2198f6ca2bedeca 100644 --- a/package_bgs/ae/KDE.cpp +++ b/package_bgs/KDE.cpp @@ -16,11 +16,15 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "KDE.h" -KDE::KDE() : SequenceLength(50), TimeWindowSize(100), SDEstimationFlag(1), lUseColorRatiosFlag(1), - th(10e-8), alpha(0.3), framesToLearn(10), frameNumber(0), firstTime(true), showOutput(true) +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() @@ -32,72 +36,73 @@ KDE::~KDE() void KDE::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); + init(img_input, img_output, img_bgmodel); - if(firstTime) + 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. + // 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); + 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); + 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(rows,cols,CV_8UC1); + img_foreground = cv::Mat::zeros(img_input.size(), CV_8UC1); + img_background = cv::Mat::zeros(img_input.size(), img_input.type()); frameNumber = 0; - saveConfig(); firstTime = false; } // Stores the first N frames to build the background model - if(frameNumber < framesToLearn) + if (frameNumber < framesToLearn) { p->AddFrame(img_input.data); frameNumber++; - return; } - - // Build the background model with first 10 frames - if(frameNumber == framesToLearn) + else { - p->Estimation(); - frameNumber++; - } + // 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); - // 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); + // 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; + img_foreground.data = FGImage; + } - if(showOutput) +#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/KDE.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "framesToLearn", framesToLearn); cvWriteInt(fs, "SequenceLength", SequenceLength); @@ -113,16 +118,16 @@ void KDE::saveConfig() void KDE::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/KDE.xml", 0, CV_STORAGE_READ); - - framesToLearn = cvReadIntByName(fs, 0, "framesToLearn", 10); - SequenceLength = cvReadIntByName(fs, 0, "SequenceLength", 50); - TimeWindowSize = cvReadIntByName(fs, 0, "TimeWindowSize", 100); - SDEstimationFlag = cvReadIntByName(fs, 0, "SDEstimationFlag", 1); - lUseColorRatiosFlag = cvReadIntByName(fs, 0, "lUseColorRatiosFlag", 1); - th = cvReadRealByName(fs, 0, "th", 10e-8); - alpha = cvReadRealByName(fs, 0, "alpha", 0.3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..e77996fd485456e1fce78df60697bf6254cacd3b --- /dev/null +++ b/package_bgs/KDE.h @@ -0,0 +1,57 @@ +/* +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/ae/KernelTable.cpp b/package_bgs/KDE/KernelTable.cpp similarity index 75% rename from package_bgs/ae/KernelTable.cpp rename to package_bgs/KDE/KernelTable.cpp index 9e20d7cfc0c09382bc360bda5b069aa870c39d98..bd9c3685c0cf1aa6866eebb6cfcd9f0e5fa0df99 100644 --- a/package_bgs/ae/KernelTable.cpp +++ b/package_bgs/KDE/KernelTable.cpp @@ -26,21 +26,21 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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. +* 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 +* 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. +* A.V. Williams Bldg. * CollegePark, MD 20742 * E-mail: elgammal@umiacs.umd.edu * @@ -67,8 +67,8 @@ KernelLUTable::KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmam { std::cout << "KernelLUTable()" << std::endl; - double C1,C2,v,segma,sum; - int bin,b; + double C1, C2, v, segma, sum; + int bin, b; minsegma = Segmamin; maxsegma = Segmamax; @@ -78,27 +78,27 @@ KernelLUTable::KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmam // Generate the Kernel // allocate memory for the Kernal Table - kerneltable = new double[segmabins*(2*KernelHalfWidth+1)]; + 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++) + for (segma = minsegma, bin = 0; bin < segmabins; segma += segmastep, bin++) { - C1 = 1/(sqrt(2*PI)*segma); - C2 = -1/(2*segma*segma); + C1 = 1 / (sqrt(2 * PI)*segma); + C2 = -1 / (2 * segma*segma); - b = (2*KernelHalfWidth+1)*bin; + b = (2 * KernelHalfWidth + 1)*bin; sum = 0; - - for(int x = 0; x <= KernelHalfWidth; x++) + + for (int x = 0; x <= KernelHalfWidth; x++) { - y = x/1.0; + y = x / 1.0; v = C1*exp(C2*y*y); - kerneltable[b+KernelHalfWidth+x]=v; - kerneltable[b+KernelHalfWidth-x]=v; - sum += 2*v; + kerneltable[b + KernelHalfWidth + x] = v; + kerneltable[b + KernelHalfWidth - x] = v; + sum += 2 * v; } sum -= C1; @@ -106,11 +106,11 @@ KernelLUTable::KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmam kernelsums[bin] = sum; // Normailization - for(int x = 0; x <= KernelHalfWidth; x++) + for (int x = 0; x <= KernelHalfWidth; x++) { - v = kerneltable[b+KernelHalfWidth+x] / sum; - kerneltable[b+KernelHalfWidth+x]=v; - kerneltable[b+KernelHalfWidth-x]=v; + v = kerneltable[b + KernelHalfWidth + x] / sum; + kerneltable[b + KernelHalfWidth + x] = v; + kerneltable[b + KernelHalfWidth - x] = v; } } } diff --git a/package_bgs/ae/KernelTable.h b/package_bgs/KDE/KernelTable.h similarity index 86% rename from package_bgs/ae/KernelTable.h rename to package_bgs/KDE/KernelTable.h index bc37cc4f0a8befb16cf987f7c0f7e697400b1dff..63a20dcdcf257f133abd4403e2fb1dc81618facc 100644 --- a/package_bgs/ae/KernelTable.h +++ b/package_bgs/KDE/KernelTable.h @@ -26,28 +26,26 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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. +* 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 +* 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. +* A.V. Williams Bldg. * CollegePark, MD 20742 * E-mail: elgammal@umiacs.umd.edu * **/ - -#ifndef __KERNEL_TABLE__ -#define __KERNEL_TABLE__ +#pragma once #include <iostream> @@ -65,7 +63,5 @@ public: KernelLUTable(); ~KernelLUTable(); - KernelLUTable(int KernelHalfWidth,double Segmamin,double Segmamax,int Segmabins); + KernelLUTable(int KernelHalfWidth, double Segmamin, double Segmamax, int Segmabins); }; - -#endif diff --git a/package_bgs/KDE/NPBGSubtractor.cpp b/package_bgs/KDE/NPBGSubtractor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f004b9f1f2cb77fc80b6f3bade41f026ff17cad --- /dev/null +++ b/package_bgs/KDE/NPBGSubtractor.cpp @@ -0,0 +1,1160 @@ +/* +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/ae/NPBGSubtractor.h b/package_bgs/KDE/NPBGSubtractor.h similarity index 87% rename from package_bgs/ae/NPBGSubtractor.h rename to package_bgs/KDE/NPBGSubtractor.h index e7f379542767bec2b6e47b1b1b74a2574e58ebb9..ce4bffc4812904a81a203c63f64bf1cf6080d14a 100644 --- a/package_bgs/ae/NPBGSubtractor.h +++ b/package_bgs/KDE/NPBGSubtractor.h @@ -26,21 +26,21 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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. +* 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 +* 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. +* A.V. Williams Bldg. * CollegePark, MD 20742 * E-mail: elgammal@umiacs.umd.edu * @@ -49,13 +49,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // NPBGSubtractor.h: interface for the NPBGSubtractor class. // ////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_NPBGSUBTRACTOR_H__84B0F51E_6E65_41E4_AC01_723B406363C4__INCLUDED_) -#define AFX_NPBGSUBTRACTOR_H__84B0F51E_6E65_41E4_AC01_723B406363C4__INCLUDED_ - -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 #include "NPBGmodel.h" #include "KernelTable.h" @@ -87,7 +81,7 @@ typedef struct unsigned int *List; } ImageIndex; -class NPBGSubtractor +class NPBGSubtractor { private: unsigned int rows; @@ -146,9 +140,7 @@ public: AlphaValue = alpha; }; - void SetUpdateFlag(unsigned int bgflag){ + void SetUpdateFlag(unsigned int bgflag) { UpdateBGFlag = bgflag; }; }; - -#endif // !defined(AFX_NPBGSUBTRACTOR_H__84B0F51E_6E65_41E4_AC01_723B406363C4__INCLUDED_) diff --git a/package_bgs/ae/NPBGmodel.cpp b/package_bgs/KDE/NPBGmodel.cpp similarity index 78% rename from package_bgs/ae/NPBGmodel.cpp rename to package_bgs/KDE/NPBGmodel.cpp index 2c8b07400992bf4db7810723b6fef930ed806ee3..a79a7b42f1ae663d3da1afaef56899bd4cd3f218 100644 --- a/package_bgs/ae/NPBGmodel.cpp +++ b/package_bgs/KDE/NPBGmodel.cpp @@ -26,21 +26,21 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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. +* 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 +* 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. +* A.V. Williams Bldg. * CollegePark, MD 20742 * E-mail: elgammal@umiacs.umd.edu * @@ -55,7 +55,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #ifdef _DEBUG #undef THIS_FILE -static char THIS_FILE[]=__FILE__; +static char THIS_FILE[] = __FILE__; //#define new DEBUG_NEW #endif @@ -80,11 +80,11 @@ NPBGmodel::~NPBGmodel() } NPBGmodel::NPBGmodel(unsigned int Rows, - unsigned int Cols, - unsigned int ColorChannels, - unsigned int Length, - unsigned int pTimeWindowSize, - unsigned int bg_suppression_time) + unsigned int Cols, + unsigned int ColorChannels, + unsigned int Length, + unsigned int pTimeWindowSize, + unsigned int bg_suppression_time) { std::cout << "NPBGmodel()" << std::endl; @@ -98,14 +98,14 @@ NPBGmodel::NPBGmodel(unsigned int Rows, TimeWindowSize = pTimeWindowSize; - Sequence = new unsigned char[imagesize*Length]; + Sequence = new unsigned char[imagesize*Length]; Top = 0; - memset(Sequence,0,imagesize*Length); + memset(Sequence, 0, imagesize*Length); PixelQTop = new unsigned char[rows*cols]; // temporalBuffer - TemporalBufferLength = (TimeWindowSize/Length > 2 ? TimeWindowSize/Length:2); + TemporalBufferLength = (TimeWindowSize / Length > 2 ? TimeWindowSize / Length : 2); TemporalBuffer = new unsigned char[imagesize*TemporalBufferLength]; TemporalMask = new unsigned char[rows*cols*TemporalBufferLength]; @@ -116,12 +116,12 @@ NPBGmodel::NPBGmodel(unsigned int Rows, ResetMaskTh = bg_suppression_time; } -void NPBGmodel::AddFrame(unsigned char *ImageBuffer) +void NPBGmodel::AddFrame(unsigned char *ImageBuffer) { - memcpy(Sequence+Top*imagesize,ImageBuffer,imagesize); - Top = (Top + 1) % SampleSize; + memcpy(Sequence + Top*imagesize, ImageBuffer, imagesize); + Top = (Top + 1) % SampleSize; - memset(PixelQTop, (unsigned char) Top, rows*cols); + memset(PixelQTop, (unsigned char)Top, rows*cols); - memcpy(TemporalBuffer,ImageBuffer,imagesize); + memcpy(TemporalBuffer, ImageBuffer, imagesize); } diff --git a/package_bgs/ae/NPBGmodel.h b/package_bgs/KDE/NPBGmodel.h similarity index 84% rename from package_bgs/ae/NPBGmodel.h rename to package_bgs/KDE/NPBGmodel.h index 9e285108eec393167c327970aa1c783733c71447..ba4a927875ea083f5e99dad42ee7a4bee3f9ea32 100644 --- a/package_bgs/ae/NPBGmodel.h +++ b/package_bgs/KDE/NPBGmodel.h @@ -26,21 +26,21 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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. +* 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 +* 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. +* A.V. Williams Bldg. * CollegePark, MD 20742 * E-mail: elgammal@umiacs.umd.edu * @@ -49,24 +49,18 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // NPBGmodel.h: interface for the NPBGmodel class. // ////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_NPBGMODEL_H__CCAF05D4_D06E_44C2_95D8_979E2249953A__INCLUDED_) -#define AFX_NPBGMODEL_H__CCAF05D4_D06E_44C2_95D8_979E2249953A__INCLUDED_ - -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 #include <iostream> -class NPBGmodel +class NPBGmodel { private: unsigned char *Sequence; unsigned int SampleSize; unsigned int TimeWindowSize; - unsigned int rows,cols,color_channels; + unsigned int rows, cols, color_channels; unsigned int imagesize; unsigned int Top; @@ -74,7 +68,7 @@ private: //unsigned int *PixelUpdateCounter; - unsigned char *SDbinsImage; + unsigned char *SDbinsImage; unsigned char *TemporalBuffer; unsigned char TemporalBufferLength; @@ -107,5 +101,3 @@ public: friend class NPBGSubtractor; }; - -#endif // !defined(AFX_NPBGMODEL_H__CCAF05D4_D06E_44C2_95D8_979E2249953A__INCLUDED_) diff --git a/package_bgs/KNN.cpp b/package_bgs/KNN.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2e14127ee2efcde134226b10871716994bc1f5e --- /dev/null +++ b/package_bgs/KNN.cpp @@ -0,0 +1,111 @@ +/* + 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 new file mode 100644 index 0000000000000000000000000000000000000000..87f20b249444b5ad2da2864e6b30eb0b9b36e78b --- /dev/null +++ b/package_bgs/KNN.h @@ -0,0 +1,57 @@ +/* +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/lb/LBAdaptiveSOM.cpp b/package_bgs/LBAdaptiveSOM.cpp similarity index 61% rename from package_bgs/lb/LBAdaptiveSOM.cpp rename to package_bgs/LBAdaptiveSOM.cpp index ce06433cf8ab1547a053bbf0576f7c2c6026009f..188e11d450ca29709fd5b1fcc567982ecb0f1360 100644 --- a/package_bgs/lb/LBAdaptiveSOM.cpp +++ b/package_bgs/LBAdaptiveSOM.cpp @@ -16,10 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "LBAdaptiveSOM.h" -LBAdaptiveSOM::LBAdaptiveSOM() : firstTime(true), showOutput(true), +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() @@ -30,64 +33,55 @@ LBAdaptiveSOM::~LBAdaptiveSOM() void LBAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - IplImage *frame = new IplImage(img_input); - - if(firstTime) - { - saveConfig(); + if (firstTime) + { int w = cvGetSize(frame).width; int h = cvGetSize(frame).height; - m_pBGModel = new BGModelSom(w,h); + 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->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::Mat(m_pBGModel->GetFG()); - img_background = cv::Mat(m_pBGModel->GetBG()); - - if(showOutput) + 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::finish(void) -//{ -// delete m_pBGModel; -//} - void LBAdaptiveSOM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBAdaptiveSOM.xml", 0, CV_STORAGE_WRITE); + 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); @@ -95,15 +89,14 @@ void LBAdaptiveSOM::saveConfig() void LBAdaptiveSOM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBAdaptiveSOM.xml", 0, CV_STORAGE_READ); - - sensitivity = cvReadIntByName(fs, 0, "sensitivity", 75); - trainingSensitivity = cvReadIntByName(fs, 0, "trainingSensitivity", 245); - learningRate = cvReadIntByName(fs, 0, "learningRate", 62); - trainingLearningRate = cvReadIntByName(fs, 0, "trainingLearningRate", 255); - trainingSteps = cvReadIntByName(fs, 0, "trainingSteps", 55); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/lb/LBAdaptiveSOM.h b/package_bgs/LBAdaptiveSOM.h similarity index 55% rename from package_bgs/lb/LBAdaptiveSOM.h rename to package_bgs/LBAdaptiveSOM.h index beaf77b62a44cecc0ce4d43f754843847306efab..7671ae1df9ff0540e2c74e3da8d53c5d58cceccd 100644 --- a/package_bgs/lb/LBAdaptiveSOM.h +++ b/package_bgs/LBAdaptiveSOM.h @@ -16,41 +16,35 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "BGModelSom.h" - -#include "../IBGS.h" +#include "lb/BGModelSom.h" +#include "IBGS.h" using namespace lb_library; using namespace lb_library::AdaptiveSOM; -class LBAdaptiveSOM : public IBGS +namespace bgslibrary { -private: - bool firstTime; - bool showOutput; - - BGModel* m_pBGModel; - int sensitivity; - int trainingSensitivity; - int learningRate; - int trainingLearningRate; - int trainingSteps; - - cv::Mat img_foreground; - cv::Mat img_background; - -public: - LBAdaptiveSOM(); - ~LBAdaptiveSOM(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - //void finish(void); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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/lb/LBFuzzyAdaptiveSOM.cpp b/package_bgs/LBFuzzyAdaptiveSOM.cpp similarity index 59% rename from package_bgs/lb/LBFuzzyAdaptiveSOM.cpp rename to package_bgs/LBFuzzyAdaptiveSOM.cpp index 4ef856028cbd063cda01e3aaacef7c702c9713d4..73df1d7ba56f18bc35f2ca667727495b254f7555 100644 --- a/package_bgs/lb/LBFuzzyAdaptiveSOM.cpp +++ b/package_bgs/LBFuzzyAdaptiveSOM.cpp @@ -16,10 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "LBFuzzyAdaptiveSOM.h" -LBFuzzyAdaptiveSOM::LBFuzzyAdaptiveSOM() : firstTime(true), showOutput(true), +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() @@ -30,64 +33,55 @@ LBFuzzyAdaptiveSOM::~LBFuzzyAdaptiveSOM() void LBFuzzyAdaptiveSOM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - IplImage *frame = new IplImage(img_input); - - if(firstTime) - { - saveConfig(); + if (firstTime) + { int w = cvGetSize(frame).width; int h = cvGetSize(frame).height; - m_pBGModel = new BGModelFuzzySom(w,h); + 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->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::Mat(m_pBGModel->GetFG()); - img_background = cv::Mat(m_pBGModel->GetBG()); - - if(showOutput) + 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::finish(void) -//{ -// //delete m_pBGModel; -//} - void LBFuzzyAdaptiveSOM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBFuzzyAdaptiveSOM.xml", 0, CV_STORAGE_WRITE); + 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); @@ -95,15 +89,14 @@ void LBFuzzyAdaptiveSOM::saveConfig() void LBFuzzyAdaptiveSOM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBFuzzyAdaptiveSOM.xml", 0, CV_STORAGE_READ); - - sensitivity = cvReadIntByName(fs, 0, "sensitivity", 90); - trainingSensitivity = cvReadIntByName(fs, 0, "trainingSensitivity", 240); - learningRate = cvReadIntByName(fs, 0, "learningRate", 38); - trainingLearningRate = cvReadIntByName(fs, 0, "trainingLearningRate", 255); - trainingSteps = cvReadIntByName(fs, 0, "trainingSteps", 81); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/lb/LBFuzzyAdaptiveSOM.h b/package_bgs/LBFuzzyAdaptiveSOM.h similarity index 55% rename from package_bgs/lb/LBFuzzyAdaptiveSOM.h rename to package_bgs/LBFuzzyAdaptiveSOM.h index 9c11d7568c46e8463424145cc6aae72c99ed58c0..6a4a85c0007951b3a82b6f11941e669d16430332 100644 --- a/package_bgs/lb/LBFuzzyAdaptiveSOM.h +++ b/package_bgs/LBFuzzyAdaptiveSOM.h @@ -16,41 +16,35 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "BGModelFuzzySom.h" - -#include "../IBGS.h" +#include "IBGS.h" +#include "lb/BGModelFuzzySom.h" using namespace lb_library; using namespace lb_library::FuzzyAdaptiveSOM; -class LBFuzzyAdaptiveSOM : public IBGS +namespace bgslibrary { -private: - bool firstTime; - bool showOutput; - - BGModel* m_pBGModel; - int sensitivity; - int trainingSensitivity; - int learningRate; - int trainingLearningRate; - int trainingSteps; - - cv::Mat img_foreground; - cv::Mat img_background; - -public: - LBFuzzyAdaptiveSOM(); - ~LBFuzzyAdaptiveSOM(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - //void finish(void); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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/lb/LBFuzzyGaussian.cpp b/package_bgs/LBFuzzyGaussian.cpp similarity index 59% rename from package_bgs/lb/LBFuzzyGaussian.cpp rename to package_bgs/LBFuzzyGaussian.cpp index dc257bf40325167efbe49220be9d08f9f745d4f7..b1610260bf407bc19a0750234fed4e1528ea7f06 100644 --- a/package_bgs/lb/LBFuzzyGaussian.cpp +++ b/package_bgs/LBFuzzyGaussian.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "LBFuzzyGaussian.h" -LBFuzzyGaussian::LBFuzzyGaussian() : firstTime(true), showOutput(true), sensitivity(72), bgThreshold(162), learningRate(49), noiseVariance(195) +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() @@ -29,62 +33,53 @@ LBFuzzyGaussian::~LBFuzzyGaussian() void LBFuzzyGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - IplImage *frame = new IplImage(img_input); - - if(firstTime) - { - saveConfig(); + if (firstTime) + { int w = cvGetSize(frame).width; int h = cvGetSize(frame).height; - m_pBGModel = new BGModelFuzzyGauss(w,h); + 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->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::Mat(m_pBGModel->GetFG()); - img_background = cv::Mat(m_pBGModel->GetBG()); - - if(showOutput) + 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::finish(void) -//{ -// delete m_pBGModel; -//} - void LBFuzzyGaussian::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBFuzzyGaussian.xml", 0, CV_STORAGE_WRITE); + 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); @@ -92,14 +87,13 @@ void LBFuzzyGaussian::saveConfig() void LBFuzzyGaussian::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBFuzzyGaussian.xml", 0, CV_STORAGE_READ); - - sensitivity = cvReadIntByName(fs, 0, "sensitivity", 72); - bgThreshold = cvReadIntByName(fs, 0, "bgThreshold", 162); - learningRate = cvReadIntByName(fs, 0, "learningRate", 49); - noiseVariance = cvReadIntByName(fs, 0, "noiseVariance", 195); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/lb/LBFuzzyGaussian.h b/package_bgs/LBFuzzyGaussian.h similarity index 56% rename from package_bgs/lb/LBFuzzyGaussian.h rename to package_bgs/LBFuzzyGaussian.h index f76156ef20ed1152e280a8de60f5fca966119ed7..53c26679d55f1d7720b1eabbce8486f609e7c15d 100644 --- a/package_bgs/lb/LBFuzzyGaussian.h +++ b/package_bgs/LBFuzzyGaussian.h @@ -16,40 +16,34 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "BGModelFuzzyGauss.h" - -#include "../IBGS.h" +#include "IBGS.h" +#include "lb/BGModelFuzzyGauss.h" using namespace lb_library; using namespace lb_library::FuzzyGaussian; -class LBFuzzyGaussian : public IBGS +namespace bgslibrary { -private: - bool firstTime; - bool showOutput; - - BGModel* m_pBGModel; - int sensitivity; - int bgThreshold; - int learningRate; - int noiseVariance; - - cv::Mat img_foreground; - cv::Mat img_background; - -public: - LBFuzzyGaussian(); - ~LBFuzzyGaussian(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - //void finish(void); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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/lb/LBMixtureOfGaussians.cpp b/package_bgs/LBMixtureOfGaussians.cpp similarity index 59% rename from package_bgs/lb/LBMixtureOfGaussians.cpp rename to package_bgs/LBMixtureOfGaussians.cpp index 8d235c506601f7b2a57379810c3fcd9c4ee75779..6cd9c917ca6d9fddbc01e94e7eb71a998418ba5e 100644 --- a/package_bgs/lb/LBMixtureOfGaussians.cpp +++ b/package_bgs/LBMixtureOfGaussians.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "LBMixtureOfGaussians.h" -LBMixtureOfGaussians::LBMixtureOfGaussians() : firstTime(true), showOutput(true), sensitivity(81), bgThreshold(83), learningRate(59), noiseVariance(206) +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() @@ -29,62 +33,53 @@ LBMixtureOfGaussians::~LBMixtureOfGaussians() void LBMixtureOfGaussians::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - IplImage *frame = new IplImage(img_input); - - if(firstTime) - { - saveConfig(); + if (firstTime) + { int w = cvGetSize(frame).width; int h = cvGetSize(frame).height; - m_pBGModel = new BGModelMog(w,h); + 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->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::Mat(m_pBGModel->GetFG()); - img_background = cv::Mat(m_pBGModel->GetBG()); - - if(showOutput) + 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::finish(void) -//{ -// delete m_pBGModel; -//} - void LBMixtureOfGaussians::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBMixtureOfGaussians.xml", 0, CV_STORAGE_WRITE); + 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); @@ -92,14 +87,13 @@ void LBMixtureOfGaussians::saveConfig() void LBMixtureOfGaussians::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBMixtureOfGaussians.xml", 0, CV_STORAGE_READ); - - sensitivity = cvReadIntByName(fs, 0, "sensitivity", 81); - bgThreshold = cvReadIntByName(fs, 0, "bgThreshold", 83); - learningRate = cvReadIntByName(fs, 0, "learningRate", 59); - noiseVariance = cvReadIntByName(fs, 0, "noiseVariance", 206); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/lb/LBMixtureOfGaussians.h b/package_bgs/LBMixtureOfGaussians.h similarity index 56% rename from package_bgs/lb/LBMixtureOfGaussians.h rename to package_bgs/LBMixtureOfGaussians.h index 3b1a96d9cc166dbd89804c86a75df68f646e00ff..8d4cb5619d42f85a74491cea340615f869b72d9a 100644 --- a/package_bgs/lb/LBMixtureOfGaussians.h +++ b/package_bgs/LBMixtureOfGaussians.h @@ -16,40 +16,35 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "BGModelMog.h" - -#include "../IBGS.h" +#include "IBGS.h" +#include "lb/BGModelMog.h" using namespace lb_library; using namespace lb_library::MixtureOfGaussians; -class LBMixtureOfGaussians : public IBGS +namespace bgslibrary { -private: - bool firstTime; - bool showOutput; - - BGModel* m_pBGModel; - int sensitivity; - int bgThreshold; - int learningRate; - int noiseVariance; - - cv::Mat img_foreground; - cv::Mat img_background; - -public: - LBMixtureOfGaussians(); - ~LBMixtureOfGaussians(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - //void finish(void); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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/ck/LbpMrf.cpp b/package_bgs/LBP_MRF.cpp similarity index 57% rename from package_bgs/ck/LbpMrf.cpp rename to package_bgs/LBP_MRF.cpp index f3d068c253505783976837916c3e4611bbed63bb..b9e6bbe019511ccff12706fd40f4effbb479c054 100644 --- a/package_bgs/ck/LbpMrf.cpp +++ b/package_bgs/LBP_MRF.cpp @@ -18,35 +18,29 @@ Csaba, Kertész: Texture-Based Foreground Detection, International Journal of Si Image Processing and Pattern Recognition (IJSIP), Vol. 4, No. 4, 2011. */ -#include "LbpMrf.h" +#include "LBP_MRF.h" -#include "MotionDetection.hpp" +using namespace bgslibrary::algorithms; -LbpMrf::LbpMrf() : firstTime(true), Detector(NULL), showOutput(true) +LBP_MRF::LBP_MRF() : + Detector(nullptr) { - std::cout << "LbpMrf()" << std::endl; + std::cout << "LBP_MRF()" << std::endl; + setup("./config/LBP_MRF.xml"); Detector = new MotionDetection(); Detector->SetMode(MotionDetection::md_LBPHistograms); } -LbpMrf::~LbpMrf() +LBP_MRF::~LBP_MRF() { - std::cout << "~LbpMrf()" << std::endl; + std::cout << "~LBP_MRF()" << std::endl; delete Detector; - Detector = NULL; + Detector = nullptr; } -void LbpMrf::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void LBP_MRF::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - { - saveConfig(); - } + init(img_input, img_output, img_bgmodel); IplImage TempImage(img_input); MEImage InputImage(img_input.cols, img_input.rows, img_input.channels()); @@ -56,32 +50,35 @@ void LbpMrf::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img Detector->DetectMotions(InputImage); Detector->GetMotionsMask(OutputImage); - img_output = (IplImage*)OutputImage.GetIplImage(); - bitwise_not(img_output, img_bgmodel); + 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 - if(showOutput) - { - cv::imshow("LBP-MRF FG", img_output); - cv::imshow("LBP-MRF BG", img_bgmodel); - } + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); firstTime = false; } -void LbpMrf::saveConfig() +void LBP_MRF::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LbpMrf.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "showOutput", showOutput); cvReleaseFileStorage(&fs); } -void LbpMrf::loadConfig() +void LBP_MRF::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LbpMrf.xml", 0, CV_STORAGE_READ); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + showOutput = cvReadIntByName(fs, nullptr, "showOutput", true); cvReleaseFileStorage(&fs); } diff --git a/package_bgs/WeightedMovingMeanBGS.h b/package_bgs/LBP_MRF.h similarity index 58% rename from package_bgs/WeightedMovingMeanBGS.h rename to package_bgs/LBP_MRF.h index 6f72306c10a18debc70d5e87a1cc8f5b20fd08e9..a6e5c05b984d6ee3c8beb6cc97f94804a8de506d 100644 --- a/package_bgs/WeightedMovingMeanBGS.h +++ b/package_bgs/LBP_MRF.h @@ -16,32 +16,28 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - #include "IBGS.h" +#include "LBP_MRF/MotionDetection.hpp" -class WeightedMovingMeanBGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::Mat img_input_prev_1; - cv::Mat img_input_prev_2; - bool enableWeight; - bool enableThreshold; - int threshold; - bool showOutput; - bool showBackground; - -public: - WeightedMovingMeanBGS(); - ~WeightedMovingMeanBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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 new file mode 100644 index 0000000000000000000000000000000000000000..95b803333991104738bf58a771f7ff4882f9c488 --- /dev/null +++ b/package_bgs/LBP_MRF/MEDefs.cpp @@ -0,0 +1,57 @@ +/* +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/ck/MEDefs.hpp b/package_bgs/LBP_MRF/MEDefs.hpp similarity index 73% rename from package_bgs/ck/MEDefs.hpp rename to package_bgs/LBP_MRF/MEDefs.hpp index d5bc24637555a67639842a9269ea758d605db9dd..a886ee9ff3be75eb4c3841b38609fbd33dc30037 100644 --- a/package_bgs/ck/MEDefs.hpp +++ b/package_bgs/LBP_MRF/MEDefs.hpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -18,16 +34,9 @@ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. * */ +#pragma once -#ifndef MEDefs_hpp -#define MEDefs_hpp - -/** - * @addtogroup mindeye - * @{ - */ - -/// Pi value + /// Pi value #ifndef ME_PI_VALUE #define ME_PI_VALUE 3.14159265 #endif @@ -79,5 +88,3 @@ const T& MEBound(const T& min, const T& val, const T& max) float MERound(float number); /** @} */ - -#endif diff --git a/package_bgs/ck/MEHistogram.cpp b/package_bgs/LBP_MRF/MEHistogram.cpp similarity index 54% rename from package_bgs/ck/MEHistogram.cpp rename to package_bgs/LBP_MRF/MEHistogram.cpp index 09a96724763d527a63f3dd6167dcf7d1b7815e3a..17c77fdb9079f40391229f37401e64dd5b0e2b1e 100644 --- a/package_bgs/ck/MEHistogram.cpp +++ b/package_bgs/LBP_MRF/MEHistogram.cpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -45,7 +61,7 @@ MEHistogram::~MEHistogram() void MEHistogram::Clear() { - memset(&HistogramData, 0, 256*sizeof(int)); + memset(&HistogramData, 0, 256 * sizeof(int)); } @@ -77,11 +93,11 @@ void MEHistogram::Calculate(MEImage& image, int channel, HistogramType mode) unsigned char *ImageData = image.GetImageData(); int rowStart = 0; - for (int i = image.GetHeight()-1; i >= 0; i--) + for (int i = image.GetHeight() - 1; i >= 0; i--) { - for (int i1 = (image.GetWidth()-1)*image.GetLayers()+Channel-1; i1 >= Channel-1; i1 -= image.GetLayers()) + for (int i1 = (image.GetWidth() - 1)*image.GetLayers() + Channel - 1; i1 >= Channel - 1; i1 -= image.GetLayers()) { - HistogramData[ImageData[rowStart+i1]]++; + HistogramData[ImageData[rowStart + i1]]++; } rowStart += image.GetRowWidth(); } @@ -99,11 +115,11 @@ void MEHistogram::Calculate(MEImage& image, HistogramType mode) int RowStart = 0; int RowWidth = image.GetRowWidth(); - for (int i = image.GetHeight()-1; i >= 0; i--) + for (int i = image.GetHeight() - 1; i >= 0; i--) { - for (int i1 = image.GetWidth()*image.GetLayers()-1; i1 >= 0; i1--) + for (int i1 = image.GetWidth()*image.GetLayers() - 1; i1 >= 0; i1--) { - HistogramData[ImageData[RowStart+i1]]++; + HistogramData[ImageData[RowStart + i1]]++; } RowStart += RowWidth; } @@ -126,16 +142,16 @@ void MEHistogram::Calculate(MEImage& image, int channel, int x0, int y0, int x1, // Compute the correct region coordinates and check them X0 = X0 < 0 ? 0 : X0; Y0 = Y0 < 0 ? 0 : Y0; - X1 = X1 > image.GetWidth()-1 ? image.GetWidth()-1 : X1; - Y1 = Y1 > image.GetHeight()-1 ? image.GetHeight()-1 : Y1; + X1 = X1 > image.GetWidth() - 1 ? image.GetWidth() - 1 : X1; + Y1 = Y1 > image.GetHeight() - 1 ? image.GetHeight() - 1 : Y1; RowStart = Y0*image.GetRowWidth(); for (int i = Y1; i >= Y0; --i) { - for (int i1 = X1*image.GetLayers()+Channel-1; i1 >= X0*image.GetLayers()+Channel-1; - i1 -= image.GetLayers()) + for (int i1 = X1*image.GetLayers() + Channel - 1; i1 >= X0*image.GetLayers() + Channel - 1; + i1 -= image.GetLayers()) { - HistogramData[ImageData[RowStart+i1]]++; + HistogramData[ImageData[RowStart + i1]]++; } RowStart += RowWidth; } @@ -242,70 +258,70 @@ bool MEHistogram::Stretch(StretchType mode) switch (mode) { - case s_OwnMode: - Percent = 20; + case s_OwnMode: + Percent = 20; + MinIndex = GetLowestLimitIndex(Percent); + MaxIndex = GetHighestLimitIndex(Percent); + + while ((abs(MaxIndex - MinIndex) < 52) && (Percent > 1)) + { + Percent = Percent / 2; MinIndex = GetLowestLimitIndex(Percent); MaxIndex = GetHighestLimitIndex(Percent); - while ((abs(MaxIndex-MinIndex) < 52) && (Percent > 1)) + // The calculation gives wrong answer back + if (MinIndex == 0 && MaxIndex == 255) { - Percent = Percent / 2; - MinIndex = GetLowestLimitIndex(Percent); - MaxIndex = GetHighestLimitIndex(Percent); - - // The calculation gives wrong answer back - if (MinIndex == 0 && MaxIndex == 255) - { - MinIndex = 128; - MaxIndex = 128; - Ret = false; - } + MinIndex = 128; + MaxIndex = 128; + Ret = false; } - break; + } + break; - case s_GimpMode: - Count = GetPowerAmount(0, 255); - NewCount = 0; + case s_GimpMode: + Count = GetPowerAmount(0, 255); + NewCount = 0; - for (int i = 0; i < 255; i++) - { - double Value = 0.0; - double NextValue = 0.0; + for (int i = 0; i < 255; i++) + { + double Value = 0.0; + double NextValue = 0.0; - Value = HistogramData[i]; - NextValue = HistogramData[i+1]; - NewCount += Value; - Percentage = NewCount / Count; - NextPercentage = (NewCount+NextValue) / Count; + Value = HistogramData[i]; + NextValue = HistogramData[i + 1]; + NewCount += Value; + Percentage = NewCount / Count; + NextPercentage = (NewCount + NextValue) / Count; - if (fabs(Percentage-0.006) < fabs(NextPercentage-0.006)) - { - MinIndex = i+1; - break; - } - } - NewCount = 0.0; - for (int i = 255; i > 0; i--) + if (fabs(Percentage - 0.006) < fabs(NextPercentage - 0.006)) { - double Value = 0.0; - double NextValue = 0.0; + MinIndex = i + 1; + break; + } + } + NewCount = 0.0; + for (int i = 255; i > 0; i--) + { + double Value = 0.0; + double NextValue = 0.0; - Value = HistogramData[i]; - NextValue = HistogramData[i-1]; - NewCount += Value; - Percentage = NewCount / Count; - NextPercentage = (NewCount+NextValue) / Count; + Value = HistogramData[i]; + NextValue = HistogramData[i - 1]; + NewCount += Value; + Percentage = NewCount / Count; + NextPercentage = (NewCount + NextValue) / Count; - if (fabs(Percentage-0.006) < fabs(NextPercentage-0.006)) - { - MaxIndex = i-1; - break; - } + if (fabs(Percentage - 0.006) < fabs(NextPercentage - 0.006)) + { + MaxIndex = i - 1; + break; } - break; + } + break; - default: - break; + default: + break; } if (MaxIndex <= MinIndex) @@ -314,8 +330,8 @@ bool MEHistogram::Stretch(StretchType mode) MaxIndex = 255; Ret = false; } - if (MaxIndex-MinIndex <= 10 || - (MaxIndex-MinIndex <= 20 && (float)GetPowerAmount(MinIndex, MaxIndex) / GetPowerAmount(0, 255) < 0.20)) + if (MaxIndex - MinIndex <= 10 || + (MaxIndex - MinIndex <= 20 && (float)GetPowerAmount(MinIndex, MaxIndex) / GetPowerAmount(0, 255) < 0.20)) { MinIndex = 0; MaxIndex = 255; @@ -327,7 +343,7 @@ bool MEHistogram::Stretch(StretchType mode) for (int i = 0; i < 256; ++i) { - TransformedHistogram[i] = (unsigned char)MEBound(0, 255*(i-MinIndex) / (MaxIndex-MinIndex), 255); + TransformedHistogram[i] = (unsigned char)MEBound(0, 255 * (i - MinIndex) / (MaxIndex - MinIndex), 255); } for (int i = 0; i < 256; ++i) { @@ -371,7 +387,7 @@ void MEHistogramTransform::HistogramStretch(MEImage& image, TransformType time_m for (int l = 1; l < image.GetLayers(); l++) { - RedChannel.Calculate(image, l+1, MEHistogram::h_Add); + RedChannel.Calculate(image, l + 1, MEHistogram::h_Add); } RedChannel.Stretch(StretchMode); if (time_mode == t_Discrete && !DiscreteStretchingDone) @@ -383,45 +399,46 @@ void MEHistogramTransform::HistogramStretch(MEImage& image, TransformType time_m int RowStart = 0; int RowWidth = image.GetRowWidth(); - for (int i = image.GetHeight()-1; i >= 0; i--) + for (int i = image.GetHeight() - 1; i >= 0; i--) { - for (int i1 = image.GetWidth()*image.GetLayers()-1; i1 >= 0; i1--) + for (int i1 = image.GetWidth()*image.GetLayers() - 1; i1 >= 0; i1--) { - ImageData[RowStart+i1] = RedChannel.HistogramData[ImageData[RowStart+i1]]; + ImageData[RowStart + i1] = RedChannel.HistogramData[ImageData[RowStart + i1]]; } RowStart += RowWidth; } - } else - if (ChannelMode == p_SeparateChannels) - { - if (time_mode == t_Continuous || (time_mode == t_Discrete && !DiscreteStretchingDone)) + } + else + if (ChannelMode == p_SeparateChannels) { - RedChannel.Calculate(image, 1, MEHistogram::h_Overwrite); - GreenChannel.Calculate(image, 2, MEHistogram::h_Overwrite); - BlueChannel.Calculate(image, 3, MEHistogram::h_Overwrite); - RedChannel.Stretch(StretchMode); - GreenChannel.Stretch(StretchMode); - BlueChannel.Stretch(StretchMode); - if (time_mode == t_Discrete && !DiscreteStretchingDone) + if (time_mode == t_Continuous || (time_mode == t_Discrete && !DiscreteStretchingDone)) { - DiscreteStretchingDone = true; + RedChannel.Calculate(image, 1, MEHistogram::h_Overwrite); + GreenChannel.Calculate(image, 2, MEHistogram::h_Overwrite); + BlueChannel.Calculate(image, 3, MEHistogram::h_Overwrite); + RedChannel.Stretch(StretchMode); + GreenChannel.Stretch(StretchMode); + BlueChannel.Stretch(StretchMode); + if (time_mode == t_Discrete && !DiscreteStretchingDone) + { + DiscreteStretchingDone = true; + } } - } - unsigned char *ImageData = image.GetImageData(); - int RowStart = 0; - int RowWidth = image.GetRowWidth(); + unsigned char *ImageData = image.GetImageData(); + int RowStart = 0; + int RowWidth = image.GetRowWidth(); - for (int i = image.GetHeight()-1; i >= 0; i--) - { - for (int i1 = image.GetWidth()*image.GetLayers()-3; i1 >= 0; i1 -= 3) + for (int i = image.GetHeight() - 1; i >= 0; i--) { - ImageData[RowStart+i1] = RedChannel.HistogramData[ImageData[RowStart+i1]]; - ImageData[RowStart+i1+1] = GreenChannel.HistogramData[ImageData[RowStart+i1+1]]; - ImageData[RowStart+i1+2] = BlueChannel.HistogramData[ImageData[RowStart+i1+2]]; + for (int i1 = image.GetWidth()*image.GetLayers() - 3; i1 >= 0; i1 -= 3) + { + ImageData[RowStart + i1] = RedChannel.HistogramData[ImageData[RowStart + i1]]; + ImageData[RowStart + i1 + 1] = GreenChannel.HistogramData[ImageData[RowStart + i1 + 1]]; + ImageData[RowStart + i1 + 2] = BlueChannel.HistogramData[ImageData[RowStart + i1 + 2]]; + } + RowStart += RowWidth; } - RowStart += RowWidth; } - } } @@ -433,72 +450,72 @@ void MEHistogramTransform::HistogramEqualize(MEImage& image) switch (image.GetLayers()) { - case 1: - // Grayscale image - cvDest8bitImg = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); - cvEqualizeHist((IplImage*)image.GetIplImage(), cvDest8bitImg); - image.SetIplImage((void*)cvDest8bitImg); - cvReleaseImage(&cvDest8bitImg); - break; - - case 3: - // RGB image - cvDestImg = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 3); - IplImage *cvR, *cvG, *cvB; - - cvR = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); - cvG = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); - cvB = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); - - cvSplit((IplImage*)image.GetIplImage(), cvR, cvG, cvB, NULL); - cvEqualizeHist(cvR, cvR); - cvEqualizeHist(cvG, cvG); - cvEqualizeHist(cvB, cvB); - cvMerge(cvR, cvG, cvB, NULL, cvDestImg); - - image.SetIplImage((void*)cvDestImg); - cvReleaseImage(&cvR); - cvReleaseImage(&cvG); - cvReleaseImage(&cvB); - cvReleaseImage(&cvDestImg); - break; - - default: - break; + case 1: + // Grayscale image + cvDest8bitImg = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); + cvEqualizeHist((IplImage*)image.GetIplImage(), cvDest8bitImg); + image.SetIplImage((void*)cvDest8bitImg); + cvReleaseImage(&cvDest8bitImg); + break; + + case 3: + // RGB image + cvDestImg = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 3); + IplImage *cvR, *cvG, *cvB; + + cvR = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); + cvG = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); + cvB = cvCreateImage(cvSize(image.GetWidth(), image.GetHeight()), 8, 1); + + cvSplit((IplImage*)image.GetIplImage(), cvR, cvG, cvB, NULL); + cvEqualizeHist(cvR, cvR); + cvEqualizeHist(cvG, cvG); + cvEqualizeHist(cvB, cvB); + cvMerge(cvR, cvG, cvB, NULL, cvDestImg); + + image.SetIplImage((void*)cvDestImg); + cvReleaseImage(&cvR); + cvReleaseImage(&cvG); + cvReleaseImage(&cvB); + cvReleaseImage(&cvDestImg); + break; + + default: + break; } } void MEHistogramTransform::SetStretchProcessingMode(ProcessingType new_channel_mode, - MEHistogram::StretchType new_stretch_mode) + MEHistogram::StretchType new_stretch_mode) { DiscreteStretchingDone = false; - switch(new_channel_mode) + switch (new_channel_mode) { - case p_SeparateChannels: - ChannelMode = new_channel_mode; - break; + case p_SeparateChannels: + ChannelMode = new_channel_mode; + break; - case p_Average: - ChannelMode = new_channel_mode; - break; + case p_Average: + ChannelMode = new_channel_mode; + break; - default: - break; + default: + break; } - switch(new_stretch_mode) + switch (new_stretch_mode) { - case MEHistogram::s_OwnMode: - StretchMode = new_stretch_mode; - break; + case MEHistogram::s_OwnMode: + StretchMode = new_stretch_mode; + break; - case MEHistogram::s_GimpMode: - StretchMode = new_stretch_mode; - break; + case MEHistogram::s_GimpMode: + StretchMode = new_stretch_mode; + break; - default: - break; + default: + break; } } diff --git a/package_bgs/ck/MEHistogram.hpp b/package_bgs/LBP_MRF/MEHistogram.hpp similarity index 93% rename from package_bgs/ck/MEHistogram.hpp rename to package_bgs/LBP_MRF/MEHistogram.hpp index 5b2b47f00d44716df0b1307a3631992e8c7342b0..0b2fb0dbd833f78fc7140e284fcb1ebd90925af5 100644 --- a/package_bgs/ck/MEHistogram.hpp +++ b/package_bgs/LBP_MRF/MEHistogram.hpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -18,14 +34,12 @@ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. * */ +#pragma once -#ifndef MEHistogram_hpp -#define MEHistogram_hpp - -/** - * @addtogroup mindeye - * @{ - */ + /** + * @addtogroup mindeye + * @{ + */ class MEImage; @@ -344,5 +358,3 @@ private: }; /** @} */ - -#endif diff --git a/package_bgs/ck/MEImage.cpp b/package_bgs/LBP_MRF/MEImage.cpp similarity index 50% rename from package_bgs/ck/MEImage.cpp rename to package_bgs/LBP_MRF/MEImage.cpp index 737383447133ee6148d6f384cd7b5ff31ed0cee3..b01d494e1091985dc04d312aa99712d440fea80e 100644 --- a/package_bgs/ck/MEImage.cpp +++ b/package_bgs/LBP_MRF/MEImage.cpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -30,17 +46,17 @@ cvReleaseImage((IplImage**)&image_ptr); \ image_ptr = NULL; -// RGB to YUV transform + // 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 }}; +{ { 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 }}; +{ { 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) { @@ -74,15 +90,15 @@ 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.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); LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels; } @@ -103,17 +119,17 @@ 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) + 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); + "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); LayerNumber = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels; } if (LayerNumber <= 0) @@ -124,7 +140,7 @@ void MEImage::SetLayer(MEImage& layer, int layer_number) if (layer.GetLayers() != 1) { printf("The layer image has not one color channel (1 != %d)\n", - layer.GetLayers()); + layer.GetLayers()); return; } cvSetImageCOI(ME_CAST_TO_IPLIMAGE(cvImg), LayerNumber); @@ -223,7 +239,7 @@ void MEImage::SetData(unsigned char* image_data, int width, int height, int chan { _Init(width, height, channels); - for (int y = height-1; y >= 0; --y) + for (int y = height - 1; y >= 0; --y) { int Start = GetRowWidth()*y; int Start2 = width*channels*y; @@ -235,7 +251,7 @@ void MEImage::SetData(unsigned char* image_data, int width, int height, int chan 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; + return ME_CAST_TO_IPLIMAGE(cvImg) ? (float)ME_CAST_TO_IPLIMAGE(cvImg)->height / (float)ME_CAST_TO_IPLIMAGE(cvImg)->width : 0.0; } @@ -289,7 +305,7 @@ void MEImage::ResizeScaleY(int new_height) printf("Invalid new height: %d < 1\n", new_height); return; } - Resize((int)((float)new_height*1/GetRatio()), new_height); + Resize((int)((float)new_height * 1 / GetRatio()), new_height); } @@ -322,19 +338,19 @@ void MEImage::Crop(int x1, int y1, int x2, int y2) NewY2 = (NewY2 < 0) ? 0 : NewY2; NewY2 = (NewY2 > ME_CAST_TO_IPLIMAGE(cvImg)->height) ? ME_CAST_TO_IPLIMAGE(cvImg)->height : NewY2; - if ((NewX2-NewX1) <= 0) + if ((NewX2 - NewX1) <= 0) { - printf("Invalid new width: %d <= 0\n", NewX2-NewX1); + printf("Invalid new width: %d <= 0\n", NewX2 - NewX1); return; } - if ((NewY2-NewY1) <= 0) + if ((NewY2 - NewY1) <= 0) { - printf("Invalid new height: %d <= 0\n", NewY2-NewY1); + 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); + 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)); + 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; @@ -367,13 +383,13 @@ void MEImage::CopyImageInside(int x, int y, MEImage& source_image) 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 (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()) + PasteLengthY != source_image.GetHeight()) { source_image.Resize(PasteLengthX, PasteLengthY); } @@ -386,8 +402,8 @@ void MEImage::CopyImageInside(int x, int y, MEImage& source_image) 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); + 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); @@ -398,8 +414,8 @@ void MEImage::Erode(int iterations) 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); + 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); @@ -416,22 +432,22 @@ void MEImage::Smooth() 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); + 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; + 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; @@ -446,7 +462,7 @@ void MEImage::Canny() } IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels); + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels); cvCanny(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 800, 1100, 5); ME_RELEASE_IPLIMAGE(cvImg); cvImg = TempImg; @@ -460,8 +476,8 @@ void MEImage::Laplace() ConvertToGrayscale(g_OpenCV); } IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, - ME_CAST_TO_IPLIMAGE(cvImg)->height), - IPL_DEPTH_16S, 1); + 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); @@ -482,7 +498,7 @@ void MEImage::Quantize(int levels) } 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) + 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); } @@ -503,7 +519,7 @@ void MEImage::Threshold(int threshold_limit) } 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) + for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i) { if (ImageData[i] < threshold_limit) { @@ -520,9 +536,9 @@ void MEImage::AdaptiveThreshold() 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); + ME_CAST_TO_IPLIMAGE(cvImg)->nChannels); cvAdaptiveThreshold(ME_CAST_TO_IPLIMAGE(cvImg), TempImg, 25, - CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, -7); + CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, -7); ME_RELEASE_IPLIMAGE(cvImg); cvImg = TempImg; } @@ -531,7 +547,7 @@ void MEImage::AdaptiveThreshold() 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) + mask_image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height) { printf("Image properties are different\n"); return; @@ -543,7 +559,7 @@ void MEImage::ThresholdByMask(MEImage& mask_image) 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) + for (int i = ME_CAST_TO_IPLIMAGE(cvImg)->widthStep*ME_CAST_TO_IPLIMAGE(cvImg)->height - 1; i >= 0; --i) { if (MaskImageData[i] == 0) { @@ -567,123 +583,123 @@ void MEImage::ColorSpace(ColorSpaceConvertType mode) } 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) + 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) { - 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; + 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); } - break; + RowStart += WidthStep; + } + break; - default: - break; + default: + break; } } @@ -701,27 +717,27 @@ void MEImage::ConvertToGrayscale(GrayscaleType grayscale_mode) 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; + 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; + 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; + 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; + default: + break; } } @@ -760,60 +776,60 @@ void MEImage::LBP(LBPType mode) 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; + 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_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; + 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; + default: + break; } ME_RELEASE_IPLIMAGE(cvImg); cvImg = TempImg; @@ -824,12 +840,13 @@ 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) + 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 { + } + else { ImageData[i] = 0; } } @@ -839,8 +856,8 @@ void MEImage::Binarize(int threshold) 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) + source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height || + source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels) { printf("Image properties are different.\n"); return; @@ -852,42 +869,42 @@ void MEImage::Subtract(MEImage& source, SubtractModeType mode) switch (mode) { - case sub_Normal: - ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData; - DstData = source.GetImageData(); - RowStart = 0; + 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 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) { - 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; + ImageData[RowStart + x] = + ImageData[RowStart + x] - DstData[RowStart + x] < 0 ? 0 : + ImageData[RowStart + x] - DstData[RowStart + x]; } - break; + RowStart += WidthStep; + } + break; - case sub_Absolut: - ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData; - DstData = source.GetImageData(); - RowStart = 0; + 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 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) { - 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; + ImageData[RowStart + x] = ImageData[RowStart + x] - + DstData[RowStart + x] < 0 ? -ImageData[RowStart + x] + + DstData[RowStart + x] : ImageData[RowStart + x] - DstData[RowStart + x]; } - break; + RowStart += WidthStep; + } + break; - default: - break; + default: + break; } } @@ -895,8 +912,8 @@ void MEImage::Subtract(MEImage& source, SubtractModeType mode) 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) + source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height || + source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels) { printf("Image properties are different.\n"); return; @@ -910,57 +927,59 @@ void MEImage::Multiple(MEImage& source, MultiplicationType mode) switch (mode) { - case m_Normal: - Result = 0; - ImageData = (unsigned char*)ME_CAST_TO_IPLIMAGE(cvImg)->imageData; - DstData = source.GetImageData(); + 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) + 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)) { - if ((ImageData[i] >= 128) && (DstData[i] >= 128)) - { - Result = (float)ImageData[i]/128*(float)DstData[i]/128; + Result = (float)ImageData[i] / 128 * (float)DstData[i] / 128; - if (Result >= 1) - { - ImageData[i] = 255; - } else { - ImageData[i] = 0; - } - } else { + if (Result >= 1) + { + ImageData[i] = 255; + } + 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)) + 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) { - ImageData3[y*ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels+ - x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels+l] = 255; + 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; + ME_RELEASE_IPLIMAGE(cvImg); + cvImg = TempImg; + break; - default: - break; + default: + break; } } @@ -968,8 +987,8 @@ void MEImage::Multiple(MEImage& source, MultiplicationType mode) 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) + source.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height || + source.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels) { printf("Image properties are different.\n"); return; @@ -979,25 +998,25 @@ void MEImage::Addition(MEImage& source, AdditionType mode) 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_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) + 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]) { - if (DstData[i] > ImageData[i]) - { - ImageData[i] = DstData[i]; - } + ImageData[i] = DstData[i]; } - break; + } + break; - default: - break; + default: + break; } } @@ -1005,42 +1024,44 @@ void MEImage::Addition(MEImage& source, AdditionType mode) 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); + 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) + 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) { - 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)) + xy = y*ywidth + x*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels; + + for (int l = ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; l >= 0; --l) { - 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) + 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)) { - DstData[xy+l] = 255; - } else { - DstData[xy+l] = 0; + 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; } - } else { - DstData[xy+l] = 0; } } - } ME_RELEASE_IPLIMAGE(cvImg); cvImg = TempImg; } @@ -1049,8 +1070,8 @@ void MEImage::EliminateSinglePixels() float MEImage::DifferenceAreas(MEImage& reference, int difference) const { if (reference.GetWidth() != GetWidth() || - reference.GetHeight() != GetHeight() || - reference.GetLayers() != GetLayers()) + reference.GetHeight() != GetHeight() || + reference.GetLayers() != GetLayers()) { printf("Image dimensions or channels are different\n"); return -1.0; @@ -1062,16 +1083,16 @@ float MEImage::DifferenceAreas(MEImage& reference, int difference) const 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 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) + 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) + 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; + PixelDiff = (float)Pixels / (ME_CAST_TO_IPLIMAGE(cvImg)->height*ME_CAST_TO_IPLIMAGE(cvImg)->widthStep) * 100; return PixelDiff; } @@ -1079,8 +1100,8 @@ float MEImage::DifferenceAreas(MEImage& reference, int difference) const int MEImage::AverageDifference(MEImage& reference) const { if (reference.GetWidth() != GetWidth() || - reference.GetHeight() != GetHeight() || - reference.GetLayers() != GetLayers()) + reference.GetHeight() != GetHeight() || + reference.GetLayers() != GetLayers()) { printf("Image dimensions or channels are different\n"); return -1; @@ -1091,11 +1112,11 @@ int MEImage::AverageDifference(MEImage& reference) const 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 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) + 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]); + Difference += abs(OrigImgData[RowStart + x] - RefImgData[RowStart + x]); } RowStart += WidthStep; } @@ -1107,8 +1128,8 @@ int MEImage::AverageDifference(MEImage& reference) const 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) + image.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height || + image.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels) { printf("Image properties are different\n"); return; @@ -1118,12 +1139,12 @@ void MEImage::Minimum(MEImage& image) 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 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) + 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]; + ImageData[RowStart + x] = ImageData[RowStart + x] > SecData[RowStart + x] ? + SecData[RowStart + x] : ImageData[RowStart + x]; } RowStart += WidthStep; } @@ -1137,11 +1158,11 @@ float MEImage::AverageBrightnessLevel() const int RowStart = 0; int BrightnessLevel = 0; - for (int y = ME_CAST_TO_IPLIMAGE(cvImg)->height-1; y >= 0; --y) + 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) + for (int x = ME_CAST_TO_IPLIMAGE(cvImg)->width*ME_CAST_TO_IPLIMAGE(cvImg)->nChannels - 1; x >= 0; --x) { - BrightnessLevel += (int)ImageData[RowStart+x]; + BrightnessLevel += (int)ImageData[RowStart + x]; } RowStart += WidthStep; } @@ -1160,8 +1181,8 @@ 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) + reference.GetHeight() != ME_CAST_TO_IPLIMAGE(cvImg)->height || + reference.GetLayers() != ME_CAST_TO_IPLIMAGE(cvImg)->nChannels) { printf("Image properties are different\n"); return false; @@ -1171,11 +1192,11 @@ bool MEImage::Equal(const MEImage& reference, int maxabsdiff) const 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 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) + 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) + if (abs(ImageData[RowStart + x] - RefData[RowStart + x]) >= maxabsdiff) { Ret = false; return Ret; @@ -1193,16 +1214,16 @@ unsigned char MEImage::GrayscalePixel(int x, int y) const 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; + 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; + 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 + (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); @@ -1210,7 +1231,7 @@ unsigned char MEImage::GrayscalePixel(int x, int y) const int MEImage::NeighbourhoodCounter(int startx, int starty, - NeighbourhoodType neighbourhood) const + NeighbourhoodType neighbourhood) const { int IterX = 0; int IterY = 0; @@ -1219,60 +1240,60 @@ int MEImage::NeighbourhoodCounter(int startx, int starty, // Determine the iteration numbers switch (neighbourhood) { - case n_2x2: - IterX = 2; - IterY = 2; - break; + case n_2x2: + IterX = 2; + IterY = 2; + break; - case n_3x3: - IterX = 3; - IterY = 3; - break; + case n_3x3: + IterX = 3; + IterY = 3; + break; - case n_3x2: - IterX = 2; - IterY = 3; - break; + case n_3x2: + IterX = 2; + IterY = 3; + break; - case n_5x5: - IterX = 5; - IterY = 5; - break; + case n_5x5: + IterX = 5; + IterY = 5; + break; - case n_7x7: - IterX = 7; - IterY = 7; - break; + case n_7x7: + IterX = 7; + IterY = 7; + break; - default: - IterX = 3; - IterY = 3; - break; + default: + IterX = 3; + IterY = 3; + break; } - int NewStartX = startx ; + 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; + 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; + 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) + for (int x = NewStartX; x < NewStartX + IterX; x++) + for (int y = NewStartY; y < NewStartY + IterY; y++) { - Counter++; + 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; } @@ -1288,24 +1309,24 @@ void MEImage::GradientVector(bool smooth, int x, int y, int mask_size, int& resu } if (smooth) { - SmoothAdvanced(s_Gaussian, mask_size*3-(mask_size*3-1) % 2); + 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); + 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; + 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; } @@ -1327,28 +1348,28 @@ void MEImage::GradientVisualize(int vector_x, int vector_y) } 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); + ME_CAST_TO_IPLIMAGE(cvImg)->width / (vector_x + 1) : + ME_CAST_TO_IPLIMAGE(cvImg)->height / (vector_y + 1); - SmoothAdvanced(s_Gaussian, masksize*2-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))); + { + 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); + GradientVector(false, x, y, (int)(0.707*masksize), Resultx, Resulty); - CvPoint Point1; - CvPoint Point2; + 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); - } + 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); + } } @@ -1400,16 +1421,16 @@ void MEImage::ComputeColorSpace(ColorSpaceConvertType mode) return; } IplImage* TempImg = cvCreateImage(cvSize(ME_CAST_TO_IPLIMAGE(cvImg)->width, ME_CAST_TO_IPLIMAGE(cvImg)->height), 8, - ME_CAST_TO_IPLIMAGE(cvImg)->nChannels); + 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]; - } + { + 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; @@ -1441,25 +1462,25 @@ void MEImage::ComputeColorSpace(ColorSpaceConvertType mode) 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) + 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 = (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; + 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); + 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/ck/MEImage.hpp b/package_bgs/LBP_MRF/MEImage.hpp similarity index 97% rename from package_bgs/ck/MEImage.hpp rename to package_bgs/LBP_MRF/MEImage.hpp index 41ada3ba71e086fd1b6ef0d1517f7ff34261f7bb..3a52a779a282ad02332df009a4021091645d22d7 100644 --- a/package_bgs/ck/MEImage.hpp +++ b/package_bgs/LBP_MRF/MEImage.hpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -18,19 +34,17 @@ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. * */ +#pragma once -#ifndef MEImage_H -#define MEImage_H - -/** - * @addtogroup mindeye - * @{ - */ + /** + * @addtogroup mindeye + * @{ + */ -/** - * MEImage - * @brief Basic image functions - */ + /** + * MEImage + * @brief Basic image functions + */ class MEImage { public: @@ -995,5 +1009,3 @@ private: }; /** @} */ - -#endif diff --git a/package_bgs/ck/MotionDetection.cpp b/package_bgs/LBP_MRF/MotionDetection.cpp similarity index 91% rename from package_bgs/ck/MotionDetection.cpp rename to package_bgs/LBP_MRF/MotionDetection.cpp index 5ac096afd18e51ec238fd9deae1ad60bad452ae2..e591faa92cacdf776db0198f309f76a89f955aa9 100644 --- a/package_bgs/ck/MotionDetection.cpp +++ b/package_bgs/LBP_MRF/MotionDetection.cpp @@ -1,4 +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/>. +*/ +/* * This file is part of the AiBO+ project * * Copyright (C) 2005-2013 Csaba Kertész (csaba.kertesz@gmail.com) @@ -52,15 +68,15 @@ struct MEPixelDataType }; 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) + 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; @@ -357,13 +373,13 @@ void MotionDetection::InitHUData(int imagewidth, int imageheight) 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]; + 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 @@ -399,8 +415,8 @@ void MotionDetection::InitHUOFData(int imagewidth, int imageheight) 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])); + HUOFPoints[0] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[0][0])); + HUOFPoints[1] = (CvPoint2D32f*)cvAlloc(HUOFPointsNumber * sizeof(HUOFPoints[1][0])); } } @@ -412,13 +428,13 @@ void MotionDetection::ReleaseHUData() 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]; + 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++) @@ -486,15 +502,15 @@ void MotionDetection::ClearHUData() 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; + 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; } @@ -563,13 +579,13 @@ void MotionDetection::DetectMotionsHU(MEImage& image) else if (Frames > 1) { - PreviousImage = CurrentImage; - CurrentImage = image; - // Optical flow correction of the camera movements - if (MDMode == md_DLBPHistograms) - { - OpticalFlowCorrection(); - } + PreviousImage = CurrentImage; + CurrentImage = image; + // Optical flow correction of the camera movements + if (MDMode == md_DLBPHistograms) + { + OpticalFlowCorrection(); + } } newimage.ConvertToGrayscale(MEImage::g_OpenCV); @@ -915,17 +931,17 @@ void MotionDetection::UpdateHUPixelData(MEPixelDataType* PixelData, const float 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]; + 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][0] = Weights[i - 1][0]; + Weights[i][1] = Weights[i - 1][1]; - Weights[i - 1][0] = tmp; - Weights[i - 1][1] = tmp2; - } + Weights[i - 1][0] = tmp; + Weights[i - 1][1] = tmp2; + } } float Sum = 0; @@ -1056,7 +1072,7 @@ void MotionDetection::OpticalFlowCorrection() 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])))) + abs(Distances[i - 1][0]) + abs(Distances[i - 1][1])))) { int tmp = Distances[i][0]; int tmp2 = Distances[i][1]; @@ -1331,10 +1347,10 @@ void MotionDetection::GetMotionsMaskHU(MEImage& mask_image) 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) + 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; } } diff --git a/package_bgs/ck/MotionDetection.hpp b/package_bgs/LBP_MRF/MotionDetection.hpp similarity index 93% rename from package_bgs/ck/MotionDetection.hpp rename to package_bgs/LBP_MRF/MotionDetection.hpp index 6e11521d493b40ef78ce069d0ad854ac627a4748..e58c93c107f448d62b7cf2dd0c57c7e8eb8c0b78 100644 --- a/package_bgs/ck/MotionDetection.hpp +++ b/package_bgs/LBP_MRF/MotionDetection.hpp @@ -1,3 +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/>. +*/ /* * This file is part of the AiBO+ project * @@ -18,14 +34,12 @@ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. * */ +#pragma once -#ifndef MotionDetection_hpp -#define MotionDetection_hpp - -/** - * @addtogroup mindeye - * @{ - */ + /** + * @addtogroup mindeye + * @{ + */ #include "MEDefs.hpp" #include "MEImage.hpp" @@ -181,7 +195,7 @@ public: */ void CalculateResults(MEImage& referenceimage, int& tnegatives, int& tpositives, - int& ttnegatives, int& ttpositives); + int& ttnegatives, int& ttpositives); private: @@ -397,5 +411,3 @@ private: }; /** @} */ - -#endif diff --git a/package_bgs/ck/block.h b/package_bgs/LBP_MRF/block.h similarity index 51% rename from package_bgs/ck/block.h rename to package_bgs/LBP_MRF/block.h index 98b1201fc0c0f506c924c688b51e43923ea649fe..bd1ab67ee703ea826d3debddd5eb4978bcf4e185 100644 --- a/package_bgs/ck/block.h +++ b/package_bgs/LBP_MRF/block.h @@ -1,3 +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/>. +*/ /* block.h */ /* Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca). @@ -16,8 +32,6 @@ 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. @@ -105,9 +119,7 @@ simultaneously at earlier moments. All memory is deallocated only when the destructor is called. */ - -#ifndef __BLOCK_H__ -#define __BLOCK_H__ +#pragma once #include <stdlib.h> #include <stdio.h> @@ -118,170 +130,168 @@ namespace ck { - template <class Type> class Block - { - public: - /* Constructor. Arguments are the block size and +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; } + 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; } } + /* Destructor. Deallocates all items added so far */ + ~Block() { while (first) { block *next = first->next; delete first; first = next; } } - /* Allocates 'num' consecutive items; returns pointer + /* 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; + Type *New(int num = 1) + { + Type *t; - if (!last || last->current + num > last->last) + if (!last || last->current + num > last->last) + { + if (last && last->next) last = last->next; + else { - 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; - } + 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++; - } + 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) + /* 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() + Type *ScanNext() + { + if (scan_current_data >= scan_current_block->current) { - 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++; + 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() + /* Marks all elements as empty */ + void Reset() + { + block *b; + if (!first) return; + for (b = first;; b = b->next) { - block *b; - if (!first) return; - for (b = first;; b = b->next) - { - b->current = &(b->data[0]); - if (b == last) break; - } - last = first; + b->current = &(b->data[0]); + if (b == last) break; } + last = first; + } - /***********************************************************************/ + /***********************************************************************/ - private: +private: - typedef struct block_st - { - Type *current, *last; - struct block_st *next; - Type data[1]; - } block; + typedef struct block_st + { + Type *current, *last; + struct block_st *next; + Type data[1]; + } block; - int block_size; - block *first; - block *last; + int block_size; + block *first; + block *last; - block *scan_current_block; - Type *scan_current_data; + block *scan_current_block; + Type *scan_current_data; - void(*error_function)(char *); - }; + void(*error_function)(char *); +}; - /***********************************************************************/ - /***********************************************************************/ - /***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ - template <class Type> class DBlock - { - public: - /* Constructor. Arguments are the block size and +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; + DBlock(int size, void(*err_function)(char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; } - 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; - } + /* Destructor. Deallocates all items added so far */ + ~DBlock() { while (first) { block *next = first->next; delete first; first = next; } } - item = first_free; - first_free = item->next_free; - return (Type *)item; - } + /* Allocates one item */ + Type *New() + { + block_item *item; - /* Deletes an item allocated previously */ - void Delete(Type *t) + if (!first_free) { - ((block_item *)t)->next_free = first_free; - first_free = (block_item *)t; + 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; + } - private: + /* Deletes an item allocated previously */ + void Delete(Type *t) + { + ((block_item *)t)->next_free = first_free; + first_free = (block_item *)t; + } - 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; +private: - int block_size; - block *first; - block_item *first_free; + typedef union block_item_st + { + Type t; + block_item_st *next_free; + } block_item; - void(*error_function)(char *); - }; -} + typedef struct block_st + { + struct block_st *next; + block_item data[1]; + } block; + + int block_size; + block *first; + block_item *first_free; -#endif + void(*error_function)(char *); +}; +} diff --git a/package_bgs/ck/graph.cpp b/package_bgs/LBP_MRF/graph.cpp similarity index 78% rename from package_bgs/ck/graph.cpp rename to package_bgs/LBP_MRF/graph.cpp index daed395f15c9cfa57d902177bee676ff99e76d4d..9301250f051381b1489a6365027da61548a5e5e9 100644 --- a/package_bgs/ck/graph.cpp +++ b/package_bgs/LBP_MRF/graph.cpp @@ -1,3 +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/>. +*/ /* graph.cpp */ /* Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca). @@ -80,4 +96,4 @@ namespace ck flow += (cap_source < cap_sink) ? cap_source : cap_sink; ((node*)i)->tr_cap = cap_source - cap_sink; } -} \ No newline at end of file +} diff --git a/package_bgs/ck/graph.h b/package_bgs/LBP_MRF/graph.h similarity index 60% rename from package_bgs/ck/graph.h rename to package_bgs/LBP_MRF/graph.h index b6799e40eb07fa24b40288af89daa194c37c26f0..e7b83c7e2c956cbc97777160086c502a6cf918dc 100644 --- a/package_bgs/ck/graph.h +++ b/package_bgs/LBP_MRF/graph.h @@ -1,3 +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/>. +*/ /* graph.h */ /* This software library implements the maxflow algorithm @@ -16,41 +32,36 @@ 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. - */ - -#ifndef __GRAPH_H__ -#define __GRAPH_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 + */ + /* + 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 - */ + /* + 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 @@ -67,7 +78,7 @@ namespace ck } termtype; /* terminals */ /* Type of edge weights. - Can be changed to char, int, float, double, ... */ + Can be changed to char, int, float, double, ... */ typedef short captype; /* Type of total flow */ typedef int flowtype; @@ -77,9 +88,9 @@ namespace ck /* 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. */ + 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 */ @@ -89,21 +100,21 @@ namespace ck node_id add_node(); /* Adds a bidirectional edge between 'from' and 'to' - with the weights 'cap' and 'rev_cap' */ + 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 */ + 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 */ + 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) */ + segment the node 'i' belongs (Graph::SOURCE or Graph::SINK) */ termtype what_segment(node_id i); /* Computes the maxflow. Can be called only once. */ @@ -125,13 +136,13 @@ namespace ck 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) */ + (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 */ + otherwise -tr_cap is residual capacity of the arc node->SINK */ } node; /* arc structure */ @@ -156,8 +167,8 @@ namespace ck 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) */ + with a corresponding error message + (or exit(1) is called if it's NULL) */ flowtype flow; /* total flow */ @@ -179,5 +190,3 @@ namespace ck void process_sink_orphan(node *i); }; } - -#endif diff --git a/package_bgs/ck/maxflow.cpp b/package_bgs/LBP_MRF/maxflow.cpp similarity index 67% rename from package_bgs/ck/maxflow.cpp rename to package_bgs/LBP_MRF/maxflow.cpp index 53d37057057423950921bb6f8184cde88e5b3603..6ddec507db47d3dbe0e7fdf1c69d63e3277d133f 100644 --- a/package_bgs/ck/maxflow.cpp +++ b/package_bgs/LBP_MRF/maxflow.cpp @@ -1,3 +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/>. +*/ /* maxflow.cpp */ /* Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca). @@ -16,33 +32,31 @@ 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 - */ + /* + 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). - */ + /* + 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) @@ -58,10 +72,10 @@ namespace ck } /* - Returns the next active node. - If it is connected to the sink, it stays in the list, - otherwise it is removed from the list - */ + 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; @@ -232,45 +246,45 @@ namespace ck 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 */ + j = a0->head; + if (!j->is_sink && (a = j->parent)) { - if (d < d_min) + /* checking the origin of j */ + d = 0; + while (1) { - a0_min = a0; - d_min = d; + 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; } - /* set marks along the path */ - for (j = a0->head; j->TS != TIME; j = j->parent->head) + if (d < INFINITE_D) /* j originates from the source - done */ { - j->TS = TIME; - j->DIST = d--; + 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)) { @@ -316,45 +330,45 @@ namespace ck 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 */ + j = a0->head; + if (j->is_sink && (a = j->parent)) { - if (d < d_min) + /* checking the origin of j */ + d = 0; + while (1) { - a0_min = a0; - d_min = d; + 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; } - /* set marks along the path */ - for (j = a0->head; j->TS != TIME; j = j->parent->head) + if (d < INFINITE_D) /* j originates from the sink - done */ { - j->TS = TIME; - j->DIST = d--; + 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)) { @@ -419,24 +433,24 @@ namespace ck 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; - } + 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 @@ -445,24 +459,24 @@ namespace ck 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; - } + 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; + } } } @@ -513,4 +527,4 @@ namespace ck return SINK; } -} \ No newline at end of file +} diff --git a/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp b/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2865a30709751b16a06e8a4be0d6354d93dd0eb0 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLBSP.cpp @@ -0,0 +1,85 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..ef0576c9149a4be20ea8cfb2b24f9fd48c65e4ba --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLBSP.h @@ -0,0 +1,101 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..4e5d4a6fad9bcc75476b3d598e05d44fca07cdd0 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLBSP_.cpp @@ -0,0 +1,79 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..861f78a7bd15a9e84a23e4f69f3fc1d9b88c6692 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLBSP_.h @@ -0,0 +1,107 @@ +/* +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.cpp b/package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9648c5c1bf8ebc2dfef307ebc5aafc7d11bd42a1 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLOBSTER.cpp @@ -0,0 +1,342 @@ +/* +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 "BackgroundSubtractorLOBSTER.h" +#include "DistanceUtils.h" +#include "RandUtils.h" +#include <iostream> +#include <opencv2/imgproc/imgproc.hpp> +#include <opencv2/highgui/highgui.hpp> +#include <iomanip> + +BackgroundSubtractorLOBSTER::BackgroundSubtractorLOBSTER(float fRelLBSPThreshold + , size_t nLBSPThresholdOffset + , size_t nDescDistThreshold + , size_t nColorDistThreshold + , size_t nBGSamples + , size_t nRequiredBGSamples) + : BackgroundSubtractorLBSP(fRelLBSPThreshold, nLBSPThresholdOffset) + , m_nColorDistThreshold(nColorDistThreshold) + , m_nDescDistThreshold(nDescDistThreshold) + , m_nBGSamples(nBGSamples) + , m_nRequiredBGSamples(nRequiredBGSamples) { + CV_Assert(m_nRequiredBGSamples <= m_nBGSamples); + m_bAutoModelResetEnabled = false; // @@@@@@ not supported here for now +} + +BackgroundSubtractorLOBSTER::~BackgroundSubtractorLOBSTER() { + if (m_aPxIdxLUT) + delete[] m_aPxIdxLUT; + if (m_aPxInfoLUT) + delete[] m_aPxInfoLUT; +} + +void BackgroundSubtractorLOBSTER::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) { + CV_Assert(!oInitImg.empty() && oInitImg.cols > 0 && oInitImg.rows > 0); + CV_Assert(oInitImg.isContinuous()); + CV_Assert(oInitImg.type() == CV_8UC1 || oInitImg.type() == CV_8UC3); + 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 << "\tBackgroundSubtractorLOBSTER : 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(); + } + LBSP::validateROI(oNewBGROI); + const size_t nROIPxCount = (size_t)cv::countNonZero(oNewBGROI); + CV_Assert(nROIPxCount > 0); + m_oROI = oNewBGROI; + m_oImgSize = oInitImg.size(); + m_nImgType = oInitImg.type(); + m_nImgChannels = oInitImg.channels(); + m_nTotPxCount = m_oImgSize.area(); + m_nTotRelevantPxCount = nROIPxCount; + m_nFrameIndex = 0; + m_nFramesSinceLastReset = 0; + m_nModelResetCooldown = 0; + m_oLastFGMask.create(m_oImgSize, CV_8UC1); + m_oLastFGMask = cv::Scalar_<uchar>(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_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>((t*m_fRelLBSPThreshold + m_nLBSPThresholdOffset) / 2); + 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>(t*m_fRelLBSPThreshold + m_nLBSPThresholdOffset); + 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 BackgroundSubtractorLOBSTER::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 BackgroundSubtractorLOBSTER::apply(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate) { + CV_Assert(m_bInitialized); + CV_Assert(learningRate > 0); + 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(); + oCurrFGMask = cv::Scalar_<uchar>(0); + const size_t nLearningRate = (size_t)ceil(learningRate); + 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 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 nGoodSamplesCount = 0, nModelIdx = 0; + ushort nCurrInputDesc; + while (nGoodSamplesCount < m_nRequiredBGSamples && nModelIdx < m_nBGSamples) { + const uchar nBGColor = m_voBGColorSamples[nModelIdx].data[nPxIter]; + { + const size_t nColorDist = L1dist(nCurrColor, nBGColor); + if (nColorDist > m_nColorDistThreshold / 2) + goto failedcheck1ch; + LBSP::computeGrayscaleDescriptor(oInputImg, nBGColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nBGColor], nCurrInputDesc); + const size_t nDescDist = hdist(nCurrInputDesc, *((ushort*)(m_voBGDescSamples[nModelIdx].data + nDescIter))); + if (nDescDist > m_nDescDistThreshold) + goto failedcheck1ch; + nGoodSamplesCount++; + } + failedcheck1ch: + nModelIdx++; + } + if (nGoodSamplesCount < m_nRequiredBGSamples) + oCurrFGMask.data[nPxIter] = UCHAR_MAX; + else { + if ((rand() % nLearningRate) == 0) { + const size_t nSampleModelIdx = rand() % m_nBGSamples; + ushort& nRandInputDesc = *((ushort*)(m_voBGDescSamples[nSampleModelIdx].data + nDescIter)); + LBSP::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nRandInputDesc); + m_voBGColorSamples[nSampleModelIdx].data[nPxIter] = nCurrColor; + } + if ((rand() % nLearningRate) == 0) { + int nSampleImgCoord_Y, nSampleImgCoord_X; + getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize); + const size_t nSampleModelIdx = rand() % m_nBGSamples; + ushort& nRandInputDesc = m_voBGDescSamples[nSampleModelIdx].at<ushort>(nSampleImgCoord_Y, nSampleImgCoord_X); + LBSP::computeGrayscaleDescriptor(oInputImg, nCurrColor, nCurrImgCoord_X, nCurrImgCoord_Y, m_anLBSPThreshold_8bitLUT[nCurrColor], nRandInputDesc); + m_voBGColorSamples[nSampleModelIdx].at<uchar>(nSampleImgCoord_Y, nSampleImgCoord_X) = nCurrColor; + } + } + } + } + else { //m_nImgChannels==3 + const size_t nCurrDescDistThreshold = m_nDescDistThreshold * 3; + const size_t nCurrColorDistThreshold = m_nColorDistThreshold * 3; + const size_t nCurrSCDescDistThreshold = nCurrDescDistThreshold / 2; + const size_t nCurrSCColorDistThreshold = nCurrColorDistThreshold / 2; + const size_t desc_row_step = m_voBGDescSamples[0].step.p[0]; + const size_t img_row_step = m_voBGColorSamples[0].step.p[0]; + 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 uchar* const anCurrColor = oInputImg.data + nPxIterRGB; + size_t nGoodSamplesCount = 0, nModelIdx = 0; + ushort anCurrInputDesc[3]; + while (nGoodSamplesCount < m_nRequiredBGSamples && nModelIdx < m_nBGSamples) { + const ushort* const anBGDesc = (ushort*)(m_voBGDescSamples[nModelIdx].data + nDescIterRGB); + const uchar* const anBGColor = m_voBGColorSamples[nModelIdx].data + nPxIterRGB; + size_t nTotColorDist = 0; + size_t nTotDescDist = 0; + for (size_t c = 0; c < 3; ++c) { + const size_t nColorDist = L1dist(anCurrColor[c], anBGColor[c]); + if (nColorDist > nCurrSCColorDistThreshold) + goto failedcheck3ch; + LBSP::computeSingleRGBDescriptor(oInputImg, anBGColor[c], nCurrImgCoord_X, nCurrImgCoord_Y, c, m_anLBSPThreshold_8bitLUT[anBGColor[c]], anCurrInputDesc[c]); + const size_t nDescDist = hdist(anCurrInputDesc[c], anBGDesc[c]); + if (nDescDist > nCurrSCDescDistThreshold) + goto failedcheck3ch; + nTotColorDist += nColorDist; + nTotDescDist += nDescDist; + } + if (nTotDescDist <= nCurrDescDistThreshold && nTotColorDist <= nCurrColorDistThreshold) + nGoodSamplesCount++; + failedcheck3ch: + nModelIdx++; + } + if (nGoodSamplesCount < m_nRequiredBGSamples) + oCurrFGMask.data[nPxIter] = UCHAR_MAX; + else { + if ((rand() % nLearningRate) == 0) { + const size_t nSampleModelIdx = rand() % m_nBGSamples; + ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data + nDescIterRGB)); + 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, anRandInputDesc); + for (size_t c = 0; c < 3; ++c) + *(m_voBGColorSamples[nSampleModelIdx].data + nPxIterRGB + c) = anCurrColor[c]; + } + if ((rand() % nLearningRate) == 0) { + int nSampleImgCoord_Y, nSampleImgCoord_X; + getRandNeighborPosition_3x3(nSampleImgCoord_X, nSampleImgCoord_Y, nCurrImgCoord_X, nCurrImgCoord_Y, LBSP::PATCH_SIZE / 2, m_oImgSize); + const size_t nSampleModelIdx = rand() % m_nBGSamples; + ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data + desc_row_step*nSampleImgCoord_Y + 6 * nSampleImgCoord_X)); + 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, anRandInputDesc); + for (size_t c = 0; c < 3; ++c) + *(m_voBGColorSamples[nSampleModelIdx].data + img_row_step*nSampleImgCoord_Y + 3 * nSampleImgCoord_X + c) = anCurrColor[c]; + } + } + } + } + cv::medianBlur(oCurrFGMask, m_oLastFGMask, m_nDefaultMedianBlurKernelSize); + m_oLastFGMask.copyTo(oCurrFGMask); +} + +void BackgroundSubtractorLOBSTER::getBackgroundImage(cv::OutputArray backgroundImage) const { + CV_DbgAssert(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 idx_flt32 = idx_nimg * 4; + float* oAvgBgImgPtr = (float*)(oAvgBGImg.data + idx_flt32); + 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 BackgroundSubtractorLOBSTER::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 idx_flt32 = idx_ndesc * 2; + float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data + idx_flt32); + 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/BackgroundSubtractorLOBSTER.h b/package_bgs/LBSP/BackgroundSubtractorLOBSTER.h new file mode 100644 index 0000000000000000000000000000000000000000..d69fd1c3e8d1ff6d9f7a3f7ea807b92dcc94f7e4 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorLOBSTER.h @@ -0,0 +1,83 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..6c48df3b91115c25be8aff64e6d30c9f21865208 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorPAWCS.cpp @@ -0,0 +1,1349 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..cafa48c55a0993ca6ec76024e17ad57f8bfdca78 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorPAWCS.h @@ -0,0 +1,169 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..3dcc1b86e231fe83fded922cab432aed5fc53862 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.cpp @@ -0,0 +1,753 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..9950ea429270007c4e6ee6c45b2d472668b7d2b0 --- /dev/null +++ b/package_bgs/LBSP/BackgroundSubtractorSuBSENSE.h @@ -0,0 +1,129 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..9eabca4a79db6f5f83a2d54c9558370cde799115 --- /dev/null +++ b/package_bgs/LBSP/DistanceUtils.h @@ -0,0 +1,332 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..4ec17b973dfeaf4d4de076927831838399f4900c --- /dev/null +++ b/package_bgs/LBSP/LBSP.cpp @@ -0,0 +1,334 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..c908eaa068641ece3b1ec0f487e2f6b01fae5899 --- /dev/null +++ b/package_bgs/LBSP/LBSP.h @@ -0,0 +1,134 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..ff5c8e8abed8fd8e1a96a4ef1bfea3b91fe74119 --- /dev/null +++ b/package_bgs/LBSP/LBSP_.cpp @@ -0,0 +1,334 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..819174a948ea1556f898f7804cacff30ac25d1b2 --- /dev/null +++ b/package_bgs/LBSP/LBSP_.h @@ -0,0 +1,134 @@ +/* +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/pl/LBSP_16bits_dbcross_1ch.i b/package_bgs/LBSP/LBSP_16bits_dbcross_1ch.i similarity index 100% rename from package_bgs/pl/LBSP_16bits_dbcross_1ch.i rename to package_bgs/LBSP/LBSP_16bits_dbcross_1ch.i diff --git a/package_bgs/pl/LBSP_16bits_dbcross_3ch1t.i b/package_bgs/LBSP/LBSP_16bits_dbcross_3ch1t.i similarity index 100% rename from package_bgs/pl/LBSP_16bits_dbcross_3ch1t.i rename to package_bgs/LBSP/LBSP_16bits_dbcross_3ch1t.i diff --git a/package_bgs/pl/LBSP_16bits_dbcross_3ch3t.i b/package_bgs/LBSP/LBSP_16bits_dbcross_3ch3t.i similarity index 100% rename from package_bgs/pl/LBSP_16bits_dbcross_3ch3t.i rename to package_bgs/LBSP/LBSP_16bits_dbcross_3ch3t.i diff --git a/package_bgs/pl/LBSP_16bits_dbcross_s3ch.i b/package_bgs/LBSP/LBSP_16bits_dbcross_s3ch.i similarity index 100% rename from package_bgs/pl/LBSP_16bits_dbcross_s3ch.i rename to package_bgs/LBSP/LBSP_16bits_dbcross_s3ch.i diff --git a/package_bgs/LBSP/RandUtils.h b/package_bgs/LBSP/RandUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..f676ca08da83ee0478c762180664d1b9a9dc34e4 --- /dev/null +++ b/package_bgs/LBSP/RandUtils.h @@ -0,0 +1,112 @@ +/* +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/lb/LBSimpleGaussian.cpp b/package_bgs/LBSimpleGaussian.cpp similarity index 61% rename from package_bgs/lb/LBSimpleGaussian.cpp rename to package_bgs/LBSimpleGaussian.cpp index f0ce6fc69c6e572e1ebba8883af7706a117f91ad..9ce071c029e94969da5b07347bf4696a98dec84e 100644 --- a/package_bgs/lb/LBSimpleGaussian.cpp +++ b/package_bgs/LBSimpleGaussian.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "LBSimpleGaussian.h" -LBSimpleGaussian::LBSimpleGaussian() : firstTime(true), showOutput(true), sensitivity(66), noiseVariance(162), learningRate(18) +using namespace bgslibrary::algorithms; + +LBSimpleGaussian::LBSimpleGaussian() : + sensitivity(66), noiseVariance(162), learningRate(18) { std::cout << "LBSimpleGaussian()" << std::endl; + setup("./config/LBSimpleGaussian.xml"); } LBSimpleGaussian::~LBSimpleGaussian() @@ -29,55 +33,47 @@ LBSimpleGaussian::~LBSimpleGaussian() void LBSimpleGaussian::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - loadConfig(); - IplImage *frame = new IplImage(img_input); - - if(firstTime) - { - saveConfig(); + if (firstTime) + { int w = cvGetSize(frame).width; int h = cvGetSize(frame).height; - m_pBGModel = new BGModelGauss(w,h); + 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->setBGModelParameter(0, sensitivity); + m_pBGModel->setBGModelParameter(1, noiseVariance); + m_pBGModel->setBGModelParameter(2, learningRate); m_pBGModel->UpdateModel(frame); - img_foreground = cv::Mat(m_pBGModel->GetFG()); - img_background = cv::Mat(m_pBGModel->GetBG()); - - if(showOutput) + 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::finish(void) -//{ -// delete m_pBGModel; -//} - void LBSimpleGaussian::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBSimpleGaussian.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "sensitivity", sensitivity); cvWriteInt(fs, "noiseVariance", noiseVariance); @@ -89,12 +85,12 @@ void LBSimpleGaussian::saveConfig() void LBSimpleGaussian::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/LBSimpleGaussian.xml", 0, CV_STORAGE_READ); - - sensitivity = cvReadIntByName(fs, 0, "sensitivity", 66); - noiseVariance = cvReadIntByName(fs, 0, "noiseVariance", 162); - learningRate = cvReadIntByName(fs, 0, "learningRate", 18); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/lb/LBSimpleGaussian.h b/package_bgs/LBSimpleGaussian.h similarity index 57% rename from package_bgs/lb/LBSimpleGaussian.h rename to package_bgs/LBSimpleGaussian.h index bfefd3e12cf9bd03b9b14585d512f6b3d1c54adc..5c829234f86933736682ca4d41e9fa4f12bf550c 100644 --- a/package_bgs/lb/LBSimpleGaussian.h +++ b/package_bgs/LBSimpleGaussian.h @@ -16,39 +16,33 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "BGModelGauss.h" - -#include "../IBGS.h" +#include "IBGS.h" +#include "lb/BGModelGauss.h" using namespace lb_library; using namespace lb_library::SimpleGaussian; -class LBSimpleGaussian : public IBGS +namespace bgslibrary { -private: - bool firstTime; - bool showOutput; - - BGModel* m_pBGModel; - int sensitivity; - int noiseVariance; - int learningRate; - - cv::Mat img_foreground; - cv::Mat img_background; - -public: - LBSimpleGaussian(); - ~LBSimpleGaussian(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - //void finish(void); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file + 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 new file mode 100644 index 0000000000000000000000000000000000000000..dc48a63ba3a578e1ac0b8ebd9f123189827e2959 --- /dev/null +++ b/package_bgs/LOBSTER.cpp @@ -0,0 +1,98 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..41ba8828664215cf1b9201a1c9f64b748e43ff34 --- /dev/null +++ b/package_bgs/LOBSTER.h @@ -0,0 +1,49 @@ +/* +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/MixtureOfGaussianV1BGS.cpp b/package_bgs/MixtureOfGaussianV1.cpp similarity index 53% rename from package_bgs/MixtureOfGaussianV1BGS.cpp rename to package_bgs/MixtureOfGaussianV1.cpp index 51d41eb57348d76695a5c6c4392dc0e5e385a371..e56609a64c69539e2e6638db5fc159b055d8ac9f 100644 --- a/package_bgs/MixtureOfGaussianV1BGS.cpp +++ b/package_bgs/MixtureOfGaussianV1.cpp @@ -14,27 +14,27 @@ 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 "MixtureOfGaussianV1BGS.h" +#include "MixtureOfGaussianV1.h" -MixtureOfGaussianV1BGS::MixtureOfGaussianV1BGS() : firstTime(true), alpha(0.05), enableThreshold(true), threshold(15), showOutput(true) +#if CV_MAJOR_VERSION == 2 + +using namespace bgslibrary::algorithms; + +MixtureOfGaussianV1::MixtureOfGaussianV1() : + alpha(0.05), enableThreshold(true), threshold(15) { - std::cout << "MixtureOfGaussianV1BGS()" << std::endl; + std::cout << "MixtureOfGaussianV1()" << std::endl; + setup("./config/MixtureOfGaussianV1.xml"); } -MixtureOfGaussianV1BGS::~MixtureOfGaussianV1BGS() +MixtureOfGaussianV1::~MixtureOfGaussianV1() { - std::cout << "~MixtureOfGaussianV1BGS()" << std::endl; + std::cout << "~MixtureOfGaussianV1()" << std::endl; } -void MixtureOfGaussianV1BGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void MixtureOfGaussianV1::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); //------------------------------------------------------------------ // BackgroundSubtractorMOG @@ -43,26 +43,30 @@ void MixtureOfGaussianV1BGS::process(const cv::Mat &img_input, cv::Mat &img_outp // 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, + // 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); - cv::Mat img_background; mog.getBackgroundImage(img_background); - if(enableThreshold) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - if(showOutput) + 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) { - if (!img_foreground.empty()) - cv::imshow("GMM FG (KadewTraKuPong&Bowden)", img_foreground); - - if (!img_background.empty()) - cv::imshow("GMM BG (KadewTraKuPong&Bowden)", img_background); + 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); @@ -70,9 +74,9 @@ void MixtureOfGaussianV1BGS::process(const cv::Mat &img_input, cv::Mat &img_outp firstTime = false; } -void MixtureOfGaussianV1BGS::saveConfig() +void MixtureOfGaussianV1::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MixtureOfGaussianV1BGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "alpha", alpha); cvWriteInt(fs, "enableThreshold", enableThreshold); @@ -82,14 +86,15 @@ void MixtureOfGaussianV1BGS::saveConfig() cvReleaseFileStorage(&fs); } -void MixtureOfGaussianV1BGS::loadConfig() +void MixtureOfGaussianV1::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MixtureOfGaussianV1BGS.xml", 0, CV_STORAGE_READ); - - alpha = cvReadRealByName(fs, 0, "alpha", 0.05); - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/MixtureOfGaussianV1BGS.h b/package_bgs/MixtureOfGaussianV1.h similarity index 59% rename from package_bgs/MixtureOfGaussianV1BGS.h rename to package_bgs/MixtureOfGaussianV1.h index f735a1357e321de6ba5acbb0b9b76c4fb1534d1a..e18dbdbeae973b8d8e6c4b73504a5bea94050c5e 100644 --- a/package_bgs/MixtureOfGaussianV1BGS.h +++ b/package_bgs/MixtureOfGaussianV1.h @@ -16,32 +16,38 @@ 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" -class MixtureOfGaussianV1BGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::BackgroundSubtractorMOG mog; - cv::Mat img_foreground; - double alpha; - bool enableThreshold; - int threshold; - bool showOutput; - -public: - MixtureOfGaussianV1BGS(); - ~MixtureOfGaussianV1BGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/MixtureOfGaussianV2BGS.cpp b/package_bgs/MixtureOfGaussianV2.cpp similarity index 60% rename from package_bgs/MixtureOfGaussianV2BGS.cpp rename to package_bgs/MixtureOfGaussianV2.cpp index 5ce33a3ef1b36a5948c20288530be22332106f0c..085b1a9503f9297a9d553b4991ff29443aead97f 100644 --- a/package_bgs/MixtureOfGaussianV2BGS.cpp +++ b/package_bgs/MixtureOfGaussianV2.cpp @@ -14,27 +14,31 @@ 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 "MixtureOfGaussianV2BGS.h" +#include "MixtureOfGaussianV2.h" -MixtureOfGaussianV2BGS::MixtureOfGaussianV2BGS() : firstTime(true), alpha(0.05), enableThreshold(true), threshold(15), showOutput(true) +using namespace bgslibrary::algorithms; + +MixtureOfGaussianV2::MixtureOfGaussianV2() : + alpha(0.05), enableThreshold(true), threshold(15) { - std::cout << "MixtureOfGaussianV2BGS()" << std::endl; + std::cout << "MixtureOfGaussianV2()" << std::endl; + setup("./config/MixtureOfGaussianV2.xml"); } -MixtureOfGaussianV2BGS::~MixtureOfGaussianV2BGS() +MixtureOfGaussianV2::~MixtureOfGaussianV2() { - std::cout << "~MixtureOfGaussianV2BGS()" << std::endl; + std::cout << "~MixtureOfGaussianV2()" << std::endl; } -void MixtureOfGaussianV2BGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void MixtureOfGaussianV2::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); + init(img_input, img_output, img_bgmodel); - if(firstTime) - saveConfig(); + if (firstTime) { +#if CV_MAJOR_VERSION == 3 + mog = cv::createBackgroundSubtractorMOG2(); +#endif + } //------------------------------------------------------------------ // BackgroundSubtractorMOG2 @@ -43,29 +47,34 @@ void MixtureOfGaussianV2BGS::process(const cv::Mat &img_input, cv::Mat &img_outp // Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm. // // The class implements the Gaussian mixture model background subtraction described in: - // (1) Z.Zivkovic, Improved adaptive Gausian mixture model for background subtraction, International Conference Pattern Recognition, UK, August, 2004, + // (1) Z.Zivkovic, Improved adaptive Gausian mixture model for background subtraction, International Conference Pattern Recognition, UK, August, 2004, // The code is very fast and performs also shadow detection. Number of Gausssian components is adapted per pixel. // - // (2) Z.Zivkovic, F. van der Heijden, Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction, - // Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006. - // The algorithm similar to the standard Stauffer&Grimson algorithm with additional selection of the number of the Gaussian components based on: - // Z.Zivkovic, F.van der Heijden, Recursive unsupervised learning of finite mixture models, IEEE Trans. on Pattern Analysis and Machine Intelligence, + // (2) Z.Zivkovic, F. van der Heijden, Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction, + // Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006. + // The algorithm similar to the standard Stauffer&Grimson algorithm with additional selection of the number of the Gaussian components based on: + // Z.Zivkovic, F.van der Heijden, Recursive unsupervised learning of finite mixture models, IEEE Trans. on Pattern Analysis and Machine Intelligence, // vol.26, no.5, pages 651-656, 2004. //------------------------------------------------------------------ +#if CV_MAJOR_VERSION == 2 mog(img_input, img_foreground, alpha); - - cv::Mat img_background; mog.getBackgroundImage(img_background); +#elif CV_MAJOR_VERSION == 3 + mog->apply(img_input, img_foreground, alpha); + mog->getBackgroundImage(img_background); +#endif - if(enableThreshold) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) { - cv::imshow("GMM (Zivkovic&Heijden)", img_foreground); - cv::imshow("GMM BKG (Zivkovic&Heijden)", img_background); + cv::imshow("GMM FG (Zivkovic&Heijden)", img_foreground); + cv::imshow("GMM BG (Zivkovic&Heijden)", img_background); } +#endif img_foreground.copyTo(img_output); img_background.copyTo(img_bgmodel); @@ -73,9 +82,9 @@ void MixtureOfGaussianV2BGS::process(const cv::Mat &img_input, cv::Mat &img_outp firstTime = false; } -void MixtureOfGaussianV2BGS::saveConfig() +void MixtureOfGaussianV2::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MixtureOfGaussianV2BGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "alpha", alpha); cvWriteInt(fs, "enableThreshold", enableThreshold); @@ -85,14 +94,14 @@ void MixtureOfGaussianV2BGS::saveConfig() cvReleaseFileStorage(&fs); } -void MixtureOfGaussianV2BGS::loadConfig() +void MixtureOfGaussianV2::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MixtureOfGaussianV2BGS.xml", 0, CV_STORAGE_READ); - - alpha = cvReadRealByName(fs, 0, "alpha", 0.05); - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); } diff --git a/package_bgs/MixtureOfGaussianV2BGS.h b/package_bgs/MixtureOfGaussianV2.h similarity index 57% rename from package_bgs/MixtureOfGaussianV2BGS.h rename to package_bgs/MixtureOfGaussianV2.h index a14ff0b788fb4e161e9d4acd7a2855a71f68a2c6..edc8add6c693988fd2bc9c06815b0b6e4d01c9ca 100644 --- a/package_bgs/MixtureOfGaussianV2BGS.h +++ b/package_bgs/MixtureOfGaussianV2.h @@ -18,30 +18,35 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - #include <opencv2/video/background_segm.hpp> #include "IBGS.h" -class MixtureOfGaussianV2BGS : public IBGS +namespace bgslibrary { -private: - bool firstTime; - cv::BackgroundSubtractorMOG2 mog; - cv::Mat img_foreground; - double alpha; - bool enableThreshold; - int threshold; - bool showOutput; - -public: - MixtureOfGaussianV2BGS(); - ~MixtureOfGaussianV2BGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; - + 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/sjn/SJN_MultiCueBGS.cpp b/package_bgs/MultiCue.cpp similarity index 83% rename from package_bgs/sjn/SJN_MultiCueBGS.cpp rename to package_bgs/MultiCue.cpp index 83db6ec62153ca3a40136dc9df2a3ffbb762dd94..7717842975210f5ff32eeb876f615737d4c024bd 100644 --- a/package_bgs/sjn/SJN_MultiCueBGS.cpp +++ b/package_bgs/MultiCue.cpp @@ -21,12 +21,16 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // - Code by: SeungJon Noh // //------------------------------------------------------------------------------------------------------------------------------------// //#include "StdAfx.h" -#include "SJN_MultiCueBGS.h" -SJN_MultiCueBGS::SJN_MultiCueBGS() : firstTime(true), showOutput(true) +#include "MultiCue.h" + +using namespace bgslibrary::algorithms::libMultiCue; +using namespace bgslibrary::algorithms; + +MultiCue::MultiCue() { //---------------------------------- // User adjustable parameters - //---------------------------------- + //---------------------------------- g_iTrainingPeriod = 20; //the training period (The parameter t in the paper) g_iT_ModelThreshold = 1; //the threshold for texture-model based BGS. (The parameter tau_T in the paper) g_iC_ModelThreshold = 10; //the threshold for appearance based verification. (The parameter tau_A in the paper) @@ -37,15 +41,15 @@ SJN_MultiCueBGS::SJN_MultiCueBGS() : firstTime(true), showOutput(true) g_nColorTrainVolRange = 20; //the codebook size factor for color models. (The parameter eta_1 in the paper) g_bAbsorptionEnable = TRUE; //If TRUE, cache-book is also modeled for ghost region removal. - g_iAbsortionPeriod = 200; //the period to absorb static ghost regions + g_iAbsortionPeriod = 200; //the period to absorb static ghost regions g_iRWidth = 160, g_iRHeight = 120; //Frames are precessed after reduced in this size . //------------------------------------ // For codebook maintenance //------------------------------------ - g_iBackClearPeriod = 300; //the period to clear background models - g_iCacheClearPeriod = 30; //the period to clear cache-book models + g_iBackClearPeriod = 300; //the period to clear background models + g_iCacheClearPeriod = 30; //the period to clear cache-book models //------------------------------------ // Initialization of other parameters @@ -57,38 +61,37 @@ SJN_MultiCueBGS::SJN_MultiCueBGS() : firstTime(true), showOutput(true) g_bForegroundMapEnable = FALSE; //TRUE only when BGS is successful g_bModelMemAllocated = FALSE; //To handle memory.. g_bNonModelMemAllocated = FALSE; //To handle memory.. + + std::cout << "MultiCue()" << std::endl; + setup("./config/MultiCue.xml"); } -SJN_MultiCueBGS::~SJN_MultiCueBGS(void){ +MultiCue::~MultiCue(void) +{ Destroy(); + std::cout << "~MultiCue()" << std::endl; } //-----------------------------------------------------------------------------------------------------------------------------------------// // the main function to background modeling and subtraction // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel){ - - if (img_input.empty()) - return; - - loadConfig(); - - if (firstTime) - saveConfig(); +void MultiCue::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +{ + init(img_input, img_output, img_bgmodel); //--STep1: Background Modeling--// //IplImage* frame = &IplImage(img_input); IplImage* frame = new IplImage(img_input); 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); @@ -99,33 +102,35 @@ void SJN_MultiCueBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv: } delete frame; - cv::Mat temp(result_image, TRUE); - temp.copyTo(img_output); - + img_background = cv::Mat::zeros(img_input.size(), img_input.type()); + img_foreground = cv::cvarrToMat(result_image, TRUE); cvReleaseImage(&result_image); +#ifndef MEX_COMPILE_FLAG if (showOutput) - { - cv::imshow("MultiCueBGS FG", img_output); - } + cv::imshow("MultiCue FG", img_foreground); +#endif + + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); firstTime = false; } -void SJN_MultiCueBGS::saveConfig() +void MultiCue::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MultiCueBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "showOutput", showOutput); cvReleaseFileStorage(&fs); } -void SJN_MultiCueBGS::loadConfig() +void MultiCue::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MultiCueBGS.xml", 0, CV_STORAGE_READ); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + showOutput = cvReadIntByName(fs, nullptr, "showOutput", true); cvReleaseFileStorage(&fs); } @@ -133,7 +138,7 @@ void SJN_MultiCueBGS::loadConfig() //-----------------------------------------------------------------------------------------------------------------------------------------// // the system initialization function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::Initialize(IplImage* frame) +void MultiCue::Initialize(IplImage* frame) { int i, j; @@ -148,15 +153,15 @@ void SJN_MultiCueBGS::Initialize(IplImage* frame) g_ResizedFrame = cvCreateImage(cvSize(g_iRWidth, g_iRHeight), IPL_DEPTH_8U, 3); g_aGaussFilteredFrame = (uchar***)malloc(sizeof(uchar**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_aGaussFilteredFrame[i] = (uchar**)malloc(sizeof(uchar*)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++) g_aGaussFilteredFrame[i][j] = (uchar*)malloc(sizeof(uchar)* 3); + for (j = 0; j < g_iRWidth; j++) g_aGaussFilteredFrame[i][j] = (uchar*)malloc(sizeof(uchar) * 3); } g_aXYZFrame = (uchar***)malloc(sizeof(uchar**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_aXYZFrame[i] = (uchar**)malloc(sizeof(uchar*)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++) g_aXYZFrame[i][j] = (uchar*)malloc(sizeof(uchar)* 3); + for (j = 0; j < g_iRWidth; j++) g_aXYZFrame[i][j] = (uchar*)malloc(sizeof(uchar) * 3); } g_aLandmarkArray = (uchar**)malloc(sizeof(uchar*)*g_iRHeight); @@ -203,30 +208,30 @@ void SJN_MultiCueBGS::Initialize(IplImage* frame) //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to release allocated memories // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::Destroy() +void MultiCue::Destroy() { if (g_bModelMemAllocated == FALSE && g_bNonModelMemAllocated == FALSE) return; short nNeighborNum = g_nNeighborNum; - if (g_bModelMemAllocated == TRUE){ + if (g_bModelMemAllocated == TRUE) { T_ReleaseTextureModelRelatedMemory(); C_ReleaseColorModelRelatedMemory(); g_bModelMemAllocated = FALSE; } - if (g_bNonModelMemAllocated == TRUE){ + if (g_bNonModelMemAllocated == TRUE) { cvReleaseImage(&g_ResizedFrame); - for (int i = 0; i < g_iRHeight; i++){ + for (int i = 0; i < g_iRHeight; i++) { for (int j = 0; j < g_iRWidth; j++) free(g_aGaussFilteredFrame[i][j]); free(g_aGaussFilteredFrame[i]); } free(g_aGaussFilteredFrame); - for (int i = 0; i < g_iRHeight; i++){ + for (int i = 0; i < g_iRHeight; i++) { for (int j = 0; j < g_iRWidth; j++) free(g_aXYZFrame[i][j]); free(g_aXYZFrame[i]); } @@ -256,7 +261,7 @@ void SJN_MultiCueBGS::Destroy() //-----------------------------------------------------------------------------------------------------------------------------------------// // the preprocessing function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::PreProcessing(IplImage* frame){ +void MultiCue::PreProcessing(IplImage* frame) { //image resize ReduceImageSize(frame, g_ResizedFrame); @@ -271,7 +276,7 @@ void SJN_MultiCueBGS::PreProcessing(IplImage* frame){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the background modeling function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::BackgroundModeling_Par(IplImage* frame){ +void MultiCue::BackgroundModeling_Par(IplImage* frame) { //initialization if (g_iFrameCount == 0) Initialize(frame); @@ -285,8 +290,8 @@ void SJN_MultiCueBGS::BackgroundModeling_Par(IplImage* frame){ float fLearningRate = g_fLearningRate * 4; //Step2: background modeling - for (int i = iH_Start; i < iH_end; i++){ - for (int j = iW_Start; j < iW_end; j++){ + for (int i = iH_Start; i < iH_end; i++) { + for (int j = iW_Start; j < iW_end; j++) { point center; center.m_nX = j; center.m_nY = i; @@ -297,9 +302,9 @@ void SJN_MultiCueBGS::BackgroundModeling_Par(IplImage* frame){ } //Step3: Clear non-essential codewords - if (g_iFrameCount == g_iTrainingPeriod){ - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + if (g_iFrameCount == g_iTrainingPeriod) { + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { T_ClearNonEssentialEntries(g_iTrainingPeriod, g_TextureModel[i][j]); C_ClearNonEssentialEntries(g_iTrainingPeriod, g_ColorModel[i][j]); @@ -312,7 +317,7 @@ void SJN_MultiCueBGS::BackgroundModeling_Par(IplImage* frame){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the background subtraction function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::ForegroundExtraction(IplImage* frame){ +void MultiCue::ForegroundExtraction(IplImage* frame) { //Step1:pre-processing PreProcessing(frame); @@ -332,9 +337,9 @@ void SJN_MultiCueBGS::ForegroundExtraction(IplImage* frame){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the post-processing function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::PostProcessing(IplImage* frame){ +void MultiCue::PostProcessing(IplImage* frame) { - //Step1: morphological operation + //Step1: morphological operation MorphologicalOpearions(g_aLandmarkArray, g_aResizedForeMap, 0.5, 5, g_iRWidth, g_iRHeight); g_bForegroundMapEnable = TRUE; @@ -361,20 +366,20 @@ void SJN_MultiCueBGS::PostProcessing(IplImage* frame){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the background-model update function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::UpdateModel_Par(){ +void MultiCue::UpdateModel_Par() { short nNeighborNum = g_nNeighborNum; //Step1: update map construction - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { g_aUpdateMap[i][j] = TRUE; } } - for (int k = 0; k < g_BoundBoxInfo->m_iBoundBoxNum; k++){ - if (g_BoundBoxInfo->m_ValidBox[k] == TRUE){ - for (int i = g_BoundBoxInfo->m_aRUpper[k]; i <= g_BoundBoxInfo->m_aRBottom[k]; i++){ - for (int j = g_BoundBoxInfo->m_aRLeft[k]; j <= g_BoundBoxInfo->m_aRRight[k]; j++){ + for (int k = 0; k < g_BoundBoxInfo->m_iBoundBoxNum; k++) { + if (g_BoundBoxInfo->m_ValidBox[k] == TRUE) { + for (int i = g_BoundBoxInfo->m_aRUpper[k]; i <= g_BoundBoxInfo->m_aRBottom[k]; i++) { + for (int j = g_BoundBoxInfo->m_aRLeft[k]; j <= g_BoundBoxInfo->m_aRRight[k]; j++) { g_aUpdateMap[i][j] = FALSE; } } @@ -387,16 +392,16 @@ void SJN_MultiCueBGS::UpdateModel_Par(){ float fLearningRate = (float)g_fLearningRate; - for (int i = iH_Start; i < iH_End; i++){ - for (int j = iW_Start; j < iW_End; j++){ + for (int i = iH_Start; i < iH_End; i++) { + for (int j = iW_Start; j < iW_End; j++) { point center; center.m_nX = j; center.m_nY = i; - if (g_aUpdateMap[i][j] == TRUE){ - //model update + if (g_aUpdateMap[i][j] == TRUE) { + //model update T_ModelConstruction(g_nTextureTrainVolRange, fLearningRate, g_aXYZFrame, center, g_aNeighborDirection[i][j], g_TextureModel[i][j]); C_CodebookConstruction(g_aXYZFrame[i][j], j, i, g_nColorTrainVolRange, fLearningRate, g_ColorModel[i][j]); @@ -406,7 +411,7 @@ void SJN_MultiCueBGS::UpdateModel_Par(){ } else { - if (g_bAbsorptionEnable == TRUE){ + if (g_bAbsorptionEnable == TRUE) { //model update T_ModelConstruction(g_nTextureTrainVolRange, fLearningRate, g_aXYZFrame, center, g_aNeighborDirection[i][j], g_TCacheBook[i][j]); C_CodebookConstruction(g_aXYZFrame[i][j], j, i, g_nColorTrainVolRange, fLearningRate, g_CCacheBook[i][j]); @@ -419,7 +424,7 @@ void SJN_MultiCueBGS::UpdateModel_Par(){ } //clearing non-essential codewords for cache-books - if (g_bAbsorptionEnable == TRUE){ + if (g_bAbsorptionEnable == TRUE) { T_ClearNonEssentialEntriesForCachebook(g_aLandmarkArray[i][j], g_aTReferredIndex[i][j], 10, g_TCacheBook[i][j]); C_ClearNonEssentialEntriesForCachebook(g_aLandmarkArray[i][j], g_aCReferredIndex[i][j], 10, g_CCacheBook[i][j]); } @@ -431,16 +436,16 @@ void SJN_MultiCueBGS::UpdateModel_Par(){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the color based verification function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRange, float**aConfMap, int iNehborNum, uchar*** aXYZ, - point*** aNeiDir, TextureModel**** TModel, ColorModel*** CModel, uchar**aLandmarkArr){ +void MultiCue::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRange, float**aConfMap, int iNehborNum, uchar*** aXYZ, + point*** aNeiDir, TextureModel**** TModel, ColorModel*** CModel, uchar**aLandmarkArr) { int iBound_w = g_iRWidth - g_nRadius; int iBound_h = g_iRHeight - g_nRadius; - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { - if (i < g_nRadius || i >= iBound_h || j<g_nRadius || j >= iBound_w) { + if (i < g_nRadius || i >= iBound_h || j < g_nRadius || j >= iBound_w) { aLandmarkArr[i][j] = 0; continue; } @@ -448,14 +453,14 @@ void SJN_MultiCueBGS::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRa double tmp = aConfMap[i][j]; if (tmp > fConfThre) aLandmarkArr[i][j] = 255; - else{ + else { aLandmarkArr[i][j] = 0; //Calculating texture amount in the background double dBackAmt, dCnt; dBackAmt = dCnt = 0; - for (int m = 0; m < iNehborNum; m++){ - for (int n = 0; n < TModel[i][j][m]->m_iNumEntries; n++){ + for (int m = 0; m < iNehborNum; m++) { + for (int n = 0; n < TModel[i][j][m]->m_iNumEntries; n++) { dBackAmt += TModel[i][j][m]->m_Codewords[n]->m_fMean; dCnt++; } @@ -464,7 +469,7 @@ void SJN_MultiCueBGS::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRa //Calculating texture amount in the input image double dTemp, dInputAmt = 0; - for (int m = 0; m < iNehborNum; m++){ + for (int m = 0; m < iNehborNum; m++) { dTemp = aXYZ[i][j][2] - aXYZ[aNeiDir[i][j][m].m_nY][aNeiDir[i][j][m].m_nX][2]; if (dTemp >= 0) dInputAmt += dTemp; @@ -473,13 +478,13 @@ void SJN_MultiCueBGS::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRa } //If there are only few textures in both background and input image - if (dBackAmt < 50 && dInputAmt < 50){ + if (dBackAmt < 50 && dInputAmt < 50) { //Conduct color codebook matching BOOL bMatched = FALSE; - for (int m = 0; m < CModel[i][j]->m_iNumEntries; m++){ + for (int m = 0; m < CModel[i][j]->m_iNumEntries; m++) { int iMatchedCount = 0; - for (int n = 0; n < 3; n++){ + for (int n = 0; n < 3; n++) { double dLowThre = CModel[i][j]->m_Codewords[m]->m_dMean[n] - nTrainVolRange - 10; double dHighThre = CModel[i][j]->m_Codewords[m]->m_dMean[n] + nTrainVolRange + 10; @@ -505,13 +510,13 @@ void SJN_MultiCueBGS::CreateLandmarkArray_Par(float fConfThre, short nTrainVolRa //-----------------------------------------------------------------------------------------------------------------------------------------// // the Gaussian filtering function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame){ +void MultiCue::GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame) { double dSigma = 0.7; - if (dSigma == 0){ - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + if (dSigma == 0) { + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { aFilteredFrame[i][j][0] = frame->imageData[i*frame->widthStep + j * 3]; aFilteredFrame[i][j][1] = frame->imageData[i*frame->widthStep + j * 3 + 1]; aFilteredFrame[i][j][2] = frame->imageData[i*frame->widthStep + j * 3 + 2]; @@ -520,16 +525,16 @@ void SJN_MultiCueBGS::GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame } else { - cv::Mat temp_img(frame, TRUE); + cv::Mat temp_img = cv::cvarrToMat(frame, TRUE); cv::GaussianBlur(temp_img, temp_img, cv::Size(7, 7), dSigma); //Store results into aFilteredFrame[][][] //IplImage* img = &IplImage(temp_img); IplImage* img = new IplImage(temp_img); - int iWidthStep = img->widthStep; + //int iWidthStep = img->widthStep; - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { aFilteredFrame[i][j][0] = img->imageData[i*img->widthStep + j * 3]; aFilteredFrame[i][j][1] = img->imageData[i*img->widthStep + j * 3 + 1]; aFilteredFrame[i][j][2] = img->imageData[i*img->widthStep + j * 3 + 2]; @@ -542,7 +547,7 @@ void SJN_MultiCueBGS::GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame //------------------------------------------------------------------------------------------------------------------------------------// // the image resize function // //------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::ReduceImageSize(IplImage* SrcImage, IplImage* DstImage){ +void MultiCue::ReduceImageSize(IplImage* SrcImage, IplImage* DstImage) { int iChannel = 3; @@ -550,8 +555,8 @@ void SJN_MultiCueBGS::ReduceImageSize(IplImage* SrcImage, IplImage* DstImage){ double dResizeFactor_h = (double)g_iHeight / (double)g_iRHeight; - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { int iSrcY = (int)(i*dResizeFactor_h); int iSrcX = (int)(j*dResizeFactor_w); @@ -565,18 +570,18 @@ void SJN_MultiCueBGS::ReduceImageSize(IplImage* SrcImage, IplImage* DstImage){ //------------------------------------------------------------------------------------------------------------------------------------// // the color space conversion function // //------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ){ +void MultiCue::BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ) { double dH_ratio = (2 * PI) / 360; - for (int i = 0; i < g_iRHeight; i++){ + for (int i = 0; i < g_iRHeight; i++) { double dR, dG, dB; double dMax, dMin; double dH, dS, dV; - for (int j = 0; j < g_iRWidth; j++){ + for (int j = 0; j < g_iRWidth; j++) { dB = (double)(aBGR[i][j][0]) / 255; dG = (double)(aBGR[i][j][1]) / 255; @@ -593,13 +598,13 @@ void SJN_MultiCueBGS::BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ){ //Get S, H if (dV == 0) dS = dH = 0; - else{ + else { //S value dS = (dMax - dMin) / dMax; if (dS == 0) dH = 0; - else{ + else { //H value if (dMax == dR) { dH = 60 * (dG - dB) / dS; @@ -622,7 +627,7 @@ void SJN_MultiCueBGS::BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to get enlarged confidence map // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::GetEnlargedMap(float** aOriginMap, float** aEnlargedMap){ +void MultiCue::GetEnlargedMap(float** aOriginMap, float** aEnlargedMap) { int i, j; short nSrcX; @@ -639,8 +644,8 @@ void SJN_MultiCueBGS::GetEnlargedMap(float** aOriginMap, float** aEnlargedMap){ double dScaleFactor_w = ((double)g_iWidth) / ((double)g_iRWidth); double dScaleFactor_h = ((double)g_iHeight) / ((double)g_iRHeight); - for (i = 0; i < g_iHeight; i++){ - for (j = 0; j < g_iWidth; j++){ + for (i = 0; i < g_iHeight; i++) { + for (j = 0; j < g_iWidth; j++) { //backward mapping nSrcY = (int)(i / dScaleFactor_h); nSrcX = (int)(j / dScaleFactor_w); @@ -668,7 +673,7 @@ void SJN_MultiCueBGS::GetEnlargedMap(float** aOriginMap, float** aEnlargedMap){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the morphological operation function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::MorphologicalOpearions(uchar** aInput, uchar** aOutput, double dThresholdRatio, int iMaskSize, int iWidth, int iHeight){ +void MultiCue::MorphologicalOpearions(uchar** aInput, uchar** aOutput, double dThresholdRatio, int iMaskSize, int iWidth, int iHeight) { int iOffset = (int)(iMaskSize / 2); @@ -676,28 +681,28 @@ void SJN_MultiCueBGS::MorphologicalOpearions(uchar** aInput, uchar** aOutput, do int iBound_h = iHeight - iOffset; uchar** aTemp = (uchar**)malloc(sizeof(uchar*)*iHeight); - for (int i = 0; i < iHeight; i++){ + for (int i = 0; i < iHeight; i++) { aTemp[i] = (uchar*)malloc(sizeof(uchar)*iWidth); } - for (int i = 0; i < iHeight; i++){ - for (int j = 0; j < iWidth; j++){ + for (int i = 0; i < iHeight; i++) { + for (int j = 0; j < iWidth; j++) { aTemp[i][j] = aInput[i][j]; } } int iThreshold = (int)(iMaskSize*iMaskSize*dThresholdRatio); - for (int i = 0; i < iHeight; i++){ - for (int j = 0; j < iWidth; j++){ + for (int i = 0; i < iHeight; i++) { + for (int j = 0; j < iWidth; j++) { - if (i < iOffset || i >= iBound_h || j < iOffset || j >= iBound_w){ + if (i < iOffset || i >= iBound_h || j < iOffset || j >= iBound_w) { aOutput[i][j] = 0; continue; } int iCnt = 0; - for (int m = -iOffset; m <= iOffset; m++){ - for (int n = -iOffset; n <= iOffset; n++){ + for (int m = -iOffset; m <= iOffset; m++) { + for (int n = -iOffset; n <= iOffset; n++) { if (aTemp[i + m][j + n] == 255) iCnt++; } } @@ -708,7 +713,7 @@ void SJN_MultiCueBGS::MorphologicalOpearions(uchar** aInput, uchar** aOutput, do } - for (int i = 0; i < iHeight; i++){ + for (int i = 0; i < iHeight; i++) { free(aTemp[i]); } free(aTemp); @@ -717,7 +722,7 @@ void SJN_MultiCueBGS::MorphologicalOpearions(uchar** aInput, uchar** aOutput, do //-----------------------------------------------------------------------------------------------------------------------------------------// // 2-raster scan pass based labeling function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLabelTable){ +void MultiCue::Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLabelTable) { int x, y, i; // pass 1,2 int cnt = 0; // pass 1 int label = 0; // pass 2 @@ -730,45 +735,45 @@ void SJN_MultiCueBGS::Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLa int* aTable1 = (int*)malloc(iSize / 2 * sizeof(int)); int* aTable2 = (int*)malloc(iSize / 2 * sizeof(int)); - memset(aPass1, 0, (iSize)* sizeof(int)); - for (y = 1; y < (g_iRHeight); y++){ - for (x = 1; x < (g_iRWidth); x++){ + memset(aPass1, 0, (iSize) * sizeof(int)); + for (y = 1; y < (g_iRHeight); y++) { + for (x = 1; x < (g_iRWidth); x++) { aLabelTable[y][x] = 0; } } - for (i = 0; i < iTableSize; i++){ + for (i = 0; i < iTableSize; i++) { aTable1[i] = i; } memset(aTable2, 0, iTableSize * sizeof(int)); // pass 1 - for (y = 1; y < (g_iRHeight); y++){ - for (x = 1; x < (g_iRWidth); x++){ + for (y = 1; y < (g_iRHeight); y++) { + for (x = 1; x < (g_iRWidth); x++) { - if (aBinaryArray[y][x] == 255){ // fore ground?? + if (aBinaryArray[y][x] == 255) { // fore ground?? int up, le; up = aPass1[(y - 1)*(g_iRWidth)+(x)]; // up index le = aPass1[(y)*(g_iRWidth)+(x - 1)]; // left index // case - if (up == 0 && le == 0){ + if (up == 0 && le == 0) { ++cnt; aPass1[y * g_iRWidth + x] = cnt; } - else if (up != 0 && le != 0){ - if (up > le){ + else if (up != 0 && le != 0) { + if (up > le) { aPass1[y *g_iRWidth + x] = le; aTable1[up] = aTable1[le]; // update table1 table1 } - else{ + else { aPass1[y * g_iRWidth + x] = up; aTable1[le] = aTable1[up]; // update table1 table1 } } - else{ + else { aPass1[y * g_iRWidth + x] = up + le; } @@ -778,13 +783,13 @@ void SJN_MultiCueBGS::Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLa } // pass 2 - for (y = 1; y < (g_iRHeight); y++){ - for (x = 1; x < (g_iRWidth); x++){ + for (y = 1; y < (g_iRHeight); y++) { + for (x = 1; x < (g_iRWidth); x++) { - if (aPass1[y * g_iRWidth + x]){ + if (aPass1[y * g_iRWidth + x]) { int v = aTable1[aPass1[y * g_iRWidth + x]]; - if (aTable2[v] == 0){ + if (aTable2[v] == 0) { ++label; aTable2[v] = label; } @@ -804,12 +809,12 @@ void SJN_MultiCueBGS::Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLa //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to set bounding boxes for each candidate foreground regions // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::SetBoundingBox(int iLabelCount, int** aLabelTable){ +void MultiCue::SetBoundingBox(int iLabelCount, int** aLabelTable) { int iBoundBoxIndex; g_BoundBoxInfo->m_iBoundBoxNum = iLabelCount; - for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++) { g_BoundBoxInfo->m_aRLeft[i] = 9999; //left g_BoundBoxInfo->m_aRUpper[i] = 9999; //top g_BoundBoxInfo->m_aRRight[i] = 0; //right @@ -817,8 +822,8 @@ void SJN_MultiCueBGS::SetBoundingBox(int iLabelCount, int** aLabelTable){ } //Step1: Set tight bounding boxes - for (int i = 1; i<g_iRHeight; i++){ - for (int j = 1; j<g_iRWidth; j++){ + for (int i = 1; i < g_iRHeight; i++) { + for (int j = 1; j < g_iRWidth; j++) { if ((aLabelTable[i][j] == 0)) continue; @@ -835,7 +840,7 @@ void SJN_MultiCueBGS::SetBoundingBox(int iLabelCount, int** aLabelTable){ //Step2: Add margins. int iBoundary_w = (int)(g_iRWidth / 80), iBoundary_h = (int)(g_iRHeight / 60); - for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++) { g_BoundBoxInfo->m_aRLeft[i] -= iBoundary_w; if (g_BoundBoxInfo->m_aRLeft[i] < g_nRadius) g_BoundBoxInfo->m_aRLeft[i] = g_nRadius; //left @@ -853,7 +858,7 @@ void SJN_MultiCueBGS::SetBoundingBox(int iLabelCount, int** aLabelTable){ double dH_ratio = (double)g_iHeight / (double)g_iRHeight; double dW_ratio = (double)g_iWidth / (double)g_iRWidth; - for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < g_BoundBoxInfo->m_iBoundBoxNum; i++) { g_BoundBoxInfo->m_aLeft[i] = (int)(g_BoundBoxInfo->m_aRLeft[i] * dW_ratio); g_BoundBoxInfo->m_aUpper[i] = (int)(g_BoundBoxInfo->m_aRUpper[i] * dH_ratio); g_BoundBoxInfo->m_aRight[i] = (int)(g_BoundBoxInfo->m_aRRight[i] * dW_ratio); @@ -865,7 +870,7 @@ void SJN_MultiCueBGS::SetBoundingBox(int iLabelCount, int** aLabelTable){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the box verification function // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::BoundBoxVerification(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo){ +void MultiCue::BoundBoxVerification(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo) { //Step1: Verification by the bounding box size EvaluateBoxSize(BoundBoxInfo); @@ -875,7 +880,7 @@ void SJN_MultiCueBGS::BoundBoxVerification(IplImage* frame, uchar** aResForeMap, //Step3: Counting the # of valid box g_iForegroundNum = 0; - for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++) { if (BoundBoxInfo->m_ValidBox[i] == TRUE) g_iForegroundNum++; } } @@ -883,7 +888,7 @@ void SJN_MultiCueBGS::BoundBoxVerification(IplImage* frame, uchar** aResForeMap, //-----------------------------------------------------------------------------------------------------------------------------------------// // the size based verification // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::EvaluateBoxSize(BoundingBoxInfo* BoundBoxInfo){ +void MultiCue::EvaluateBoxSize(BoundingBoxInfo* BoundBoxInfo) { //Set thresholds int iLowThreshold_w, iHighThreshold_w; @@ -897,7 +902,7 @@ void SJN_MultiCueBGS::EvaluateBoxSize(BoundingBoxInfo* BoundBoxInfo){ int iBoxWidth, iBoxHeight; //Perform verification. - for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++) { iBoxWidth = BoundBoxInfo->m_aRRight[i] - BoundBoxInfo->m_aRLeft[i]; iBoxHeight = BoundBoxInfo->m_aRBottom[i] - BoundBoxInfo->m_aRUpper[i]; @@ -912,7 +917,7 @@ void SJN_MultiCueBGS::EvaluateBoxSize(BoundingBoxInfo* BoundBoxInfo){ //------------------------------------------------------------------------------------------------------------------------------------// // overlapped region removal // //------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo){ +void MultiCue::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo) { BOOL *aValidBoxFlag = new BOOL[SrcBoxInfo->m_iBoundBoxNum]; for (int i = 0; i < SrcBoxInfo->m_iBoundBoxNum; i++) aValidBoxFlag[i] = TRUE; @@ -924,7 +929,7 @@ void SJN_MultiCueBGS::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo){ int iThreshold, iCount, iSmall_Idx, iLarge_Idx; double dThreRatio = 0.7; - for (int i = 0; i < SrcBoxInfo->m_iBoundBoxNum; i++){ + for (int i = 0; i < SrcBoxInfo->m_iBoundBoxNum; i++) { if (SrcBoxInfo->m_ValidBox[i] == FALSE) { aValidBoxFlag[i] = FALSE; @@ -933,7 +938,7 @@ void SJN_MultiCueBGS::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo){ size1 = (aRight[i] - aLeft[i]) * (aBottom[i] - aTop[i]); - for (int j = i; j < SrcBoxInfo->m_iBoundBoxNum; j++){ + for (int j = i; j < SrcBoxInfo->m_iBoundBoxNum; j++) { if ((i == j) || (SrcBoxInfo->m_ValidBox[j] == FALSE)) continue; //Setting threshold for checking overlapped region size @@ -950,8 +955,8 @@ void SJN_MultiCueBGS::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo){ //Calculating overlapped region size iCount = 0; - for (int m = aLeft[iSmall_Idx]; m < aRight[iSmall_Idx]; m++){ - for (int n = aTop[iSmall_Idx]; n<aBottom[iSmall_Idx]; n++){ + for (int m = aLeft[iSmall_Idx]; m < aRight[iSmall_Idx]; m++) { + for (int n = aTop[iSmall_Idx]; n < aBottom[iSmall_Idx]; n++) { if (aLeft[iLarge_Idx] <= m && m <= aRight[iLarge_Idx] && aTop[iLarge_Idx] <= n && n <= aBottom[iLarge_Idx]) iCount++; } } @@ -968,20 +973,20 @@ void SJN_MultiCueBGS::EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo){ //-----------------------------------------------------------------------------------------------------------------------------------------// // appearance based verification // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo){ +void MultiCue::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo) { double dThreshold = 10; BOOL** aUpdateMap = (BOOL**)malloc(sizeof(BOOL*)*g_iRHeight); - for (int i = 0; i < g_iRHeight; i++){ + for (int i = 0; i < g_iRHeight; i++) { aUpdateMap[i] = (BOOL*)malloc(sizeof(BOOL)*g_iRWidth); for (int j = 0; j < g_iRWidth; j++) aUpdateMap[i][j] = FALSE; } //Step1: Conduct fore-region evaluation to identify ghost regions - for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++){ - if (BoundBoxInfo->m_ValidBox[i] == TRUE){ + for (int i = 0; i < BoundBoxInfo->m_iBoundBoxNum; i++) { + if (BoundBoxInfo->m_ValidBox[i] == TRUE) { int iWin_w = BoundBoxInfo->m_aRRight[i] - BoundBoxInfo->m_aRLeft[i]; int iWin_h = BoundBoxInfo->m_aRBottom[i] - BoundBoxInfo->m_aRUpper[i]; @@ -999,8 +1004,8 @@ void SJN_MultiCueBGS::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, //Generating edge image from aResForeMap IplImage* edge_fore = cvCreateImage(cvSize(iWin_w, iWin_h), IPL_DEPTH_8U, 1); - for (int m = BoundBoxInfo->m_aRUpper[i]; m < BoundBoxInfo->m_aRBottom[i]; m++){ - for (int n = BoundBoxInfo->m_aRLeft[i]; n<BoundBoxInfo->m_aRRight[i]; n++){ + for (int m = BoundBoxInfo->m_aRUpper[i]; m < BoundBoxInfo->m_aRBottom[i]; m++) { + for (int n = BoundBoxInfo->m_aRLeft[i]; n < BoundBoxInfo->m_aRRight[i]; n++) { edge_fore->imageData[(m - BoundBoxInfo->m_aRUpper[i])*edge_fore->widthStep + (n - BoundBoxInfo->m_aRLeft[i])] = (char)aResForeMap[m][n]; } } @@ -1011,8 +1016,8 @@ void SJN_MultiCueBGS::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, //Recording evaluation result if (distance > dThreshold) { - for (int m = BoundBoxInfo->m_aRUpper[i]; m < BoundBoxInfo->m_aRBottom[i]; m++){ - for (int n = BoundBoxInfo->m_aRLeft[i]; n < BoundBoxInfo->m_aRRight[i]; n++){ + for (int m = BoundBoxInfo->m_aRUpper[i]; m < BoundBoxInfo->m_aRBottom[i]; m++) { + for (int n = BoundBoxInfo->m_aRLeft[i]; n < BoundBoxInfo->m_aRRight[i]; n++) { aUpdateMap[m][n] = TRUE; } } @@ -1029,9 +1034,9 @@ void SJN_MultiCueBGS::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, //Step2: Adding information fo ghost region pixels to background model float fLearningRate = g_fLearningRate; - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ - if (aUpdateMap[i][j] == TRUE){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { + if (aUpdateMap[i][j] == TRUE) { point center; center.m_nX = j; center.m_nY = i; @@ -1053,16 +1058,16 @@ void SJN_MultiCueBGS::EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to calculate partial undirected Hausdorff distance(forward distance) // // //-----------------------------------------------------------------------------------------------------------------------------------------// -double SJN_MultiCueBGS::CalculateHausdorffDist(IplImage* input_image, IplImage* model_image){ +double MultiCue::CalculateHausdorffDist(IplImage* input_image, IplImage* model_image) { //Step1: Generating imag vectors //For reduce errors, points at the image boundary are excluded - vector<point> vInput, vModel; + std::vector<point> vInput, vModel; point temp; - //input image --> input vector - for (int i = 0; i < input_image->height; i++){ - for (int j = 0; j < input_image->width; j++){ + //input image --> input vector + for (int i = 0; i < input_image->height; i++) { + for (int j = 0; j < input_image->width; j++) { if ((uchar)input_image->imageData[i*input_image->widthStep + j] == 0) continue; @@ -1071,8 +1076,8 @@ double SJN_MultiCueBGS::CalculateHausdorffDist(IplImage* input_image, IplImage* } } //model image --> model vector - for (int i = 0; i < model_image->height; i++){ - for (int j = 0; j < model_image->width; j++){ + for (int i = 0; i < model_image->height; i++) { + for (int j = 0; j < model_image->width; j++) { if ((uchar)model_image->imageData[i*model_image->widthStep + j] == 0) continue; temp.m_nX = j; temp.m_nY = i; @@ -1086,12 +1091,12 @@ double SJN_MultiCueBGS::CalculateHausdorffDist(IplImage* input_image, IplImage* //Step2: Calculating forward distance h(Model,Image) double dDist, temp1, temp2, dMinDist; - vector<double> vTempDist; + std::vector<double> vTempDist; - for (auto iter_m = vModel.begin(); iter_m < vModel.end(); iter_m++){ + for (auto iter_m = vModel.begin(); iter_m < vModel.end(); iter_m++) { dMinDist = 9999999; - for (auto iter_i = vInput.begin(); iter_i < vInput.end(); iter_i++){ + for (auto iter_i = vInput.begin(); iter_i < vInput.end(); iter_i++) { temp1 = (*iter_m).m_nX - (*iter_i).m_nX; temp2 = (*iter_m).m_nY - (*iter_i).m_nY; dDist = temp1*temp1 + temp2*temp2; @@ -1114,15 +1119,15 @@ double SJN_MultiCueBGS::CalculateHausdorffDist(IplImage* input_image, IplImage* //-----------------------------------------------------------------------------------------------------------------------------------------// // function to remove non-valid bounding boxes fore fore-candidates // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::RemovingInvalidForeRegions(uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo){ +void MultiCue::RemovingInvalidForeRegions(uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo) { int iBoxNum = BoundBoxInfo->m_iBoundBoxNum; - for (int k = 0; k < iBoxNum; k++){ + for (int k = 0; k < iBoxNum; k++) { - if (BoundBoxInfo->m_ValidBox[k] == FALSE){ - for (int i = BoundBoxInfo->m_aRUpper[k]; i < BoundBoxInfo->m_aRBottom[k]; i++){ - for (int j = BoundBoxInfo->m_aRLeft[k]; j < BoundBoxInfo->m_aRRight[k]; j++){ + if (BoundBoxInfo->m_ValidBox[k] == FALSE) { + for (int i = BoundBoxInfo->m_aRUpper[k]; i < BoundBoxInfo->m_aRBottom[k]; i++) { + for (int j = BoundBoxInfo->m_aRLeft[k]; j < BoundBoxInfo->m_aRRight[k]; j++) { if (aResForeMap[i][j] == 255) aResForeMap[i][j] = 0; } } @@ -1134,15 +1139,15 @@ void SJN_MultiCueBGS::RemovingInvalidForeRegions(uchar** aResForeMap, BoundingBo //-----------------------------------------------------------------------------------------------------------------------------------------// // the function returning a foreground binary-map // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::GetForegroundMap(IplImage* return_image, IplImage* input_frame){ +void MultiCue::GetForegroundMap(IplImage* return_image, IplImage* input_frame) { if (g_bForegroundMapEnable == FALSE) return; IplImage* temp_image = cvCreateImage(cvSize(g_iRWidth, g_iRHeight), IPL_DEPTH_8U, 3); - if (input_frame == NULL){ - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + if (input_frame == NULL) { + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { temp_image->imageData[i*temp_image->widthStep + j * 3] = (char)g_aResizedForeMap[i][j]; temp_image->imageData[i*temp_image->widthStep + j * 3 + 1] = (char)g_aResizedForeMap[i][j]; temp_image->imageData[i*temp_image->widthStep + j * 3 + 2] = (char)g_aResizedForeMap[i][j]; @@ -1150,7 +1155,7 @@ void SJN_MultiCueBGS::GetForegroundMap(IplImage* return_image, IplImage* input_f } } - else{ + else { cvResize(input_frame, temp_image); CvScalar MixColor; @@ -1158,8 +1163,8 @@ void SJN_MultiCueBGS::GetForegroundMap(IplImage* return_image, IplImage* input_f MixColor.val[1] = 0; //G MixColor.val[2] = 255; //R - for (int i = 0; i < g_iRHeight; i++){ - for (int j = 0; j < g_iRWidth; j++){ + for (int i = 0; i < g_iRHeight; i++) { + for (int j = 0; j < g_iRWidth; j++) { if (g_aResizedForeMap[i][j] == 255) { @@ -1187,15 +1192,15 @@ void SJN_MultiCueBGS::GetForegroundMap(IplImage* return_image, IplImage* input_f //-----------------------------------------------------------------------------------------------------------------------------------------// // the initialization function for the texture-models // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_AllocateTextureModelRelatedMemory(){ +void MultiCue::T_AllocateTextureModelRelatedMemory() { int i, j, k; //neighborhood system related int iMaxNeighborArraySize = 8; g_aNeighborDirection = (point***)malloc(sizeof(point**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_aNeighborDirection[i] = (point**)malloc(sizeof(point*)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { g_aNeighborDirection[i][j] = (point*)malloc(sizeof(point)*iMaxNeighborArraySize); } } @@ -1204,11 +1209,11 @@ void SJN_MultiCueBGS::T_AllocateTextureModelRelatedMemory(){ //texture-model related int iElementArraySize = 6; g_TextureModel = (TextureModel****)malloc(sizeof(TextureModel***)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_TextureModel[i] = (TextureModel***)malloc(sizeof(TextureModel**)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { g_TextureModel[i][j] = (TextureModel**)malloc(sizeof(TextureModel*)*g_nNeighborNum); - for (k = 0; k < g_nNeighborNum; k++){ + for (k = 0; k < g_nNeighborNum; k++) { g_TextureModel[i][j][k] = (TextureModel*)malloc(sizeof(TextureModel)); g_TextureModel[i][j][k]->m_Codewords = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*iElementArraySize); g_TextureModel[i][j][k]->m_iElementArraySize = iElementArraySize; @@ -1223,16 +1228,16 @@ void SJN_MultiCueBGS::T_AllocateTextureModelRelatedMemory(){ for (i = 0; i < g_iRHeight; i++) g_aTextureConfMap[i] = (float*)malloc(sizeof(float)*g_iRWidth); //cache-book related - if (g_bAbsorptionEnable == TRUE){ + if (g_bAbsorptionEnable == TRUE) { iElementArraySize = iElementArraySize / 2; if (iElementArraySize < 3)iElementArraySize = 3; g_TCacheBook = (TextureModel****)malloc(sizeof(TextureModel***)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_TCacheBook[i] = (TextureModel***)malloc(sizeof(TextureModel**)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { g_TCacheBook[i][j] = (TextureModel**)malloc(sizeof(TextureModel*)*g_nNeighborNum); - for (k = 0; k < g_nNeighborNum; k++){ + for (k = 0; k < g_nNeighborNum; k++) { g_TCacheBook[i][j][k] = (TextureModel*)malloc(sizeof(TextureModel)); g_TCacheBook[i][j][k]->m_Codewords = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*iElementArraySize); g_TCacheBook[i][j][k]->m_iElementArraySize = iElementArraySize; @@ -1245,13 +1250,13 @@ void SJN_MultiCueBGS::T_AllocateTextureModelRelatedMemory(){ g_aTReferredIndex = (short***)malloc(sizeof(short**)*g_iRHeight); g_aTContinuousCnt = (short***)malloc(sizeof(short**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_aTReferredIndex[i] = (short**)malloc(sizeof(short*)*g_iRWidth); g_aTContinuousCnt[i] = (short**)malloc(sizeof(short*)*g_iRWidth); for (j = 0; j < g_iRWidth; j++) { g_aTReferredIndex[i][j] = (short*)malloc(sizeof(short)*g_nNeighborNum); g_aTContinuousCnt[i][j] = (short*)malloc(sizeof(short)*g_nNeighborNum); - for (k = 0; k < g_nNeighborNum; k++){ + for (k = 0; k < g_nNeighborNum; k++) { g_aTReferredIndex[i][j][k] = -1; g_aTContinuousCnt[i][j][k] = 0; } @@ -1262,13 +1267,13 @@ void SJN_MultiCueBGS::T_AllocateTextureModelRelatedMemory(){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the memory release function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_ReleaseTextureModelRelatedMemory(){ +void MultiCue::T_ReleaseTextureModelRelatedMemory() { int i, j, k, m; short nNeighborNum = g_nNeighborNum; - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ - for (k = 0; k < nNeighborNum; k++){ + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { + for (k = 0; k < nNeighborNum; k++) { for (m = 0; m < g_TextureModel[i][j][k]->m_iNumEntries; m++) free(g_TextureModel[i][j][k]->m_Codewords[m]); free(g_TextureModel[i][j][k]->m_Codewords); free(g_TextureModel[i][j][k]); @@ -1278,7 +1283,7 @@ void SJN_MultiCueBGS::T_ReleaseTextureModelRelatedMemory(){ } free(g_TextureModel); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { for (j = 0; j < g_iRWidth; j++) free(g_aNeighborDirection[i][j]); free(g_aNeighborDirection[i]); } @@ -1287,10 +1292,10 @@ void SJN_MultiCueBGS::T_ReleaseTextureModelRelatedMemory(){ for (i = 0; i < g_iRHeight; i++) free(g_aTextureConfMap[i]); free(g_aTextureConfMap); - if (g_bAbsorptionEnable == TRUE){ - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ - for (k = 0; k < nNeighborNum; k++){ + if (g_bAbsorptionEnable == TRUE) { + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { + for (k = 0; k < nNeighborNum; k++) { for (m = 0; m < g_TCacheBook[i][j][k]->m_iNumEntries; m++) free(g_TCacheBook[i][j][k]->m_Codewords[m]); free(g_TCacheBook[i][j][k]->m_Codewords); free(g_TCacheBook[i][j][k]); @@ -1300,8 +1305,8 @@ void SJN_MultiCueBGS::T_ReleaseTextureModelRelatedMemory(){ } free(g_TCacheBook); - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { free(g_aTReferredIndex[i][j]); free(g_aTContinuousCnt[i][j]); } @@ -1317,7 +1322,7 @@ void SJN_MultiCueBGS::T_ReleaseTextureModelRelatedMemory(){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the codebook construction function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningRate, uchar*** aXYZ, point center, point* aNei, TextureModel** aModel){ +void MultiCue::T_ModelConstruction(short nTrainVolRange, float fLearningRate, uchar*** aXYZ, point center, point* aNei, TextureModel** aModel) { int i, j; int iMatchedIndex; @@ -1329,15 +1334,15 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR float fNegLearningRate = 1 - fLearningRate; - //for all neighboring pairs - for (i = 0; i < nNeighborNum; i++){ + //for all neighboring pairs + for (i = 0; i < nNeighborNum; i++) { fDifference = (float)(aXYZ[center.m_nY][center.m_nX][2] - aXYZ[aNei[i].m_nY][aNei[i].m_nX][2]); //Step1: matching iMatchedIndex = -1; - for (j = 0; j < aModel[i]->m_iNumEntries; j++){ - if (aModel[i]->m_Codewords[j]->m_fLowThre <= fDifference && fDifference <= aModel[i]->m_Codewords[j]->m_fHighThre){ + for (j = 0; j < aModel[i]->m_iNumEntries; j++) { + if (aModel[i]->m_Codewords[j]->m_fLowThre <= fDifference && fDifference <= aModel[i]->m_Codewords[j]->m_fHighThre) { iMatchedIndex = j; break; } @@ -1345,12 +1350,12 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR aModel[i]->m_iTotal++; //Step2: adding a new element - if (iMatchedIndex == -1){ + if (iMatchedIndex == -1) { //element array - if (aModel[i]->m_iElementArraySize == aModel[i]->m_iNumEntries){ + if (aModel[i]->m_iElementArraySize == aModel[i]->m_iNumEntries) { aModel[i]->m_iElementArraySize += 5; TextureCodeword **temp = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*aModel[i]->m_iElementArraySize); - for (j = 0; j < aModel[i]->m_iNumEntries; j++){ + for (j = 0; j < aModel[i]->m_iNumEntries; j++) { temp[j] = aModel[i]->m_Codewords[j]; aModel[i]->m_Codewords[j] = NULL; } @@ -1370,7 +1375,7 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR } //Step3: update - else{ + else { fDiffMean = aModel[i]->m_Codewords[iMatchedIndex]->m_fMean; aModel[i]->m_Codewords[iMatchedIndex]->m_fMean = fLearningRate*fDifference + fNegLearningRate*fDiffMean; @@ -1381,10 +1386,10 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR } //cache-book handling - if (aModel[i]->m_bID == 1){ + if (aModel[i]->m_bID == 1) { //1. m_iMNRL update int negTime; - for (j = 0; j < aModel[i]->m_iNumEntries; j++){ + for (j = 0; j < aModel[i]->m_iNumEntries; j++) { //m_iMNRL update negTime = aModel[i]->m_iTotal - aModel[i]->m_Codewords[j]->m_iT_last_time + aModel[i]->m_Codewords[j]->m_iT_first_time - 1; if (aModel[i]->m_Codewords[j]->m_iMNRL < negTime) aModel[i]->m_Codewords[j]->m_iMNRL = negTime; @@ -1395,18 +1400,18 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR if (g_bAbsorptionEnable == TRUE) g_aTReferredIndex[center.m_nY][center.m_nX][i] = -1; } - else{ + else { //1. m_iMNRL update if (iMatchedIndex == -1) aModel[i]->m_Codewords[aModel[i]->m_iNumEntries - 1]->m_iMNRL = 0; //2. g_aTReferredIndex[center.m_nY][center.m_nX][i] update - if (iMatchedIndex == -1){ + if (iMatchedIndex == -1) { g_aTReferredIndex[center.m_nY][center.m_nX][i] = aModel[i]->m_iNumEntries - 1; g_aTContinuousCnt[center.m_nY][center.m_nX][i] = 1; } - else{ + else { if (iMatchedIndex == g_aTReferredIndex[center.m_nY][center.m_nX][i]) g_aTContinuousCnt[center.m_nY][center.m_nX][i]++; - else{ + else { g_aTReferredIndex[center.m_nY][center.m_nX][i] = iMatchedIndex; g_aTContinuousCnt[center.m_nY][center.m_nX][i] = 1; } @@ -1420,7 +1425,7 @@ void SJN_MultiCueBGS::T_ModelConstruction(short nTrainVolRange, float fLearningR //-----------------------------------------------------------------------------------------------------------------------------------------// // Clear non-essential codewords of the given codebook // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_ClearNonEssentialEntries(short nClearNum, TextureModel** aModel){ +void MultiCue::T_ClearNonEssentialEntries(short nClearNum, TextureModel** aModel) { int i, n; int iStaleThresh = (int)(nClearNum*0.5); int iKeepCnt; @@ -1430,7 +1435,7 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntries(short nClearNum, TextureModel** TextureModel* c; - for (n = 0; n < nNeighborNum; n++){ + for (n = 0; n < nNeighborNum; n++) { c = aModel[n]; if (c->m_iTotal < nClearNum) continue; //(being operated only when c[w][h]->m_iTotal == nClearNum) @@ -1441,7 +1446,7 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntries(short nClearNum, TextureModel** iKeepCnt = 0; //Step2: Find non-essential code-words - for (i = 0; i<c->m_iNumEntries; i++){ + for (i = 0; i < c->m_iNumEntries; i++) { if (c->m_Codewords[i]->m_iMNRL > iStaleThresh) { aKeep[i] = 0; //removal candidate } @@ -1452,20 +1457,20 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntries(short nClearNum, TextureModel** } //Step3: Perform removal - if (iKeepCnt == 0 || iKeepCnt == c->m_iNumEntries){ - for (i = 0; i < c->m_iNumEntries; i++){ + if (iKeepCnt == 0 || iKeepCnt == c->m_iNumEntries) { + for (i = 0; i < c->m_iNumEntries; i++) { c->m_Codewords[i]->m_iT_first_time = 1; c->m_Codewords[i]->m_iT_last_time = 1; c->m_Codewords[i]->m_iMNRL = 0; } } - else{ + else { iKeepCnt = 0; TextureCodeword** temp = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*c->m_iNumEntries); - for (i = 0; i < c->m_iNumEntries; i++){ - if (aKeep[i] == 1){ + for (i = 0; i < c->m_iNumEntries; i++) { + if (aKeep[i] == 1) { temp[iKeepCnt] = c->m_Codewords[i]; temp[iKeepCnt]->m_iT_first_time = 1; temp[iKeepCnt]->m_iT_last_time = 1; @@ -1491,21 +1496,21 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntries(short nClearNum, TextureModel** //-----------------------------------------------------------------------------------------------------------------------------------------// // Clear non-essential codewords of the given codebook (only for the cache-book) // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short* nReferredIdxArr, short nClearNum, TextureModel** pCachebook){ +void MultiCue::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short* nReferredIdxArr, short nClearNum, TextureModel** pCachebook) { int i, n; short nNeighborNum = g_nNeighborNum; TextureModel* c; short nReferredIdx; - for (n = 0; n < nNeighborNum; n++){ + for (n = 0; n < nNeighborNum; n++) { c = pCachebook[n]; nReferredIdx = nReferredIdxArr[n]; //pCachebook->m_iTotal < nClearNum? --> MNRL update if (c->m_iTotal < nClearNum) { - for (i = 0; i < c->m_iNumEntries; i++){ + for (i = 0; i < c->m_iNumEntries; i++) { if (bLandmark == 255 && i == nReferredIdx) c->m_Codewords[i]->m_iMNRL = 0; else c->m_Codewords[i]->m_iMNRL++; } @@ -1514,7 +1519,7 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh } //Perform clearing - else{ + else { int iStaleThreshold = 5; int* aKeep; @@ -1523,8 +1528,8 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh aKeep = (int*)malloc(sizeof(int)*c->m_iNumEntries); nKeepCnt = 0; - for (i = 0; i < c->m_iNumEntries; i++){ - if (c->m_Codewords[i]->m_iMNRL < iStaleThreshold){ + for (i = 0; i < c->m_iNumEntries; i++) { + if (c->m_Codewords[i]->m_iMNRL < iStaleThreshold) { aKeep[i] = 1; nKeepCnt++; } @@ -1537,8 +1542,8 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh TextureCodeword** temp = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*c->m_iElementArraySize); nKeepCnt = 0; - for (i = 0; i < c->m_iNumEntries; i++){ - if (aKeep[i] == 1){ + for (i = 0; i < c->m_iNumEntries; i++) { + if (aKeep[i] == 1) { temp[nKeepCnt] = c->m_Codewords[i]; temp[nKeepCnt]->m_iMNRL = 0; nKeepCnt++; @@ -1564,7 +1569,7 @@ void SJN_MultiCueBGS::T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to generate texture confidence maps // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, point*** aNeiDirArr, TextureModel**** aModel){ +void MultiCue::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, point*** aNeiDirArr, TextureModel**** aModel) { int iBound_w = g_iRWidth - g_nRadius; int iBound_h = g_iRHeight - g_nRadius; @@ -1572,10 +1577,10 @@ void SJN_MultiCueBGS::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, short nNeighborNum = g_nNeighborNum; float fPadding = 5; - for (int h = 0; h < g_iRHeight; h++){ - for (int w = 0; w < g_iRWidth; w++){ + for (int h = 0; h < g_iRHeight; h++) { + for (int w = 0; w < g_iRWidth; w++) { - if (h < g_nRadius || h >= iBound_h || w < g_nRadius || w >= iBound_w){ + if (h < g_nRadius || h >= iBound_h || w < g_nRadius || w >= iBound_w) { aTextureMap[h][w] = 0; continue; } @@ -1585,7 +1590,7 @@ void SJN_MultiCueBGS::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, float fDifference; point nei; - for (int i = 0; i < nNeighborNum; i++){ + for (int i = 0; i < nNeighborNum; i++) { nei.m_nX = aNeiDirArr[h][w][i].m_nX; nei.m_nY = aNeiDirArr[h][w][i].m_nY; @@ -1594,8 +1599,8 @@ void SJN_MultiCueBGS::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, if (fDifference < 0) fDiffSum -= fDifference; else fDiffSum += fDifference; - for (int j = 0; j < aModel[h][w][i]->m_iNumEntries; j++){ - if (aModel[h][w][i]->m_Codewords[j]->m_fLowThre - fPadding <= fDifference && fDifference <= aModel[h][w][i]->m_Codewords[j]->m_fHighThre + fPadding){ + for (int j = 0; j < aModel[h][w][i]->m_iNumEntries; j++) { + if (aModel[h][w][i]->m_Codewords[j]->m_fLowThre - fPadding <= fDifference && fDifference <= aModel[h][w][i]->m_Codewords[j]->m_fHighThre + fPadding) { nMatchedCount++; break; } @@ -1609,21 +1614,21 @@ void SJN_MultiCueBGS::T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, //-----------------------------------------------------------------------------------------------------------------------------------------// // Absorbing Ghost Non-background Region Update // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_Absorption(int iAbsorbCnt, point pos, short*** aContinuCnt, short*** aRefferedIndex, TextureModel** pModel, TextureModel** pCache){ +void MultiCue::T_Absorption(int iAbsorbCnt, point pos, short*** aContinuCnt, short*** aRefferedIndex, TextureModel** pModel, TextureModel** pCache) { int i, j, k; int iLeavingIndex; - short g_nRadius = 2; + //short g_nRadius = 2; short nNeighborNum = g_nNeighborNum; - for (i = 0; i < nNeighborNum; i++){ + for (i = 0; i < nNeighborNum; i++) { //set iLeavingIndex if (aContinuCnt[pos.m_nY][pos.m_nX][i] < iAbsorbCnt) continue; iLeavingIndex = aRefferedIndex[pos.m_nY][pos.m_nX][i]; //array expansion - if (pModel[i]->m_iElementArraySize == pModel[i]->m_iNumEntries){ + if (pModel[i]->m_iElementArraySize == pModel[i]->m_iNumEntries) { pModel[i]->m_iElementArraySize = pModel[i]->m_iElementArraySize + 5; TextureCodeword** temp = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*pModel[i]->m_iElementArraySize); for (j = 0; j < pModel[i]->m_iNumEntries; j++) temp[j] = pModel[i]->m_Codewords[j]; @@ -1643,9 +1648,9 @@ void SJN_MultiCueBGS::T_Absorption(int iAbsorbCnt, point pos, short*** aContinuC k = 0; TextureCodeword **temp_Cache = (TextureCodeword**)malloc(sizeof(TextureCodeword*)*pCache[i]->m_iElementArraySize); - for (j = 0; j < pCache[i]->m_iNumEntries; j++){ + for (j = 0; j < pCache[i]->m_iNumEntries; j++) { if (j == iLeavingIndex) continue; - else{ + else { temp_Cache[k] = pCache[i]->m_Codewords[j]; k++; } @@ -1659,7 +1664,7 @@ void SJN_MultiCueBGS::T_Absorption(int iAbsorbCnt, point pos, short*** aContinuC //-----------------------------------------------------------------------------------------------------------------------------------------// // the function to set neighborhood system // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::T_SetNeighborDirection(point*** aNeighborPos){ +void MultiCue::T_SetNeighborDirection(point*** aNeighborPos) { int i, j, k; point* aSearchDirection = (point*)malloc(sizeof(point)*g_nNeighborNum); @@ -1683,9 +1688,9 @@ void SJN_MultiCueBGS::T_SetNeighborDirection(point*** aNeighborPos){ point temp_pos; - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ - for (k = 0; k < g_nNeighborNum; k++){ + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { + for (k = 0; k < g_nNeighborNum; k++) { temp_pos.m_nX = j + aSearchDirection[k].m_nX; temp_pos.m_nY = i + aSearchDirection[k].m_nY; @@ -1707,16 +1712,16 @@ void SJN_MultiCueBGS::T_SetNeighborDirection(point*** aNeighborPos){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the color-model initialization function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_AllocateColorModelRelatedMemory(){ +void MultiCue::C_AllocateColorModelRelatedMemory() { int i, j; int iElementArraySize = 10; //codebook initialization g_ColorModel = (ColorModel***)malloc(sizeof(ColorModel**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_ColorModel[i] = (ColorModel**)malloc(sizeof(ColorModel*)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { //initialization of each CodeBookArray. g_ColorModel[i][j] = (ColorModel*)malloc(sizeof(ColorModel)); g_ColorModel[i][j]->m_Codewords = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*iElementArraySize); @@ -1728,13 +1733,13 @@ void SJN_MultiCueBGS::C_AllocateColorModelRelatedMemory(){ } //cache-book initialization - if (g_bAbsorptionEnable == TRUE){ + if (g_bAbsorptionEnable == TRUE) { iElementArraySize = 3; g_CCacheBook = (ColorModel***)malloc(sizeof(ColorModel**)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_CCacheBook[i] = (ColorModel**)malloc(sizeof(ColorModel*)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { //initialization of each CodeBookArray. g_CCacheBook[i][j] = (ColorModel*)malloc(sizeof(ColorModel)); g_CCacheBook[i][j]->m_Codewords = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*iElementArraySize); @@ -1747,10 +1752,10 @@ void SJN_MultiCueBGS::C_AllocateColorModelRelatedMemory(){ g_aCReferredIndex = (short**)malloc(sizeof(short*)*g_iRHeight); g_aCContinuousCnt = (short**)malloc(sizeof(short*)*g_iRHeight); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { g_aCReferredIndex[i] = (short*)malloc(sizeof(short)*g_iRWidth); g_aCContinuousCnt[i] = (short*)malloc(sizeof(short)*g_iRWidth); - for (j = 0; j < g_iRWidth; j++){ + for (j = 0; j < g_iRWidth; j++) { g_aCReferredIndex[i][j] = -1; g_aCContinuousCnt[i][j] = 0; } @@ -1761,12 +1766,12 @@ void SJN_MultiCueBGS::C_AllocateColorModelRelatedMemory(){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the memory release function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_ReleaseColorModelRelatedMemory(){ +void MultiCue::C_ReleaseColorModelRelatedMemory() { int i, j, k; - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ - for (k = 0; k < g_ColorModel[i][j]->m_iNumEntries; k++){ + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { + for (k = 0; k < g_ColorModel[i][j]->m_iNumEntries; k++) { free(g_ColorModel[i][j]->m_Codewords[k]); } free(g_ColorModel[i][j]->m_Codewords); @@ -1776,10 +1781,10 @@ void SJN_MultiCueBGS::C_ReleaseColorModelRelatedMemory(){ } free(g_ColorModel); - if (g_bAbsorptionEnable == TRUE){ - for (i = 0; i < g_iRHeight; i++){ - for (j = 0; j < g_iRWidth; j++){ - for (k = 0; k < g_CCacheBook[i][j]->m_iNumEntries; k++){ + if (g_bAbsorptionEnable == TRUE) { + for (i = 0; i < g_iRHeight; i++) { + for (j = 0; j < g_iRWidth; j++) { + for (k = 0; k < g_CCacheBook[i][j]->m_iNumEntries; k++) { free(g_CCacheBook[i][j]->m_Codewords[k]); } free(g_CCacheBook[i][j]->m_Codewords); @@ -1789,7 +1794,7 @@ void SJN_MultiCueBGS::C_ReleaseColorModelRelatedMemory(){ } free(g_CCacheBook); - for (i = 0; i < g_iRHeight; i++){ + for (i = 0; i < g_iRHeight; i++) { free(g_aCReferredIndex[i]); free(g_aCContinuousCnt[i]); } @@ -1801,7 +1806,7 @@ void SJN_MultiCueBGS::C_ReleaseColorModelRelatedMemory(){ //-----------------------------------------------------------------------------------------------------------------------------------------// // the codebook construction function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, short nTrainVolRange, float fLearningRate, ColorModel* pC){ +void MultiCue::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, short nTrainVolRange, float fLearningRate, ColorModel* pC) { //Step1: matching short nMatchedIndex; @@ -1810,14 +1815,14 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh nMatchedIndex = -1; - for (int i = 0; i < pC->m_iNumEntries; i++){ + for (int i = 0; i < pC->m_iNumEntries; i++) { //Checking X - if (pC->m_Codewords[i]->m_dMean[0] - nTrainVolRange <= aP[0] && aP[0] <= pC->m_Codewords[i]->m_dMean[0] + nTrainVolRange){ + if (pC->m_Codewords[i]->m_dMean[0] - nTrainVolRange <= aP[0] && aP[0] <= pC->m_Codewords[i]->m_dMean[0] + nTrainVolRange) { //Checking Y - if (pC->m_Codewords[i]->m_dMean[1] - nTrainVolRange <= aP[1] && aP[1] <= pC->m_Codewords[i]->m_dMean[1] + nTrainVolRange){ + if (pC->m_Codewords[i]->m_dMean[1] - nTrainVolRange <= aP[1] && aP[1] <= pC->m_Codewords[i]->m_dMean[1] + nTrainVolRange) { //Checking Z - if (pC->m_Codewords[i]->m_dMean[2] - nTrainVolRange <= aP[2] && aP[2] <= pC->m_Codewords[i]->m_dMean[2] + nTrainVolRange){ + if (pC->m_Codewords[i]->m_dMean[2] - nTrainVolRange <= aP[2] && aP[2] <= pC->m_Codewords[i]->m_dMean[2] + nTrainVolRange) { nMatchedIndex = i; break; } @@ -1828,11 +1833,11 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh pC->m_iTotal = pC->m_iTotal + 1; //Step2 : adding a new element - if (nMatchedIndex == -1){ - if (pC->m_iElementArraySize == pC->m_iNumEntries){ + if (nMatchedIndex == -1) { + if (pC->m_iElementArraySize == pC->m_iNumEntries) { pC->m_iElementArraySize = pC->m_iElementArraySize + 5; ColorCodeword **temp = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*pC->m_iElementArraySize); - for (int j = 0; j < pC->m_iNumEntries; j++){ + for (int j = 0; j < pC->m_iNumEntries; j++) { temp[j] = pC->m_Codewords[j]; pC->m_Codewords[j] = NULL; } @@ -1853,7 +1858,7 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh } //Step3 : update - else{ + else { //m_dMean update pC->m_Codewords[nMatchedIndex]->m_dMean[0] = (fLearningRate*aP[0]) + fNegLearningRate*pC->m_Codewords[nMatchedIndex]->m_dMean[0];//X pC->m_Codewords[nMatchedIndex]->m_dMean[1] = (fLearningRate*aP[1]) + fNegLearningRate*pC->m_Codewords[nMatchedIndex]->m_dMean[1];//Y @@ -1863,10 +1868,10 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh } //cache-book handling - if (pC->m_bID == 1){ + if (pC->m_bID == 1) { //1. m_iMNRL update int iNegTime; - for (int i = 0; i < pC->m_iNumEntries; i++){ + for (int i = 0; i < pC->m_iNumEntries; i++) { //m_iMNRL update iNegTime = pC->m_iTotal - pC->m_Codewords[i]->m_iT_last_time + pC->m_Codewords[i]->m_iT_first_time - 1; if (pC->m_Codewords[i]->m_iMNRL < iNegTime) pC->m_Codewords[i]->m_iMNRL = iNegTime; @@ -1876,18 +1881,18 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh if (g_bAbsorptionEnable == TRUE) g_aCReferredIndex[iPosY][iPosX] = -1; } - else{ + else { //1. m_iMNRL update: if (nMatchedIndex == -1) pC->m_Codewords[pC->m_iNumEntries - 1]->m_iMNRL = 0; //2. g_aCReferredIndex[iPosY][iPosX] update - if (nMatchedIndex == -1){ + if (nMatchedIndex == -1) { g_aCReferredIndex[iPosY][iPosX] = pC->m_iNumEntries - 1; g_aCContinuousCnt[iPosY][iPosX] = 1; } - else{ + else { if (nMatchedIndex == g_aCReferredIndex[iPosY][iPosX]) g_aCContinuousCnt[iPosY][iPosX]++; - else{ + else { g_aCReferredIndex[iPosY][iPosX] = nMatchedIndex; g_aCContinuousCnt[iPosY][iPosX] = 1; } @@ -1898,7 +1903,7 @@ void SJN_MultiCueBGS::C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, sh //-----------------------------------------------------------------------------------------------------------------------------------------// // Clear non-essential codewords of the given codebook // // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_ClearNonEssentialEntries(short nClearNum, ColorModel* pModel){ +void MultiCue::C_ClearNonEssentialEntries(short nClearNum, ColorModel* pModel) { int i; short nStaleThresh = (int)(nClearNum*0.5); short nKeepCnt; @@ -1914,7 +1919,7 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntries(short nClearNum, ColorModel* pM nKeepCnt = 0; //Step2: Find non-essential codewords - for (i = 0; i<pC->m_iNumEntries; i++){ + for (i = 0; i < pC->m_iNumEntries; i++) { if (pC->m_Codewords[i]->m_iMNRL > nStaleThresh) { aKeep[i] = 0; //removal } @@ -1925,19 +1930,19 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntries(short nClearNum, ColorModel* pM } //Step3: Perform removal - if (nKeepCnt == 0 || nKeepCnt == pC->m_iNumEntries){ - for (i = 0; i < pC->m_iNumEntries; i++){ + if (nKeepCnt == 0 || nKeepCnt == pC->m_iNumEntries) { + for (i = 0; i < pC->m_iNumEntries; i++) { pC->m_Codewords[i]->m_iT_first_time = 1; pC->m_Codewords[i]->m_iT_last_time = 1; pC->m_Codewords[i]->m_iMNRL = 0; } } - else{ + else { nKeepCnt = 0; ColorCodeword** temp = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*pC->m_iNumEntries); - for (i = 0; i < pC->m_iNumEntries; i++){ - if (aKeep[i] == 1){ + for (i = 0; i < pC->m_iNumEntries; i++) { + if (aKeep[i] == 1) { temp[nKeepCnt] = pC->m_Codewords[i]; temp[nKeepCnt]->m_iT_first_time = 1; temp[nKeepCnt]->m_iT_last_time = 1; @@ -1962,11 +1967,11 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntries(short nClearNum, ColorModel* pM //-----------------------------------------------------------------------------------------------------------------------------------------// // Clear non-essential codewords of the given codebook (for cache-book) // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short nReferredIdx, short nClearNum, ColorModel* pCachebook){ +void MultiCue::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short nReferredIdx, short nClearNum, ColorModel* pCachebook) { int i; if (pCachebook->m_iTotal < nClearNum) { - for (i = 0; i < pCachebook->m_iNumEntries; i++){ + for (i = 0; i < pCachebook->m_iNumEntries; i++) { if (bLandmark == 255 && i == nReferredIdx) pCachebook->m_Codewords[i]->m_iMNRL = 0; else pCachebook->m_Codewords[i]->m_iMNRL++; } @@ -1974,7 +1979,7 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh pCachebook->m_iTotal++; } - else{ + else { int iStaleThreshold = 5; int* aKeep; @@ -1983,8 +1988,8 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh aKeep = (int*)malloc(sizeof(int)*pCachebook->m_iNumEntries); nKeepCnt = 0; - for (i = 0; i < pCachebook->m_iNumEntries; i++){ - if (pCachebook->m_Codewords[i]->m_iMNRL < iStaleThreshold){ + for (i = 0; i < pCachebook->m_iNumEntries; i++) { + if (pCachebook->m_Codewords[i]->m_iMNRL < iStaleThreshold) { aKeep[i] = 1; nKeepCnt++; } @@ -1997,8 +2002,8 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh ColorCodeword** temp = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*pCachebook->m_iElementArraySize); nKeepCnt = 0; - for (i = 0; i < pCachebook->m_iNumEntries; i++){ - if (aKeep[i] == 1){ + for (i = 0; i < pCachebook->m_iNumEntries; i++) { + if (aKeep[i] == 1) { temp[nKeepCnt] = pCachebook->m_Codewords[i]; temp[nKeepCnt]->m_iMNRL = 0; nKeepCnt++; @@ -2022,7 +2027,7 @@ void SJN_MultiCueBGS::C_ClearNonEssentialEntriesForCachebook(uchar bLandmark, sh //-----------------------------------------------------------------------------------------------------------------------------------------// // the ghost-region absorption function // //-----------------------------------------------------------------------------------------------------------------------------------------// -void SJN_MultiCueBGS::C_Absorption(int iAbsorbCnt, point pos, short** aContinuCnt, short** aRefferedIndex, ColorModel* pModel, ColorModel* pCache){ +void MultiCue::C_Absorption(int iAbsorbCnt, point pos, short** aContinuCnt, short** aRefferedIndex, ColorModel* pModel, ColorModel* pCache) { //set iLeavingIndex if (aContinuCnt[pos.m_nY][pos.m_nX] < iAbsorbCnt) return; @@ -2030,7 +2035,7 @@ void SJN_MultiCueBGS::C_Absorption(int iAbsorbCnt, point pos, short** aContinuCn int iLeavingIndex = aRefferedIndex[pos.m_nY][pos.m_nX]; //array expansion - if (pModel->m_iElementArraySize == pModel->m_iNumEntries){ + if (pModel->m_iElementArraySize == pModel->m_iNumEntries) { pModel->m_iElementArraySize = pModel->m_iElementArraySize + 5; ColorCodeword** temp = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*pModel->m_iElementArraySize); for (int i = 0; i < pModel->m_iNumEntries; i++) temp[i] = pModel->m_Codewords[i]; @@ -2051,9 +2056,9 @@ void SJN_MultiCueBGS::C_Absorption(int iAbsorbCnt, point pos, short** aContinuCn int k = 0; ColorCodeword **pTempCache = (ColorCodeword**)malloc(sizeof(ColorCodeword*)*pCache->m_iElementArraySize); - for (int i = 0; i < pCache->m_iNumEntries; i++){ + for (int i = 0; i < pCache->m_iNumEntries; i++) { if (i == iLeavingIndex) continue; - else{ + else { pTempCache[k] = pCache->m_Codewords[i]; k++; } diff --git a/package_bgs/MultiCue.h b/package_bgs/MultiCue.h new file mode 100644 index 0000000000000000000000000000000000000000..44524e0ab11c7b192cb4a26e0f5875f58749fa9a --- /dev/null +++ b/package_bgs/MultiCue.h @@ -0,0 +1,254 @@ +/* +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 + +#if !defined(__APPLE__) +#include <malloc.h> +#endif +#include "math.h" + +#include <vector> +#include <algorithm> +#include <opencv2/opencv.hpp> + +#include "IBGS.h" + +//------------------------------------Structure Lists-------------------------------------// +namespace bgslibrary +{ + namespace algorithms + { + namespace libMultiCue + { + struct point { + short m_nX; + short m_nY; + }; + + struct neighbor_pos { + short m_nX; + short m_nY; + }; + //1) Bounding Box Structure + struct BoundingBoxInfo { + int m_iBoundBoxNum; //# of bounding boxes for all foreground and false-positive blobs + int m_iArraySize; //the size of the below arrays to store bounding box information + + short *m_aLeft, *m_aRight, *m_aUpper, *m_aBottom; //arrays to store bounding box information for (the original frame size) + short *m_aRLeft, *m_aRRight, *m_aRUpper, *m_aRBottom; //arrays to store bounding box information for (the reduced frame size) + BOOL* m_ValidBox; //If this value is true, the corresponding bounding box is for a foreground blob. + //Else, it is for a false-positive blob + }; + + //2) Texture Model Structure + struct TextureCodeword { + int m_iMNRL; //the maximum negative run-length + int m_iT_first_time; //the first access time + int m_iT_last_time; //the last access time + + float m_fLowThre; //a low threshold for the matching + float m_fHighThre; //a high threshold for the matching + float m_fMean; //mean of the codeword + }; + + struct TextureModel { + TextureCodeword** m_Codewords; //the texture-codeword Array + + int m_iTotal; //# of learned samples after the last clear process + int m_iElementArraySize; //the array size of m_Codewords + int m_iNumEntries; //# of codewords + + BOOL m_bID; //id=1 --> background model, id=0 --> cachebook + }; + + //3) Color Model Structure + struct ColorCodeword { + int m_iMNRL; //the maximum negative run-length + int m_iT_first_time; //the first access time + int m_iT_last_time; //the last access time + + double m_dMean[3]; //mean vector of the codeword + + }; + + struct ColorModel { + ColorCodeword** m_Codewords; //the color-codeword Array + + int m_iTotal; //# of learned samples after the last clear process + int m_iElementArraySize; //the array size of m_Codewords + int m_iNumEntries; //# of codewords + + BOOL m_bID; //id=1 --> background model, id=0 --> cachebookk + }; + } + } +} + +namespace bgslibrary +{ + namespace algorithms + { + using namespace bgslibrary::algorithms::libMultiCue; + + class MultiCue : public IBGS + { + private: + void saveConfig(); + void loadConfig(); + + public: + MultiCue(); + ~MultiCue(); + + public: + //---------------------------------------------------- + // APIs and User-Adjustable Parameters + //---------------------------------------------------- + void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); //the main function to background modeling and subtraction + + void GetForegroundMap(IplImage* return_image, IplImage* input_frame = NULL); //the function returning a foreground binary-map + void Destroy(); //the function to release allocated memories + + int g_iTrainingPeriod; //the training period (The parameter t in the paper) + int g_iT_ModelThreshold; //the threshold for texture-model based BGS. (The parameter tau_T in the paper) + int g_iC_ModelThreshold; //the threshold for appearance based verification. (The parameter tau_A in the paper) + + float g_fLearningRate; //the learning rate for background models. (The parameter alpha in the paper) + + 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 + //---------------------------------------------------- + + //--1) General Functions + void Initialize(IplImage* frame); + + void PreProcessing(IplImage* frame); + void ReduceImageSize(IplImage* SrcImage, IplImage* DstImage); + void GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame); + void BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ); + + void BackgroundModeling_Par(IplImage* frame); + void ForegroundExtraction(IplImage* frame); + void CreateLandmarkArray_Par(float fConfThre, short nTrainVolRange, float**aConfMap, int iNehborNum, uchar*** aXYZ, + point*** aNeiDir, TextureModel**** TModel, ColorModel*** CModel, uchar**aLandmarkArr); + + void PostProcessing(IplImage* frame); + void MorphologicalOpearions(uchar** aInput, uchar** aOutput, double dThresholdRatio, int iMaskSize, int iWidth, int iHeight); + void Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLabelTable); + void SetBoundingBox(int iLabelCount, int** aLabelTable); + void BoundBoxVerification(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); + void EvaluateBoxSize(BoundingBoxInfo* BoundBoxInfo); + void EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo); + void EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); + double CalculateHausdorffDist(IplImage* input_image, IplImage* model_image); + void RemovingInvalidForeRegions(uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); + + void UpdateModel_Par(); + void GetEnlargedMap(float** aOriginMap, float** aEnlargedMap); + + //--2) Texture Model Related Functions + void T_AllocateTextureModelRelatedMemory(); + void T_ReleaseTextureModelRelatedMemory(); + void T_SetNeighborDirection(point*** aNeighborPos); + void T_ModelConstruction(short nTrainVolRange, float fLearningRate, uchar*** aXYZ, point center, point* aNei, TextureModel** aModel); + void T_ClearNonEssentialEntries(short nClearNum, TextureModel** aModel); + void T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short* nReferredIdxArr, short nClearNum, TextureModel** pCachebook); + void T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, point*** aNeiDirArr, TextureModel**** aModel); + void T_Absorption(int iAbsorbCnt, point pos, short*** aContinuCnt, short*** aRefferedIndex, TextureModel** pModel, TextureModel** pCache); + + //--3) Color Model Related Functions + void C_AllocateColorModelRelatedMemory(); + void C_ReleaseColorModelRelatedMemory(); + void C_CodebookConstruction(uchar* aP, int iPosX, int iPosY, short nTrainVolRange, float fLearningRate, ColorModel* pC); + 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 + //---------------------------------------------------- + + //--1) General Variables + int g_iFrameCount; //the counter of processed frames + + int g_iBackClearPeriod; //the period to clear background models + int g_iCacheClearPeriod; //the period to clear cache-book models + + int g_iAbsortionPeriod; //the period to absorb static ghost regions + BOOL g_bAbsorptionEnable; //If True, procedures for ghost region absorption are activated. + + BOOL g_bModelMemAllocated; //To handle memory.. + BOOL g_bNonModelMemAllocated; //To handle memory.. + + float g_fConfidenceThre; //the final decision threshold + + int g_iWidth, g_iHeight; //width and height of input frames + int g_iRWidth, g_iRHeight; //width and height of reduced frames (For efficiency, the reduced size of frames are processed) + int g_iForegroundNum; //# of detected foreground regions + BOOL g_bForegroundMapEnable; //TRUE only when BGS is successful + + IplImage* g_ResizedFrame; //reduced size of frame (For efficiency, the reduced size of frames are processed) + uchar*** g_aGaussFilteredFrame; + uchar*** g_aXYZFrame; + uchar** g_aLandmarkArray; //the landmark map + uchar** g_aResizedForeMap; //the resized foreground map + uchar** g_aForegroundMap; //the final foreground map + BOOL** g_aUpdateMap; //the location map of update candidate pixels + + BoundingBoxInfo* g_BoundBoxInfo; //the array of bounding boxes of each foreground blob + + //--2) Texture Model Related + TextureModel**** g_TextureModel; //the texture background model + TextureModel**** g_TCacheBook; //the texture cache-book + short*** g_aTReferredIndex; //To handle cache-book + short*** g_aTContinuousCnt; //To handle cache-book + point*** g_aNeighborDirection; + float**g_aTextureConfMap; //the texture confidence map + + short g_nNeighborNum; //# of neighborhoods + short g_nRadius; + short g_nBoundarySize; + + //--3) Texture Model Related + ColorModel*** g_ColorModel; //the color background model + ColorModel*** g_CCacheBook; //the color cache-book + short** g_aCReferredIndex; //To handle cache-book + short** g_aCContinuousCnt; //To handle cache-book + }; + } +} diff --git a/package_bgs/jmo/MultiLayerBGS.cpp b/package_bgs/MultiLayer.cpp similarity index 65% rename from package_bgs/jmo/MultiLayerBGS.cpp rename to package_bgs/MultiLayer.cpp index 03e223f1f49e44816af126238d5a50f3217883f4..180d88d74a7fdded44fd4700038d3dbbe0ac9ade 100644 --- a/package_bgs/jmo/MultiLayerBGS.cpp +++ b/package_bgs/MultiLayer.cpp @@ -14,36 +14,40 @@ 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 "MultiLayerBGS.h" +#include "MultiLayer.h" -MultiLayerBGS::MultiLayerBGS() : firstTime(true), frameNumber(0), showOutput(true), -saveModel(false), disableDetectMode(true), disableLearning(false), detectAfter(0), bg_model_preload(""), loadDefaultParams(true) +using namespace bgslibrary::algorithms; + +MultiLayer::MultiLayer() : + frameNumber(0), saveModel(false), disableDetectMode(true), disableLearning(false), + detectAfter(0), bg_model_preload(""), loadDefaultParams(true) { - std::cout << "MultiLayerBGS()" << std::endl; + std::cout << "MultiLayer()" << std::endl; + setup("./config/MultiLayer.xml"); } -MultiLayerBGS::~MultiLayerBGS() +MultiLayer::~MultiLayer() { finish(); - std::cout << "~MultiLayerBGS()" << std::endl; + std::cout << "~MultiLayer()" << std::endl; } -void MultiLayerBGS::setStatus(Status _status) +void MultiLayer::setStatus(Status _status) { status = _status; } -void MultiLayerBGS::finish(void) +void MultiLayer::finish() { if (bg_model_preload.empty()) { - bg_model_preload = "./models/MultiLayerBGSModel.yml"; + bg_model_preload = "./MultiLayerModel.yml"; saveConfig(); } if (status == MLBGS_LEARN && saveModel == true) { - std::cout << "MultiLayerBGS saving background model: " << bg_model_preload << std::endl; + std::cout << "MultiLayer saving background model: " << bg_model_preload << std::endl; BGS->Save(bg_model_preload.c_str()); } @@ -57,13 +61,9 @@ void MultiLayerBGS::finish(void) delete BGS; } -void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void MultiLayer::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if (img_input.empty()) - return; - - loadConfig(); - + 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) @@ -72,10 +72,10 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M status = MLBGS_LEARN; if (status == MLBGS_LEARN) - std::cout << "MultiLayerBGS in LEARN mode" << std::endl; + std::cout << "MultiLayer in LEARN mode" << std::endl; if (status == MLBGS_DETECT) - std::cout << "MultiLayerBGS in DETECT mode" << std::endl; + std::cout << "MultiLayer in DETECT mode" << std::endl; org_img = new IplImage(img_input); @@ -93,7 +93,7 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M if (bg_model_preload.empty() == false) { - std::cout << "MultiLayerBGS loading background model: " << bg_model_preload << std::endl; + std::cout << "MultiLayer loading background model: " << bg_model_preload << std::endl; BGS->Load(bg_model_preload.c_str()); } @@ -102,14 +102,14 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M BGS->m_disableLearning = disableLearning; if (disableLearning) - std::cout << "MultiLayerBGS disabled learning in DETECT mode" << std::endl; + std::cout << "MultiLayer disabled learning in DETECT mode" << std::endl; else - std::cout << "MultiLayerBGS enabled learning in DETECT mode" << std::endl; + std::cout << "MultiLayer enabled learning in DETECT mode" << std::endl; } if (loadDefaultParams) { - std::cout << "MultiLayerBGS loading default params" << std::endl; + std::cout << "MultiLayer loading default params" << std::endl; max_mode_num = 5; weight_updating_constant = 5.0; @@ -127,7 +127,7 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M bilater_filter_sigma_r = 0.1f; } else - std::cout << "MultiLayerBGS loading config params" << std::endl; + std::cout << "MultiLayer loading config params" << std::endl; BGS->m_nMaxLBPModeNum = max_mode_num; BGS->m_fWeightUpdatingConstant = weight_updating_constant; @@ -186,9 +186,6 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M } BGS->SetParameters(max_mode_num, mode_learn_rate_per_second, weight_learn_rate_per_second, init_mode_weight); - - saveConfig(); - delete org_img; } @@ -199,7 +196,7 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M if (detectAfter > 0 && detectAfter == frameNumber) { - std::cout << "MultiLayerBGS in DETECT mode" << std::endl; + std::cout << "MultiLayer in DETECT mode" << std::endl; status = MLBGS_DETECT; @@ -212,9 +209,9 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M BGS->m_disableLearning = disableLearning; if (disableLearning) - std::cout << "MultiLayerBGS disabled learning in DETECT mode" << std::endl; + std::cout << "MultiLayer disabled learning in DETECT mode" << std::endl; else - std::cout << "MultiLayerBGS enabled learning in DETECT mode" << std::endl; + std::cout << "MultiLayer enabled learning in DETECT mode" << std::endl; } IplImage* img = new IplImage(img_input); @@ -228,15 +225,17 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M BGS->GetForegroundMaskImage(fg_mask_img); BGS->MergeImages(4, img, bg_img, fg_prob_img3, fg_img, merged_img); - img_merged = cv::Mat(merged_img); - img_foreground = cv::Mat(fg_mask_img); - img_background = cv::Mat(bg_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); @@ -248,9 +247,9 @@ void MultiLayerBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::M frameNumber++; } -void MultiLayerBGS::saveConfig() +void MultiLayer::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MultiLayerBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteString(fs, "preloadModel", bg_model_preload.c_str()); cvWriteInt(fs, "saveModel", saveModel); @@ -289,43 +288,43 @@ void MultiLayerBGS::saveConfig() cvReleaseFileStorage(&fs); } -void MultiLayerBGS::loadConfig() +void MultiLayer::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/MultiLayerBGS.xml", 0, CV_STORAGE_READ); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); - bg_model_preload = cvReadStringByName(fs, 0, "preloadModel", ""); - saveModel = cvReadIntByName(fs, 0, "saveModel", false); - detectAfter = cvReadIntByName(fs, 0, "detectAfter", 0); - disableDetectMode = cvReadIntByName(fs, 0, "disableDetectMode", true); - disableLearning = cvReadIntByName(fs, 0, "disableLearningInDetecMode", false); - loadDefaultParams = cvReadIntByName(fs, 0, "loadDefaultParams", true); + 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, 0, "max_mode_num", 5); + 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, 0, "texture_weight", 0.5); - bg_mode_percent = cvReadRealByName(fs, 0, "bg_mode_percent", 0.6); - pattern_neig_half_size = cvReadIntByName(fs, 0, "pattern_neig_half_size", 4); - pattern_neig_gaus_sigma = cvReadRealByName(fs, 0, "pattern_neig_gaus_sigma", 3.0); - bg_prob_threshold = cvReadRealByName(fs, 0, "bg_prob_threshold", 0.2); - bg_prob_updating_threshold = cvReadRealByName(fs, 0, "bg_prob_updating_threshold", 0.2); - robust_LBP_constant = cvReadIntByName(fs, 0, "robust_LBP_constant", 3); - min_noised_angle = cvReadRealByName(fs, 0, "min_noised_angle", 0.01768); - shadow_rate = cvReadRealByName(fs, 0, "shadow_rate", 0.6); - highlight_rate = cvReadRealByName(fs, 0, "highlight_rate", 1.2); - bilater_filter_sigma_s = cvReadRealByName(fs, 0, "bilater_filter_sigma_s", 3.0); - bilater_filter_sigma_r = cvReadRealByName(fs, 0, "bilater_filter_sigma_r", 0.1); - - frame_duration = cvReadRealByName(fs, 0, "frame_duration", 0.1); - - learn_mode_learn_rate_per_second = cvReadRealByName(fs, 0, "learn_mode_learn_rate_per_second", 0.5); - learn_weight_learn_rate_per_second = cvReadRealByName(fs, 0, "learn_weight_learn_rate_per_second", 0.5); - learn_init_mode_weight = cvReadRealByName(fs, 0, "learn_init_mode_weight", 0.05); - - detect_mode_learn_rate_per_second = cvReadRealByName(fs, 0, "detect_mode_learn_rate_per_second", 0.01); - detect_weight_learn_rate_per_second = cvReadRealByName(fs, 0, "detect_weight_learn_rate_per_second", 0.01); - detect_init_mode_weight = cvReadRealByName(fs, 0, "detect_init_mode_weight", 0.001); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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.h b/package_bgs/MultiLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..af7e128c9c8230653486bc5d1673405034e0eab8 --- /dev/null +++ b/package_bgs/MultiLayer.h @@ -0,0 +1,99 @@ +/* +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 "MultiLayer/CMultiLayerBGS.h" + +namespace bgslibrary +{ + namespace algorithms + { + class MultiLayer : public IBGS + { + public: + enum Status + { + MLBGS_NONE = -1, + MLBGS_LEARN = 0, + MLBGS_DETECT = 1 + }; + + private: + long long frameNumber; + cv::Mat img_merged; + bool saveModel; + bool disableDetectMode; + bool disableLearning; + int detectAfter; + CMultiLayerBGS* BGS; + Status status; + IplImage* img; + IplImage* org_img; + IplImage* fg_img; + IplImage* bg_img; + IplImage* fg_prob_img; + IplImage* fg_mask_img; + IplImage* fg_prob_img3; + IplImage* merged_img; + std::string bg_model_preload; + + bool loadDefaultParams; + + int max_mode_num; + float weight_updating_constant; + float texture_weight; + float bg_mode_percent; + int pattern_neig_half_size; + float pattern_neig_gaus_sigma; + float bg_prob_threshold; + float bg_prob_updating_threshold; + int robust_LBP_constant; + float min_noised_angle; + float shadow_rate; + float highlight_rate; + float bilater_filter_sigma_s; + float bilater_filter_sigma_r; + + float frame_duration; + + float mode_learn_rate_per_second; + float weight_learn_rate_per_second; + float init_mode_weight; + + float learn_mode_learn_rate_per_second; + float learn_weight_learn_rate_per_second; + float learn_init_mode_weight; + + float detect_mode_learn_rate_per_second; + float detect_weight_learn_rate_per_second; + float detect_init_mode_weight; + + public: + MultiLayer(); + ~MultiLayer(); + + void setStatus(Status status); + void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); + + private: + void finish(); + void saveConfig(); + void loadConfig(); + }; + } +} diff --git a/package_bgs/jmo/BGS.h b/package_bgs/MultiLayer/BGS.h similarity index 98% rename from package_bgs/jmo/BGS.h rename to package_bgs/MultiLayer/BGS.h index c506df2ba9a6e4fa68f821fd92be2a2cbc771ed5..ad2129bccbfdfbce8164925eddfee7aef07853fb 100644 --- a/package_bgs/jmo/BGS.h +++ b/package_bgs/MultiLayer/BGS.h @@ -40,10 +40,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if !defined(_BGS_H_) -#define _BGS_H_ +#pragma once -#include <opencv2/opencv.hpp> +#include "OpenCvLegacyIncludes.h" // TODO check these defines are not used (or not redundant with real params) @@ -211,6 +210,3 @@ class IMAGE_BG_MODEL delete[] pixel_PATTERNs; } }; - - -#endif // !defined(_BGS_H_) diff --git a/package_bgs/jmo/BackgroundSubtractionAPI.h b/package_bgs/MultiLayer/BackgroundSubtractionAPI.h similarity index 89% rename from package_bgs/jmo/BackgroundSubtractionAPI.h rename to package_bgs/MultiLayer/BackgroundSubtractionAPI.h index bb396119623dc9a794821b395e46af5c4adcd366..409fa4049d2cda20f7c92506e90e16bc60e5cfed 100644 --- a/package_bgs/jmo/BackgroundSubtractionAPI.h +++ b/package_bgs/MultiLayer/BackgroundSubtractionAPI.h @@ -60,12 +60,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // char image for the output // ////////////////////////////////////////////////////////////////////// +#pragma once - -#if !defined(_BACKGROUND_SUBTRACTION_API_H_) -#define _BACKGROUND_SUBTRACTION_API_H_ - -#include <opencv2/opencv.hpp> +#include "OpenCvLegacyIncludes.h" class CBackgroundSubtractionAPI { @@ -79,14 +76,14 @@ public: void Init(int width, int height); //------------------------------------------------------------- - // PROVIDE A MASK TO DEFINE THE SET OF POINTS WHERE BACKGROUND + // 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 + // + // 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 - // + // 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 @@ -96,12 +93,12 @@ public: 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 + // the time interval during the last processed frame // // frameDuration is in millisecond void SetFrameRate(float frameDuration); @@ -113,31 +110,31 @@ public: // 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 + // 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 + // 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 + // 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. + // otherwise the return value is 0. // int Process(); @@ -150,9 +147,7 @@ public: //------------------------------------------------------------- // this function should load the parameters necessary - // for the processing of the background subtraction or + // for the processing of the background subtraction or // load background model information void Load(char *bg_model_fn); }; - -#endif // !defined(_BACKGROUND_SUBTRACTION_API_H_) diff --git a/package_bgs/jmo/BlobExtraction.cpp b/package_bgs/MultiLayer/BlobExtraction.cpp similarity index 91% rename from package_bgs/jmo/BlobExtraction.cpp rename to package_bgs/MultiLayer/BlobExtraction.cpp index 81857eb671e7432dd16e7fc048f52cb648ca5e55..7aecd65b2577f162333674f84c5263f7a0c32128 100644 --- a/package_bgs/jmo/BlobExtraction.cpp +++ b/package_bgs/MultiLayer/BlobExtraction.cpp @@ -55,47 +55,47 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. //! 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 +//! 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 +//! 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 +// color dels píxels de la màscara per ser exteriors #define PIXEL_EXTERIOR 0 #include "BlobResult.h" #include "BlobExtraction.h" -#include <opencv2/legacy/compat.hpp> +#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 - */ + - 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, @@ -151,13 +151,13 @@ namespace Blob if (!CV_IS_IMAGE(inputImage) || !CV_IS_IMAGE(maskImage)) return false; - // comprova que la m�scara tingui les mateixes dimensions que la imatge + // 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) + // comprova que la màscara sigui una imatge d'un sol canal (grayscale) if (maskImage->nChannels != 1) { return false; @@ -167,16 +167,16 @@ namespace Blob // Initialize Transition array Transition = new int[(Rows + 2)*(Cols + 2)]; - memset(Transition, 0, (Rows + 2) * (Cols + 2)*sizeof(int)); + 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 ) - */ + 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; @@ -184,7 +184,7 @@ namespace Blob //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 + 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; @@ -218,12 +218,12 @@ namespace Blob } else { - //maskImage not NULL: Cal rec�rrer la m�scara tamb� per calcular la matriu de transicions + //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 + // creem la imatge que contindrà el perimetre extern de cada pixel imatgePerimetreExtern = cvCreateImage(cvSize(maskImage->width, maskImage->height), IPL_DEPTH_8U, 1); cvSetZero(imatgePerimetreExtern); @@ -255,9 +255,9 @@ namespace Blob } /*//////////////////////////////////////////////////////////////////////// - Calcul de la imatge amb els pixels externs - ////////////////////////////////////////////////////////////////////////*/ - // pels pixels externs no cal calcular res pq no hi accedir-hem + 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) @@ -277,7 +277,7 @@ namespace Blob // pixels a l'est i oest de l'actual if (iRow < imatgePerimetreExtern->height) { - if ((iCol>0) && (*(pMask - 1) == PIXEL_EXTERIOR)) perimeter++; + if ((iCol > 0) && (*(pMask - 1) == PIXEL_EXTERIOR)) perimeter++; if ((iCol < imatgePerimetreExtern->width - 1) && (*(pMask + 1) == PIXEL_EXTERIOR)) perimeter++; } @@ -323,7 +323,7 @@ namespace Blob // 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 @@ -409,7 +409,7 @@ namespace Blob uchar imagevalue; bool CandidatExterior = false; - // apuntadors als blobs de la regi� actual i last + // apuntadors als blobs de la regió actual i last CBlob *regionDataThisRegion, *regionDataLastRegion; LastRegion = new int[Cols + 2]; @@ -431,7 +431,7 @@ namespace Blob ThisIndexCount = 1; ThisRegion[0] = 0; // Border region - // beginning of the image + // 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 @@ -457,9 +457,9 @@ namespace Blob { int Index = ThisOffset + j; int TranVal = Transition[Index]; - if (TranVal > 0) ThisIndexCount = j + 1; // stop at highest + if (TranVal > 0) ThisIndexCount = j + 1; // stop at highest - if (ThisRegion[j] == -1) { EndLast = 1; } + if (ThisRegion[j] == -1) { EndLast = 1; } if (TranVal < 0) { EndThis = 1; } if (EndLast > 0 && EndThis > 0) { break; } @@ -505,7 +505,7 @@ namespace Blob #endif #if !IMATGE_CICLICA_HORITZONTAL ThisStart <= 1 || ThisEnd >= Cols || -#endif +#endif GetExternPerimeter(ThisStart, ThisEnd, ThisRow, inputImage->width, inputImage->height, imatgePerimetreExtern) ) { @@ -601,7 +601,7 @@ namespace Blob //afegim la cantonada a ThisRegion if (ThisRegionNum != -1) { - // afegim dos vertexs si s�n diferents, nom�s + // afegim dos vertexs si són diferents, només if (ThisStart - 1 != ThisEnd) { actualedge.x = ThisStart - 1; @@ -615,7 +615,7 @@ namespace Blob //afegim la cantonada a ThisRegion if (LastRegionNum != -1 && LastRegionNum != ThisRegionNum) { - // afegim dos vertexs si s�n diferents, nom�s + // afegim dos vertexs si són diferents, només if (ThisStart - 1 != ThisEnd) { actualedge.x = ThisStart - 1; @@ -662,8 +662,8 @@ namespace Blob SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum); if (CandidatExterior) ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow, - inputImage->width, inputImage->height, - imatgePerimetreExtern); + inputImage->width, inputImage->height, + imatgePerimetreExtern); } @@ -728,8 +728,8 @@ namespace Blob SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum); if (CandidatExterior) ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow, - inputImage->width, inputImage->height, - imatgePerimetreExtern); + inputImage->width, inputImage->height, + imatgePerimetreExtern); } @@ -789,8 +789,8 @@ namespace Blob SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum); if (CandidatExterior) ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow, - inputImage->width, inputImage->height, - imatgePerimetreExtern); + inputImage->width, inputImage->height, + imatgePerimetreExtern); } else if (TestMatch && !TestKnown) // Same color and unknown @@ -986,8 +986,8 @@ namespace Blob SubsumedRegion = NewSubsume(SubsumedRegion, HighRegionNum); if (CandidatExterior) ThisExternPerimeter = GetExternPerimeter(ThisStart, ThisEnd, ThisRow, - inputImage->width, inputImage->height, - imatgePerimetreExtern); + inputImage->width, inputImage->height, + imatgePerimetreExtern); } else if (TestMatch && !TestKnown) @@ -1077,7 +1077,7 @@ namespace Blob //|yyyy | #ifdef B_CONNECTIVITAT_8 - // fusionem blobs + // fusionem blobs if (TestMatch) { if (ThisRegionNum > LastRegionNum) @@ -1159,7 +1159,7 @@ namespace Blob } - // compute the mean gray level and its std deviation + // compute the mean gray level and its std deviation if (ThisRow <= Rows) { pImageAux = pImage + ThisStart; @@ -1170,9 +1170,9 @@ namespace Blob { 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) + // 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); @@ -1200,7 +1200,7 @@ namespace Blob // 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 (ThisEnd > (int) ThisMaxX) ThisMaxX = (float)ThisEnd; if (ThisRow - 1 < ThisMinY) ThisMinY = ThisRow - 1; if (ThisMinY < (float) 0.0) ThisMinY = (float) 0.0; @@ -1242,10 +1242,10 @@ namespace Blob } // end Main loop if (ErrorFlag != 0) { - delete[] Transition; - delete[] ThisRegion; - delete[] LastRegion; - return false; + 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; @@ -1254,19 +1254,19 @@ namespace Blob 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 + // 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 + // 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) + // 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...) + // (segurament no és del tot acurat) + // (i amb les màscares encara menys...) RegionData[0]->perimeter -= 8.0; // Condense the list @@ -1306,7 +1306,7 @@ namespace Blob if (findmoments) { iti = RegionData.begin(); - // Normalize summation fields into moments + // Normalize summation fields into moments for (ThisRegionNum = 0; ThisRegionNum <= HighRegionNum; ThisRegionNum++, iti++) { blobActual = *iti; @@ -1340,10 +1340,10 @@ namespace Blob blobActual->stddev = sqrt( ( - blobActual->stddev * blobActual->area - - blobActual->mean * blobActual->mean - ) / - (blobActual->area*(blobActual->area - 1)) + blobActual->stddev * blobActual->area - + blobActual->mean * blobActual->mean + ) / + (blobActual->area*(blobActual->area - 1)) ); } else @@ -1385,16 +1385,16 @@ namespace Blob } else { - subsumed = (int*)realloc(subsumed, (index_subsume + 1)*sizeof(int)); + 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] - */ + 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, @@ -1440,28 +1440,28 @@ namespace Blob // marquem el blob com a lliure blobHi->etiqueta = -1; - // Atenci�!!!! abans d'eliminar els edges + // 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�. - */ + - 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; @@ -1474,7 +1474,7 @@ namespace Blob if (row >= height - 1) perimeter += start - end; - // comprovem els pixels que toquen a la m�scara (si s'escau) + // comprovem els pixels que toquen a la màscara (si s'escau) if (imatgePerimetreExtern != NULL) { if (row <= 0 || row >= height) return perimeter; diff --git a/package_bgs/jmo/BlobExtraction.h b/package_bgs/MultiLayer/BlobExtraction.h similarity index 96% rename from package_bgs/jmo/BlobExtraction.h rename to package_bgs/MultiLayer/BlobExtraction.h index 9f47b02ad12efeba33657764544211706233c144..d8bd1af5dc762d0434311e0f6bac9c373b7af64f 100644 --- a/package_bgs/jmo/BlobExtraction.h +++ b/package_bgs/MultiLayer/BlobExtraction.h @@ -49,10 +49,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. //* Email: dgrossman@cdr.stanford.edu *// //* Acknowledgement: the algorithm has been around > 20 yrs *// //***********************************************************// - - -#if !defined(_CLASSE_BLOBEXTRACTION_INCLUDED) -#define _CLASSE_BLOBEXTRACTION_INCLUDED +#pragma once namespace Blob { @@ -71,6 +68,3 @@ namespace Blob //! Retorna el perimetre extern d'una run lenght double GetExternPerimeter(int start, int end, int row, int width, int height, IplImage *maskImage); } - -#endif //_CLASSE_BLOBEXTRACTION_INCLUDED - diff --git a/package_bgs/jmo/BlobLibraryConfiguration.h b/package_bgs/MultiLayer/BlobLibraryConfiguration.h similarity index 95% rename from package_bgs/jmo/BlobLibraryConfiguration.h rename to package_bgs/MultiLayer/BlobLibraryConfiguration.h index b864fc76dae998fc301eacf20b59b907220b43f3..0ba18fc3ac1d846e054a17ab9087915e9a50d2b8 100644 --- a/package_bgs/jmo/BlobLibraryConfiguration.h +++ b/package_bgs/MultiLayer/BlobLibraryConfiguration.h @@ -43,15 +43,16 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. /************************************************************************ BlobLibraryConfiguration.h -FUNCIONALITAT: Configuraci� del comportament global de la llibreria +FUNCIONALITAT: Configuració del comportament global de la llibreria AUTOR: Inspecta S.L. -MODIFICACIONS (Modificaci�, Autor, Data): +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 diff --git a/package_bgs/MultiLayer/BlobResult.cpp b/package_bgs/MultiLayer/BlobResult.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ec60e35e0ddc24dbef325abb7f9b9fffa5e7633 --- /dev/null +++ b/package_bgs/MultiLayer/BlobResult.cpp @@ -0,0 +1,847 @@ +/* +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/jmo/BlobResult.h b/package_bgs/MultiLayer/BlobResult.h similarity index 80% rename from package_bgs/jmo/BlobResult.h rename to package_bgs/MultiLayer/BlobResult.h index b232a978d03b748d6d58df0b80c593d26dc757ad..aa3e37b31c12998d96a91c3493f25557ad4e5a32 100644 --- a/package_bgs/jmo/BlobResult.h +++ b/package_bgs/MultiLayer/BlobResult.h @@ -40,29 +40,26 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * (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 + /************************************************************************ + BlobResult.h - FUNCIONALITAT: Definici� de la classe CBlobResult - AUTOR: Inspecta S.L. - MODIFICACIONS (Modificaci�, Autor, Data): + 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): + FUNCTIONALITY: Definition of the CBlobResult class + AUTHOR: Inspecta S.L. + MODIFICATIONS (Modification, Author, Date): - **************************************************************************/ + **************************************************************************/ #pragma once -#if !defined(_CLASSE_BLOBRESULT_INCLUDED) -#define _CLASSE_BLOBRESULT_INCLUDED - #include "BlobLibraryConfiguration.h" #include <math.h> -//#include "cxcore.h" + //#include "cxcore.h" #include <vector> #include <functional> -#include <opencv2/core/types_c.h> +#include "OpenCvLegacyIncludes.h" #include "blob.h" typedef std::vector<double> double_stl_vector; @@ -71,8 +68,8 @@ 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) + //! 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 @@ -92,23 +89,23 @@ typedef std::vector<double> double_stl_vector; Excepcions / Exceptions **************************************************************************/ -//! Excepcions llen�ades per les funcions: + //! 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 + //! 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. - */ + 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: @@ -119,7 +116,7 @@ namespace Blob //! 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 + //! constructor de còpia //! Copy constructor CBlobResult(const CBlobResult &source); //! Destructor @@ -139,7 +136,7 @@ namespace 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; + 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 @@ -149,17 +146,17 @@ namespace Blob //! 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 + //! 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 + //! 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 + //! Retorna el blob enèssim //! Gets the n-th blob of the class ( without sorting ) CBlob GetBlob(int indexblob) const; CBlob *GetBlob(int indexblob); @@ -185,7 +182,7 @@ namespace Blob private: - //! Funci� per gestionar els errors + //! Funció per gestionar els errors //! Function to manage the errors void RaiseError(const int errorCode) const; @@ -197,6 +194,3 @@ namespace Blob }; } - -#endif // !defined(_CLASSE_BLOBRESULT_INCLUDED) - diff --git a/package_bgs/jmo/CMultiLayerBGS.cpp b/package_bgs/MultiLayer/CMultiLayerBGS.cpp similarity index 99% rename from package_bgs/jmo/CMultiLayerBGS.cpp rename to package_bgs/MultiLayer/CMultiLayerBGS.cpp index 6daa9b9bf1480194166cc131ca4dc9ddde20f9a0..43417361cff3902bc8bf8bdfa0ba2a2f20c8b1b1 100644 --- a/package_bgs/jmo/CMultiLayerBGS.cpp +++ b/package_bgs/MultiLayer/CMultiLayerBGS.cpp @@ -53,7 +53,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <fstream> // file I/O #include <cmath> // math includes #include <iostream> // I/O streams -#include <opencv2/legacy/compat.hpp> +#include "OpenCvLegacyIncludes.h" using namespace Blob; @@ -220,16 +220,16 @@ void CMultiLayerBGS::MergeImages(int num, ...) { int img_idx = 0; for (a = 0; a < nRows; a++) - for (b = 0; b < nCols; b++) { - if (img_idx >= num) - break; + for (b = 0; b < nCols; b++) { + if (img_idx >= num) + break; - imgROIRect = cvRect(b * imgSize.width, a * imgSize.height, imgSize.width, imgSize.height); + imgROIRect = cvRect(b * imgSize.width, a * imgSize.height, imgSize.width, imgSize.height); - cvSetImageROI(ppIplImg[num], imgROIRect); - cvCopyImage(ppIplImg[img_idx++], ppIplImg[num]); - cvResetImageROI(ppIplImg[num]); - } + cvSetImageROI(ppIplImg[num], imgROIRect); + cvCopy(ppIplImg[img_idx++], ppIplImg[num]); + cvResetImageROI(ppIplImg[num]); + } delete[] ppIplImg; } @@ -369,7 +369,7 @@ void CMultiLayerBGS::SetBkMaskImage(IplImage *mask_img) { if (m_pBkMaskImg == NULL) { m_pBkMaskImg = cvCreateImage(cvGetSize(mask_img), mask_img->depth, mask_img->nChannels); } - cvCopyImage(mask_img, m_pBkMaskImg); + cvCopy(mask_img, m_pBkMaskImg); } void CMultiLayerBGS::BackgroundSubtractionProcess() { @@ -691,7 +691,7 @@ void CMultiLayerBGS::BackgroundSubtractionProcess() { removed_modes[a] = false; if (LBPs[lbp_idxes[a]].bg_layer_num > curLBP->bg_layer_num && LBPs[lbp_idxes[a]].weight < LBPs[lbp_idxes[a]].max_weight * 0.9f) { /* remove layers */ - //LBPs[lbp_idxes[a]].bg_layer_num = 0; + //LBPs[lbp_idxes[a]].bg_layer_num = 0; removed_modes[a] = true; removed_bg_layers = true; } @@ -835,7 +835,7 @@ void CMultiLayerBGS::GetBackgroundImage(IplImage *bk_img) { ODC.SetImageData(bg_img, org_data); delete[] org_data; - cvCopyImage(m_pBgImg, bk_img); + cvCopy(m_pBgImg, bk_img); } void CMultiLayerBGS::GetForegroundImage(IplImage *fg_img, CvScalar bg_color) { @@ -865,7 +865,7 @@ void CMultiLayerBGS::GetForegroundMaskImage(IplImage *fg_mask_img) { if (m_pROI && (m_pROI->width <= 0 || m_pROI->height <= 0)) return; - //cvCopyImage(m_pFgMaskImg, fg_mask_img); + //cvCopy(m_pFgMaskImg, fg_mask_img); if (m_pROI) { cvSetImageROI(m_pFgMaskImg, *m_pROI); cvSetImageROI(fg_mask_img, *m_pROI); @@ -1391,7 +1391,7 @@ void CMultiLayerBGS::GetCurrentLayeredBackgroundImage(int layered_no, IplImage * } void CMultiLayerBGS::GetColoredBgMultiLayeredImage(IplImage *bg_multi_layer_img, CvScalar *layer_colors) { - cvCopyImage(m_pOrgImg, bg_multi_layer_img); + cvCopy(m_pOrgImg, bg_multi_layer_img); COpencvDataConversion<uchar, uchar> ODC; diff --git a/package_bgs/jmo/CMultiLayerBGS.h b/package_bgs/MultiLayer/CMultiLayerBGS.h similarity index 96% rename from package_bgs/jmo/CMultiLayerBGS.h rename to package_bgs/MultiLayer/CMultiLayerBGS.h index c8698f6272595f7dd0c22ba95546a616641cffee..78a0527ddb75bcce0f324ec0ecd52d017bc0c529 100644 --- a/package_bgs/jmo/CMultiLayerBGS.h +++ b/package_bgs/MultiLayer/CMultiLayerBGS.h @@ -43,9 +43,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // BackgroundSubtraction.h: interface for the CBackgroundSubtraction class. // ////////////////////////////////////////////////////////////////////// - -#if !defined(_MULTI_LAYER_BGS_H_) -#define _MULTI_LAYER_BGS_H_ +#pragma once /* Since the used fast cross bilateral filter codes can not be compiled under Windows, @@ -124,16 +122,16 @@ public: 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). - // +//------------------------------------------------------------- +// 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); //------------------------------------------------------------- @@ -308,6 +306,3 @@ public: CMultiLayerBGS(); virtual ~CMultiLayerBGS(); }; - -#endif // !defined(_MULTI_LAYER_BGS_H_) - diff --git a/package_bgs/jmo/LocalBinaryPattern.cpp b/package_bgs/MultiLayer/LocalBinaryPattern.cpp similarity index 95% rename from package_bgs/jmo/LocalBinaryPattern.cpp rename to package_bgs/MultiLayer/LocalBinaryPattern.cpp index 6967cf4eb84e538df152b6d8636a4511da312c9d..060b9ea959af92ea290fe056b88457963c6fae0d 100644 --- a/package_bgs/jmo/LocalBinaryPattern.cpp +++ b/package_bgs/MultiLayer/LocalBinaryPattern.cpp @@ -105,13 +105,13 @@ void CLocalBinaryPattern::Initialization(IplImage **first_imgs, int imgs_num, in m_nMaxShift.y = 0; int shift_idx = 0; for (a = 0; a < m_nLBPLevelNum; a++) - for (b = 0; b < m_pNeigPointsNums[a]; b++) { - // compute the offset of neig point - CalNeigPixelOffset(m_pRadiuses[a], m_pNeigPointsNums[a], b, m_pXYShifts[shift_idx].x, m_pXYShifts[shift_idx].y); - m_nMaxShift.x = MAX(m_nMaxShift.x, m_pXYShifts[shift_idx].x); - m_nMaxShift.y = MAX(m_nMaxShift.y, m_pXYShifts[shift_idx].y); - shift_idx++; - } + for (b = 0; b < m_pNeigPointsNums[a]; b++) { + // compute the offset of neig point + CalNeigPixelOffset(m_pRadiuses[a], m_pNeigPointsNums[a], b, m_pXYShifts[shift_idx].x, m_pXYShifts[shift_idx].y); + m_nMaxShift.x = MAX(m_nMaxShift.x, m_pXYShifts[shift_idx].x); + m_nMaxShift.y = MAX(m_nMaxShift.y, m_pXYShifts[shift_idx].y); + shift_idx++; + } m_fRobustWhiteNoise = robust_white_noise; } @@ -155,7 +155,7 @@ void CLocalBinaryPattern::ComputeLBP(PixelLBPStruct *PLBP, CvRect *roi) if (roi) { int x, y; - for (y = 0; y < roi->height; y++) { + for (y = 0; y < roi->height; y++) { _PLBP = PLBP + (y + roi->y)*m_cvImgSize.width + roi->x; for (x = 0; x < roi->width; x++) { cur_pattern = (*_PLBP++).cur_pattern; diff --git a/package_bgs/jmo/LocalBinaryPattern.h b/package_bgs/MultiLayer/LocalBinaryPattern.h similarity index 96% rename from package_bgs/jmo/LocalBinaryPattern.h rename to package_bgs/MultiLayer/LocalBinaryPattern.h index 987a2c2655052a7ea3961bae8b8a899e6f32aaf0..40d43790f96292be18559c6056912ed4c7537469 100644 --- a/package_bgs/jmo/LocalBinaryPattern.h +++ b/package_bgs/MultiLayer/LocalBinaryPattern.h @@ -43,11 +43,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // LocalBinaryPattern.h: interface for the CLocalBinaryPattern class. // ////////////////////////////////////////////////////////////////////// +#pragma once -#if !defined(_LOCAL_BINARY_PATTERN_H_) -#define _LOCAL_BINARY_PATTERN_H_ - -#include <opencv2/opencv.hpp> +#include "OpenCvLegacyIncludes.h" #include "BGS.h" @@ -98,6 +96,3 @@ private: IplImage* m_pShiftedImg; }; - -#endif // !defined(_LOCAL_BINARY_PATTERN_H_) - diff --git a/package_bgs/jmo/OpenCvDataConversion.h b/package_bgs/MultiLayer/OpenCvDataConversion.h similarity index 97% rename from package_bgs/jmo/OpenCvDataConversion.h rename to package_bgs/MultiLayer/OpenCvDataConversion.h index a47563e59b74be9ee95c46ce0279368465158631..18371b3bf632163ee95eda0ea280cb7d978cfc11 100644 --- a/package_bgs/jmo/OpenCvDataConversion.h +++ b/package_bgs/MultiLayer/OpenCvDataConversion.h @@ -43,11 +43,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // OpencvDataConversion.h: interface for the COpencvDataConversion class. // ////////////////////////////////////////////////////////////////////// +#pragma once -#if !defined(_OPENCV_DATA_CONVERSION_H_) -#define _OPENCV_DATA_CONVERSION_H_ - -#include <opencv2/opencv.hpp> +#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 */ @@ -219,6 +217,3 @@ public: COpencvDataConversion() {}; virtual ~COpencvDataConversion() {}; }; - -#endif // !defined(_OPENCV_DATA_CONVERSION_H_) - diff --git a/package_bgs/MultiLayer/OpenCvLegacyIncludes.h b/package_bgs/MultiLayer/OpenCvLegacyIncludes.h new file mode 100644 index 0000000000000000000000000000000000000000..9d30c0ef28c2fd8d15e4daf933b0dd79cfa14441 --- /dev/null +++ b/package_bgs/MultiLayer/OpenCvLegacyIncludes.h @@ -0,0 +1,50 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..5e0fa45fac0ee03a3ffa6c33e2f89ea82df5a9b7 --- /dev/null +++ b/package_bgs/MultiLayer/blob.cpp @@ -0,0 +1,1148 @@ +/* +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/jmo/blob.h b/package_bgs/MultiLayer/blob.h similarity index 87% rename from package_bgs/jmo/blob.h rename to package_bgs/MultiLayer/blob.h index 67bdf11f856c6b0b00814be6872b6d16a03e10e1..b7d5fe1ce788cf21d5e978807243f8f2847027e3 100644 --- a/package_bgs/jmo/blob.h +++ b/package_bgs/MultiLayer/blob.h @@ -43,9 +43,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. /************************************************************************ Blob.h -FUNCIONALITAT: Definici� de la classe CBlob +FUNCIONALITAT: Definició de la classe CBlob AUTOR: Inspecta S.L. -MODIFICACIONS (Modificaci�, Autor, Data): +MODIFICACIONS (Modificació, Autor, Data): FUNCTIONALITY: Definition of the CBlob class and some helper classes to perform some calculations on it @@ -53,51 +53,46 @@ AUTHOR: Inspecta S.L. MODIFICATIONS (Modification, Author, Date): **************************************************************************/ - -//! Disable warnings referred to 255 character truncation for the std:map -//#pragma warning( disable : 4786 ) - -#ifndef CBLOB_INSPECTA_INCLUDED -#define CBLOB_INSPECTA_INCLUDED +#pragma once //#include "cxcore.h" #include "BlobLibraryConfiguration.h" #include <functional> #include <vector> #include <algorithm> -#include <opencv2/core/types_c.h> -//! Factor de conversi� de graus a radians +#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. + 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 to represent a blob, a group of connected pixels in a binary image + */ class CBlob { public: - //! Constructor est�ndard + //! Constructor estàndard //! Standard constructor CBlob(); - //! Constructor de c�pia + //! Constructor de còpia //! Copy constructor CBlob(const CBlob &src); CBlob(const CBlob *src); - //! Destructor est�ndard + //! Destructor estàndard //! Standard Destructor ~CBlob(); - //! Operador d'assignaci� + //! Operador d'assignació //! Assigment operator CBlob& operator=(const CBlob &src); - //! Indica si el blob est� buit ( no t� cap info associada ) + //! Indica si el blob està buit ( no té cap info associada ) //! Shows if the blob has associated information bool IsEmpty() const { @@ -107,13 +102,13 @@ namespace Blob //! 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�) + //! 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 + //! Calcula l'elipse que s'adapta als vèrtexs del blob //! Fits an ellipse to the blob edges CvBox2D GetEllipse() const; @@ -124,8 +119,8 @@ namespace Blob //! Funcions GET sobre els valors dels blobs //! Get functions - inline int Label() const { return etiqueta; } - inline int Parent() const { return parent; } + 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; } @@ -176,14 +171,14 @@ namespace Blob //! mitjana //! mean of the grey scale values of the blob pixels double mean; - //! desviaci� standard + //! 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 + //! à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 + //! Sequència de punts del contorn del blob //! Sequence with the edges of the blob CvSeq *edges; @@ -194,7 +189,7 @@ namespace Blob //! 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 + //! 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) @@ -208,22 +203,22 @@ namespace Blob /************************************************************************** - Definici� de les classes per a fer operacions sobre els blobs + Definició de les classes per a fer operacions sobre els blobs - Helper classes to perform operations on blobs - **************************************************************************/ + Helper classes to perform operations on blobs + **************************************************************************/ - //! Classe d'on derivarem totes les operacions sobre els blobs - //! Interface to derive all blob operations + //! Classe d'on derivarem totes les operacions sobre els blobs + //! Interface to derive all blob operations class COperadorBlob { public: - virtual ~COperadorBlob(){}; + virtual ~COperadorBlob() {}; - //! Aplica l'operaci� al blob + //! Aplica l'operació al blob virtual double operator()(const CBlob &blob) const = 0; - //! Obt� el nom de l'operador + //! Obté el nom de l'operador virtual const char *GetNom() const = 0; operator COperadorBlob*() const @@ -236,8 +231,8 @@ namespace Blob #ifdef BLOB_OBJECT_FACTORY /** - Funci� per comparar dos identificadors dins de la f�brica de COperadorBlobs - */ + Funció per comparar dos identificadors dins de la fàbrica de COperadorBlobs + */ struct functorComparacioIdOperador { bool operator()(const char* s1, const char* s2) const @@ -249,12 +244,12 @@ namespace Blob //! 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 ); + //! 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 + //! Classe per calcular l'àrea d'un blob //! Class to get the area of a blob class CBlobGetArea : public COperadorBlob { @@ -284,7 +279,7 @@ namespace Blob } }; - //! Classe que diu si un blob �s extern o no + //! Classe que diu si un blob és extern o no //! Class to get the extern flag of a blob class CBlobGetExterior : public COperadorBlob { @@ -314,7 +309,7 @@ namespace Blob } }; - //! Classe per calcular la desviaci� est�ndard dels nivells de gris d'un blob + //! 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 { @@ -365,7 +360,7 @@ namespace Blob } }; - //! Classe per calcular la difer�ncia en X del blob + //! Classe per calcular la diferència en X del blob class CBlobGetDiffX : public COperadorBlob { public: @@ -379,7 +374,7 @@ namespace Blob } }; - //! Classe per calcular la difer�ncia en X del blob + //! Classe per calcular la diferència en X del blob class CBlobGetDiffY : public COperadorBlob { public: @@ -398,7 +393,7 @@ namespace Blob class CBlobGetMoment : public COperadorBlob { public: - //! Constructor est�ndard + //! Constructor estàndard //! Standard constructor (gets the 00 moment) CBlobGetMoment() { @@ -434,7 +429,7 @@ namespace Blob } }; - //! Classe per calcular l'�rea del poligon convex d'un blob + //! 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 { @@ -494,7 +489,7 @@ namespace Blob } }; - //! Classe per a calcular la x m�nima + //! Classe per a calcular la x mínima //! Class to get the minimum x class CBlobGetMinX : public COperadorBlob { @@ -509,7 +504,7 @@ namespace Blob } }; - //! Classe per a calcular la x m�xima + //! Classe per a calcular la x màxima //! Class to get the maximum x class CBlobGetMaxX : public COperadorBlob { @@ -524,7 +519,7 @@ namespace Blob } }; - //! Classe per a calcular la y m�nima + //! Classe per a calcular la y mínima //! Class to get the minimum y class CBlobGetMinY : public COperadorBlob { @@ -539,7 +534,7 @@ namespace Blob } }; - //! Classe per a calcular la y m�xima + //! Classe per a calcular la y màxima //! Class to get the maximum y class CBlobGetMaxY : public COperadorBlob { @@ -579,7 +574,7 @@ namespace Blob } }; - //! Classe per calcular la dist�ncia entre el centre del blob i un punt donat + //! 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 { @@ -603,7 +598,7 @@ namespace Blob } private: - // coordenades del punt on volem calcular la dist�ncia + // coordenades del punt on volem calcular la distància double m_x, m_y; }; @@ -623,8 +618,8 @@ namespace Blob }; //! 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 + //! 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 { @@ -643,8 +638,8 @@ namespace Blob }; //! 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 + //! 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 { @@ -713,7 +708,7 @@ namespace Blob }; //! Classe per calcular el ratio entre l'area de la elipse i la de la taca - //! Class + //! Class class CBlobGetAreaElipseRatio : public COperadorBlob { public: @@ -755,7 +750,7 @@ namespace Blob } }; - //! Classe per calcular l'orientaci� de l'ellipse del blob en radians + //! 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 { @@ -776,7 +771,7 @@ namespace Blob } }; - //! Classe per calcular el cosinus de l'orientaci� de l'ellipse del blob + //! 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 { @@ -793,7 +788,7 @@ namespace Blob }; - //! Classe per calcular el ratio entre l'eix major i menor de la el�lipse + //! 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 { @@ -816,7 +811,7 @@ namespace Blob class CBlobGetXYInside : public COperadorBlob { public: - //! Constructor est�ndard + //! Constructor estàndard //! Standard constructor CBlobGetXYInside() { @@ -841,6 +836,3 @@ namespace Blob }; } - -#endif //CBLOB_INSPECTA_INCLUDED - diff --git a/package_bgs/PAWCS.cpp b/package_bgs/PAWCS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..908b3aeb83769663b1bf3f2219b78de64e4492e5 --- /dev/null +++ b/package_bgs/PAWCS.cpp @@ -0,0 +1,93 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..173bcf6917a2c6c253ca933538609be416feee63 --- /dev/null +++ b/package_bgs/PAWCS.h @@ -0,0 +1,48 @@ +/* +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.cpp b/package_bgs/PBAS/PBAS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc3ad40178d1302ac29860e3ae61b202508a26c0 --- /dev/null +++ b/package_bgs/PBAS/PBAS.cpp @@ -0,0 +1,585 @@ +/* +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; + + //feature vector + alpha = 7.0; + beta = 1.0; + formerMeanNorm = 0; + width = 0; + + //result image + foregroundValue = 255; + backgroundValue = 0; + + //length of random array + countOfRandomNumb = 1000; + + //the T(x_i) value needs initiation + T_init = R_lower; + + //check if something is moving in the picture + isMove = false; + + //for init, count number of runs + runs = 0; + newInitialization(); +} + +void PBAS::newInitialization() +{ + if (!randomN.empty()) + randomN.clear(); + + if (!randomX.empty()) + randomX.clear(); + + if (!randomY.empty()) + randomY.clear(); + + if (!randomMinDist.empty()) + randomMinDist.clear(); + + if (!randomT.empty()) + randomT.clear(); + + if (!randomTN.empty()) + randomTN.clear(); + + for (int l = 0; l < countOfRandomNumb; l++) + { + randomN.push_back((int)randomGenerator.uniform((int)0, (int)N)); + randomX.push_back((int)randomGenerator.uniform(-1, +2)); + randomY.push_back((int)randomGenerator.uniform(-1, +2)); + randomMinDist.push_back((int)randomGenerator.uniform((int)0, (int)N)); + randomT.push_back((int)randomGenerator.uniform((int)0, (int)T_upper)); + randomTN.push_back((int)randomGenerator.uniform((int)0, (int)T_upper)); + } +} + +PBAS::~PBAS(void) +{ + std::cout << "~PBAS()" << std::endl; + + randomN.clear(); + randomX.clear(); + randomY.clear(); + randomMinDist.clear(); + randomT.clear(); + randomTN.clear(); + + for (int k = 0; k < backgroundModel.size(); ++k) + { + if (chans == 1) + { + backgroundModel.at(k).at(0).release(); + backgroundModel.at(k).at(1).release(); + } + else + { + backgroundModel.at(k).at(0).release(); + backgroundModel.at(k).at(1).release(); + backgroundModel.at(k).at(2).release(); + + backgroundModel.at(k).at(3).release(); + backgroundModel.at(k).at(4).release(); + backgroundModel.at(k).at(5).release(); + } + } + + backgroundModel.clear(); + meanMinDist.release(); + + actualR.release(); + actualT.release(); + + sobelX.release(); + sobelY.release(); +} + +bool PBAS::process(cv::Mat* input, cv::Mat* output) +{ + if (width != input->cols) + { + width = input->cols; + chans = input->channels(); + height = input->rows; + + if (input->rows < 1 || input->cols < 1) + { + std::cout << "Error: Occurrence of to small (or empty?) image size in PBAS. STOPPING " << std::endl; + return false; + } + } + + //iniate the background model + init(input); + + resultMap = new cv::Mat(input->rows, input->cols, CV_8UC1); + + //calculate features + calculateFeatures(¤tFeatures, input); + + //set sumMagnitude to zero at beginning and then sum up in the loop + sumMagnitude = 0; + long glCounterFore = 0; + isMove = false; + + //Here starts the whole processing of each pixel of the image + // for each pixel + for (int j = 0; j < resultMap->rows; ++j) + { + resultMap_Pt = resultMap->ptr<uchar>(j); + currentFeaturesM_Pt.clear(); + currentFeaturesC_Pt.clear(); + std::vector<float*> fT; + std::vector<uchar*> uT; + B_Mag_Pts.clear(); + B_Col_Pts.clear(); + + for (int z = 0; z < chans; ++z) + { + currentFeaturesM_Pt.push_back(currentFeatures.at(z).ptr<float>(j)); + currentFeaturesC_Pt.push_back(currentFeatures.at(z + chans).ptr<uchar>(j)); + + B_Mag_Pts.push_back(fT); + + B_Col_Pts.push_back(uT); + } + + meanMinDist_Pt = meanMinDist.ptr<float>(j); + actualR_Pt = actualR.ptr<float>(j); + actualT_Pt = actualT.ptr<float>(j); + + for (int k = 0; k < runs; ++k) + { + for (int z = 0; z < chans; ++z) + { + B_Mag_Pts.at(z).push_back(backgroundModel.at(k).at(z).ptr<float>(j)); + B_Col_Pts.at(z).push_back(backgroundModel.at(k).at(z + chans).ptr<uchar>(j)); + } + } + + for (int i = 0; i < resultMap->cols; ++i) + { + //Compare each pixel to in the worst runtime-case each background model + int count = 0; + int index = 0; + + double norm = 0.0; + double dist = 0.0; + double minDist = 1000.0; + int entry = randomGenerator.uniform(3, countOfRandomNumb - 4); + + do + { + if (chans == 3) + { + norm = sqrt( + (((double)B_Mag_Pts.at(0).at(index)[i] - ((double)*currentFeaturesM_Pt.at(0)))*((double)B_Mag_Pts.at(0).at(index)[i] - ((double)*currentFeaturesM_Pt.at(0)))) + + (((double)B_Mag_Pts.at(1).at(index)[i] - ((double)*currentFeaturesM_Pt.at(1)))*((double)B_Mag_Pts.at(1).at(index)[i] - ((double)*currentFeaturesM_Pt.at(1)))) + + (((double)B_Mag_Pts.at(2).at(index)[i] - ((double)*currentFeaturesM_Pt.at(2)))*((double)B_Mag_Pts.at(2).at(index)[i] - ((double)*currentFeaturesM_Pt.at(2)))) + ); + + dist = sqrt( + (((double)B_Col_Pts.at(0).at(index)[i] - ((double)*currentFeaturesC_Pt.at(0)))*((double)B_Col_Pts.at(0).at(index)[i] - ((double)*currentFeaturesC_Pt.at(0)))) + + (((double)B_Col_Pts.at(1).at(index)[i] - ((double)*currentFeaturesC_Pt.at(1)))*((double)B_Col_Pts.at(1).at(index)[i] - ((double)*currentFeaturesC_Pt.at(1)))) + + (((double)B_Col_Pts.at(2).at(index)[i] - ((double)*currentFeaturesC_Pt.at(2)))*((double)B_Col_Pts.at(2).at(index)[i] - ((double)*currentFeaturesC_Pt.at(2)))) + ); + } + else + { + norm = abs((((double)B_Mag_Pts.at(0).at(index)[i] - + ((double)*currentFeaturesM_Pt.at(0)))*((double)B_Mag_Pts.at(0).at(index)[i] - ((double)*currentFeaturesM_Pt.at(0))))); + + dist = abs((((double)B_Col_Pts.at(0).at(index)[i] - + ((double)*currentFeaturesC_Pt.at(0)))*((double)B_Col_Pts.at(0).at(index)[i] - ((double)*currentFeaturesC_Pt.at(0)))) + ); + } + dist = ((double)alpha*(norm / formerMeanMag) + beta*dist); + + if ((dist < *actualR_Pt)) + { + ++count; + if (minDist > dist) + minDist = dist; + } + else + { + sumMagnitude += (double)(norm); + ++glCounterFore; + } + ++index; + } while ((count < Raute_min) && (index < runs)); + + + //############################################# + //update backgroundmodel + // is BACKGROUND + if (count >= Raute_min) + { + *resultMap_Pt = 0; + double ratio = std::ceil((double)T_upper / (double)(*actualT_Pt)); + //in the first run every distance is zero, because there is no background model + //in the secont run, we have already one image as background model, hence a + // reasonable minDist could be found -> because of the partly 1/run changing in the running average, we set in the first try meanMinDist to the actual minDist value + if (runs < N && runs > 2) + { + *meanMinDist_Pt = ((((float)(runs - 1)) * (*meanMinDist_Pt)) + (float)minDist) / ((float)runs); + } + else if (runs < N && runs == 2) + { + *meanMinDist_Pt = (float)minDist; + } + + //1. update model + if (runs == N) + { + //Update current pixel + //check if random numer is smaller than ratio + if (randomT.at(entry) < ratio) + { + // replace randomly chosen sample + int rand = randomN.at(entry + 1); //randomGenerator.uniform((int)0,(int)N-1); + for (int z = 0; z < chans; ++z) + { + B_Mag_Pts.at(z).at(rand)[i] = (float)*currentFeaturesM_Pt.at(z); + B_Col_Pts.at(z).at(rand)[i] = (uchar)*currentFeaturesC_Pt.at(z); + + } + + *meanMinDist_Pt = ((((float)(N - 1)) * (*meanMinDist_Pt)) + (float)minDist) / ((float)N); + } + + //Update neighboring pixel model + if (randomTN.at(entry) < ratio) + { + //choose neighboring pixel randomly + int xNeigh = randomX.at(entry) + i; + int yNeigh = randomY.at(entry) + j; + checkValid(&xNeigh, &yNeigh); + + // replace randomly chosen sample + int rand = randomN.at(entry - 1); + for (int z = 0; z < chans; ++z) + { + (backgroundModel.at(rand)).at(z).at<float>(yNeigh, xNeigh) = currentFeatures.at(z).at<float>(yNeigh, xNeigh); + (backgroundModel.at(rand)).at(z + chans).at<uchar>(yNeigh, xNeigh) = currentFeatures.at(z + chans).at<uchar>(yNeigh, xNeigh); + } + } + } + } + else + { + // store pixel as foreground + *resultMap_Pt = 255; + + //there is some movement + isMove = true; + } + + //#######################//#######################//#######################//####################### + //control loops + //#######################//#######################//#######################//####################### + //update R + decisionThresholdRegulator(actualR_Pt, meanMinDist_Pt); + + //update T + learningRateRegulator(actualT_Pt, meanMinDist_Pt, resultMap_Pt); + + //#######################//#######################//#######################//####################### + //#######################//#######################//#######################//####################### + + //jump to next pixel + ++resultMap_Pt; + for (int z = 0; z < chans; ++z) + { + ++currentFeaturesM_Pt.at(z); + ++currentFeaturesC_Pt.at(z); + } + + ++meanMinDist_Pt; + ++actualR_Pt; + ++actualT_Pt; + } + } + + resultMap->copyTo(*output); + + //if there is no foreground -> no magnitudes fount + //-> initiate some low value to prevent diving through zero + double meanMag = sumMagnitude / (double)(glCounterFore + 1); //height*width); + + if (meanMag > 20) + formerMeanMag = meanMag; + else + formerMeanMag = 20; + + delete resultMap; + + for (int z = 0; z < chans; ++z) + { + currentFeatures.at(z + chans).release(); + currentFeatures.at(z).release(); + } + + return true; +} + +void PBAS::decisionThresholdRegulator(float* pt, float* meanDist) +{ + //update R + double tempR = *pt; + double newThresh = (*meanDist)*R_scale; + + if (tempR < newThresh) + { + tempR += tempR * R_incdec; + } + else + { + tempR -= tempR * R_incdec; + } + + if (tempR >= R_lower) + *pt = (float)tempR; + else + *pt = (float)R_lower; +} + +void PBAS::learningRateRegulator(float* pt, float* meanDist, uchar* isFore) +{ + //time update + double tempT = *pt; + + if ((int)*isFore < 128) + { + tempT -= T_inc / (*meanDist + 1.0); + } + else + { + tempT += T_dec / (*meanDist + 1.0); + } + + if (tempT > T_lower && tempT < T_upper) + *pt = (float)tempT; +} + +void PBAS::checkValid(int *x, int *y) +{ + if (*x < 0) + { + *x = 0; + } + else if (*x >= width) + { + *x = width - 1; + } + + if (*y < 0) + { + *y = 0; + } + else if (*y >= height) + { + *y = height - 1; + } +} + +void PBAS::init(cv::Mat* input) +{ + if (runs < N) + { + std::vector<cv::Mat> init; + calculateFeatures(&init, input); + backgroundModel.push_back(init); + + if (chans == 1) + { + init.at(0).release(); + init.at(1).release(); + } + else + { + init.at(0).release(); + init.at(1).release(); + init.at(2).release(); + init.at(3).release(); + init.at(4).release(); + init.at(5).release(); + } + + init.clear(); + + if (runs == 0) + { + meanMinDist.create(input->size(), CV_32FC1); + meanMinDist.zeros(input->rows, input->cols, CV_32FC1); + + actualR.create(input->rows, input->cols, CV_32FC1); + actualT.create(input->rows, input->cols, CV_32FC1); + + float* ptRs, *ptTs; //, *ptM; + for (int rows = 0; rows < actualR.rows; ++rows) + { + ptRs = actualR.ptr<float>(rows); + ptTs = actualT.ptr<float>(rows); + + for (int cols = 0; cols < actualR.cols; ++cols) + { + ptRs[cols] = (float)R_lower; + ptTs[cols] = (float)T_init; + } + } + } + + ++runs; + } +} + +void PBAS::calculateFeatures(std::vector<cv::Mat>* feature, cv::Mat* inputImage) +{ + if (!feature->empty()) + feature->clear(); + + cv::Mat mag[3], dir; + + if (inputImage->channels() == 3) + { + std::vector<cv::Mat> rgbChannels(3); + cv::split(*inputImage, rgbChannels); + + for (int l = 0; l < 3; ++l) + { + cv::Sobel(rgbChannels.at(l), sobelX, CV_32F, 1, 0, 3, 1, 0.0); + cv::Sobel(rgbChannels.at(l), sobelY, CV_32F, 0, 1, 3, 1, 0.0); + + // Compute the L2 norm and direction of the gradient + cv::cartToPolar(sobelX, sobelY, mag[l], dir, true); + feature->push_back(mag[l]); + sobelX.release(); + sobelY.release(); + } + + feature->push_back(rgbChannels.at(0)); + feature->push_back(rgbChannels.at(1)); + feature->push_back(rgbChannels.at(2)); + rgbChannels.at(0).release(); + rgbChannels.at(1).release(); + rgbChannels.at(2).release(); + } + else + { + cv::Sobel(*inputImage, sobelX, CV_32F, 1, 0, 3, 1, 0.0); + cv::Sobel(*inputImage, sobelY, CV_32F, 0, 1, 3, 1, 0.0); + + // Compute the L2 norm and direction of the gradient + cv::cartToPolar(sobelX, sobelY, mag[0], dir, true); + feature->push_back(mag[0]); + + cv::Mat temp; + inputImage->copyTo(temp); + feature->push_back(temp); + temp.release(); + } + + mag[0].release(); + mag[1].release(); + mag[2].release(); + dir.release(); +} + +void PBAS::setN(int temp) +{ + N = temp; + newInitialization(); +} + +void PBAS::setRaute_min(int temp) +{ + Raute_min = temp; +} + +void PBAS::setR_lower(double temp) +{ + R_lower = temp; +} + +void PBAS::setR_incdec(double temp) +{ + R_incdec = temp; +} + +void PBAS::setR_scale(double temp) +{ + R_scale = temp; +} + +void PBAS::setT_init(double temp) +{ + T_init = temp; +} + +void PBAS::setT_lower(double temp) +{ + T_lower = temp; +} + +void PBAS::setT_upper(double temp) +{ + T_upper = temp; + newInitialization(); +} + +void PBAS::setT_dec(double temp) +{ + T_dec = temp; +} + +void PBAS::setT_inc(double temp) +{ + T_inc = temp; +} + +void PBAS::setAlpha(double temp) +{ + alpha = temp; +} + +void PBAS::setBeta(double temp) +{ + beta = temp; +} + +bool PBAS::isMovement() +{ + return isMove; +} + +//cv::Mat* PBAS::getR1_xi() +//{ +// return &actualR; +//} +// +//cv::Mat* PBAS::getT_xi() +//{ +// return &actualT; +//} diff --git a/package_bgs/PBAS/PBAS.h b/package_bgs/PBAS/PBAS.h new file mode 100644 index 0000000000000000000000000000000000000000..9014a280bb9fc2e762813d2f02470377fc4b6c9a --- /dev/null +++ b/package_bgs/PBAS/PBAS.h @@ -0,0 +1,207 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..8a3de97dd3413df895b05148862d484d8189982c --- /dev/null +++ b/package_bgs/PixelBasedAdaptiveSegmenter.cpp @@ -0,0 +1,126 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..36dd0ad03a206ff7858dafe0279e3ed280a0f6d4 --- /dev/null +++ b/package_bgs/PixelBasedAdaptiveSegmenter.h @@ -0,0 +1,58 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..d3052265052e1429745f1905fc2b354bf6ffd834 --- /dev/null +++ b/package_bgs/SigmaDelta.cpp @@ -0,0 +1,101 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..c7b1a2c660323a11672fb399a092b81139392d2a --- /dev/null +++ b/package_bgs/SigmaDelta.h @@ -0,0 +1,49 @@ +/* +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/bl/sdLaMa091.cpp b/package_bgs/SigmaDelta/sdLaMa091.cpp similarity index 97% rename from package_bgs/bl/sdLaMa091.cpp rename to package_bgs/SigmaDelta/sdLaMa091.cpp index 7071438d86ea8ce3a030081b2d85a0b4b3e2d4b0..286556be49ff77e7d7f5b406bc40e675c4dfafa6 100644 --- a/package_bgs/bl/sdLaMa091.cpp +++ b/package_bgs/SigmaDelta/sdLaMa091.cpp @@ -84,7 +84,7 @@ static inline uint8_t max(uint8_t a, uint8_t b) { } sdLaMa091_t* sdLaMa091New(void) { - sdLaMa091_t* sdLaMa091 = (sdLaMa091_t*) malloc(sizeof(*sdLaMa091)); + sdLaMa091_t* sdLaMa091 = (sdLaMa091_t*)malloc(sizeof(*sdLaMa091)); #ifdef DEFENSIVE_ALLOC if (sdLaMa091 == NULL) { @@ -151,7 +151,7 @@ int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091, sdLaMa091->numBytes = stride * height; sdLaMa091->unusedBytes = stride - sdLaMa091->width; - sdLaMa091->Mt = (uint8_t*) malloc(sdLaMa091->numBytes); + sdLaMa091->Mt = (uint8_t*)malloc(sdLaMa091->numBytes); #ifdef DEFENSIVE_ALLOC if (sdLaMa091->Mt == NULL) { outputError("Cannot allocate sdLaMa091->Mt table"); @@ -160,7 +160,7 @@ int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091, #endif memcpy(sdLaMa091->Mt, image_data, sdLaMa091->numBytes); - sdLaMa091->Ot = (uint8_t*) malloc(sdLaMa091->numBytes); + sdLaMa091->Ot = (uint8_t*)malloc(sdLaMa091->numBytes); #ifdef DEFENSIVE_ALLOC if (sdLaMa091->Ot == NULL) { outputError("Cannot allocate sdLaMa091->Ot table"); @@ -170,16 +170,16 @@ int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091, 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); + sdLaMa091->Vt = (uint8_t*)malloc(sdLaMa091->numBytes); #ifdef DEFENSIVE_ALLOC if (sdLaMa091->Vt == NULL) { outputError("Cannot allocate sdLaMa091->Vt table"); @@ -188,13 +188,13 @@ int32_t sdLaMa091AllocInit_8u_C1R(sdLaMa091_t* sdLaMa091, #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; } @@ -375,13 +375,13 @@ int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091, } #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); @@ -389,7 +389,7 @@ int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091, --(*workMt); } - + if (sdLaMa091->unusedBytes > 0) { workImage += sdLaMa091->unusedBytes; workMt += sdLaMa091->unusedBytes; @@ -400,14 +400,14 @@ int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091, 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; @@ -415,13 +415,13 @@ int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091, } } - + 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; @@ -433,30 +433,30 @@ int32_t sdLaMa091Update_8u_C1R(sdLaMa091_t* sdLaMa091, *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; @@ -525,13 +525,13 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, } #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); @@ -539,26 +539,26 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, --(*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; @@ -569,9 +569,9 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, 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; @@ -583,7 +583,7 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, *workVt = max(min(*workVt, sdLaMa091->Vmax), sdLaMa091->Vmin); } - + if (sdLaMa091->rgbUnusedBytes > 0) { workOt += sdLaMa091->rgbUnusedBytes; workVt += sdLaMa091->rgbUnusedBytes; @@ -593,19 +593,19 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, 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; @@ -626,7 +626,7 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, numColor = (numColor + 1) % CHANNELS; } - + if (sdLaMa091->rgbUnusedBytes > 0) { segmentation_map += sdLaMa091->rgbUnusedBytes; workOt += sdLaMa091->rgbUnusedBytes; diff --git a/package_bgs/bl/sdLaMa091.h b/package_bgs/SigmaDelta/sdLaMa091.h similarity index 96% rename from package_bgs/bl/sdLaMa091.h rename to package_bgs/SigmaDelta/sdLaMa091.h index bec93fb505c5a46f75ca938418ae5fc38cff360e..cf9e777d913a35d9bd5fa79e7baf62f4cdfb9f78 100644 --- a/package_bgs/bl/sdLaMa091.h +++ b/package_bgs/SigmaDelta/sdLaMa091.h @@ -14,11 +14,9 @@ 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 SD_LA_MA_091_H_ -#define SD_LA_MA_091_H_ +#pragma once #include <errno.h> -#include "stdbool.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -68,5 +66,3 @@ int32_t sdLaMa091Update_8u_C3R(sdLaMa091_t* sdLaMa091, uint8_t* segmentation_map); int32_t sdLaMa091Free(sdLaMa091_t* sdLaMa091); - -#endif diff --git a/package_bgs/StaticFrameDifferenceBGS.cpp b/package_bgs/StaticFrameDifference.cpp similarity index 53% rename from package_bgs/StaticFrameDifferenceBGS.cpp rename to package_bgs/StaticFrameDifference.cpp index 3463c457b2ae509560903d76d46ff8d2a61daf5d..2faa40c71f103b5b233ca223f1fd351cc2125f3e 100644 --- a/package_bgs/StaticFrameDifferenceBGS.cpp +++ b/package_bgs/StaticFrameDifference.cpp @@ -14,41 +14,41 @@ 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 "StaticFrameDifferenceBGS.h" +#include "StaticFrameDifference.h" -StaticFrameDifferenceBGS::StaticFrameDifferenceBGS() : firstTime(true), enableThreshold(true), threshold(15), showOutput(true) +using namespace bgslibrary::algorithms; + +StaticFrameDifference::StaticFrameDifference() : + enableThreshold(true), threshold(15) { - std::cout << "StaticFrameDifferenceBGS()" << std::endl; + std::cout << "StaticFrameDifference()" << std::endl; + setup("./config/StaticFrameDifference.xml"); } -StaticFrameDifferenceBGS::~StaticFrameDifferenceBGS() +StaticFrameDifference::~StaticFrameDifference() { - std::cout << "~StaticFrameDifferenceBGS()" << std::endl; + std::cout << "~StaticFrameDifference()" << std::endl; } -void StaticFrameDifferenceBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void StaticFrameDifference::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; + init(img_input, img_output, img_bgmodel); - if(img_background.empty()) + if (img_background.empty()) img_input.copyTo(img_background); - - loadConfig(); - - if(firstTime) - saveConfig(); cv::absdiff(img_input, img_background, img_foreground); - if(img_foreground.channels() == 3) + if (img_foreground.channels() == 3) cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY); - if(enableThreshold) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) cv::imshow("Static Frame Difference", img_foreground); +#endif img_foreground.copyTo(img_output); img_background.copyTo(img_bgmodel); @@ -56,9 +56,9 @@ void StaticFrameDifferenceBGS::process(const cv::Mat &img_input, cv::Mat &img_ou firstTime = false; } -void StaticFrameDifferenceBGS::saveConfig() +void StaticFrameDifference::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/StaticFrameDifferenceBGS.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteInt(fs, "enableThreshold", enableThreshold); cvWriteInt(fs, "threshold", threshold); @@ -67,13 +67,13 @@ void StaticFrameDifferenceBGS::saveConfig() cvReleaseFileStorage(&fs); } -void StaticFrameDifferenceBGS::loadConfig() +void StaticFrameDifference::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/StaticFrameDifferenceBGS.xml", 0, CV_STORAGE_READ); - - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/StaticFrameDifference.h b/package_bgs/StaticFrameDifference.h new file mode 100644 index 0000000000000000000000000000000000000000..8c8474c6ed065178f1275e23baa826caaab5fb36 --- /dev/null +++ b/package_bgs/StaticFrameDifference.h @@ -0,0 +1,42 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..c8a0e5d11b8a952d72c721ae55d8793b642a2294 --- /dev/null +++ b/package_bgs/SuBSENSE.cpp @@ -0,0 +1,96 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..9ac9aa6f2fcbe04592b1abf5682245885238d07a --- /dev/null +++ b/package_bgs/SuBSENSE.h @@ -0,0 +1,49 @@ +/* +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.cpp b/package_bgs/T2F/FuzzyUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a151136e6eb946138bb411ef9bf9d6088e8d789c --- /dev/null +++ b/package_bgs/T2F/FuzzyUtils.cpp @@ -0,0 +1,512 @@ +/* +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) {} + +FuzzyUtils::~FuzzyUtils(void) {} + +void FuzzyUtils::LBP(IplImage* InputImage, IplImage* LBPimage) +{ + PixelUtils p; + + float* neighberPixel = (float*)malloc(9 * sizeof(float)); + float* BinaryValue = (float*)malloc(9 * sizeof(float)); + float* CarreExp = (float*)malloc(9 * sizeof(float)); + float* valLBP = (float*)malloc(1 * sizeof(float)); + + *valLBP = 0; + + int x = 0, y = 0; + + // on implemente les 8 valeurs puissance de 2 qui correspondent aux 8 elem. d'image voisins au elem. d'image central + *(CarreExp + 0) = 1.0; + *(CarreExp + 1) = 2.0; + *(CarreExp + 2) = 4.0; + *(CarreExp + 3) = 8.0; + *(CarreExp + 4) = 0.0; + *(CarreExp + 5) = 16.0; + *(CarreExp + 6) = 32.0; + *(CarreExp + 7) = 64.0; + *(CarreExp + 8) = 128.0; + + //le calcule de LBP + //pour les 4 coins + /* 1.*/ + if (x == 0 && y == 0) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 4, 0); + *valLBP = *valLBP + ((*(BinaryValue + 1))*(*(CarreExp + 1)) + (*(BinaryValue + 2))*(*(CarreExp + 2)) + (*(BinaryValue + 3))*(*(CarreExp + 3))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + + /* 2.*/ + if (x == 0 && y == InputImage->width) + { + *valLBP = 0; + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 4, 1); + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 2))*(*(CarreExp + 2)) + (*(BinaryValue + 3))*(*(CarreExp + 3))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + + /* 3.*/ + if (x == InputImage->height && y == 0) + { + *valLBP = 0; + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 4, 2); + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 1))*(*(CarreExp + 1)) + (*(BinaryValue + 3))*(*(CarreExp + 3))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + + /* 4.*/ + if (x == InputImage->height && y == InputImage->width) + { + *valLBP = 0; + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 4, 3); + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 1))*(*(CarreExp + 1)) + (*(BinaryValue + 2))*(*(CarreExp + 2))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + + //le calcul de LBP pour la première ligne : L(0) + if (x == 0 && (y != 0 && y != InputImage->width)) + { + for (int y = 1; y < InputImage->width - 1; y++) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 6, 4); + *valLBP = 0; + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 1))*(*(CarreExp + 1)) + (*(BinaryValue + 2))*(*(CarreExp + 2)) + (*(BinaryValue + 3))*(*(CarreExp + 3)) + (*(BinaryValue + 5))*(*(CarreExp + 5))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + } + + //le calcul de LBP pour la dernière colonne : C(w) + if ((x != 0 && x != InputImage->height) && y == InputImage->width) + { + for (int x = 1; x < InputImage->height - 1; x++) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 6, 4); + *valLBP = 0; + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 1))*(*(CarreExp + 1)) + (*(BinaryValue + 2))*(*(CarreExp + 2)) + (*(BinaryValue + 3))*(*(CarreExp + 3)) + (*(BinaryValue + 5))*(*(CarreExp + 5))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + } + + //le calcul de LBP pour la dernière ligne : L(h) + if (x == InputImage->height && (y != 0 && y != InputImage->width)) + { + for (int y = 1; y < InputImage->width - 1; y++) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 6, 1); + *valLBP = 0; + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp)) + (*(BinaryValue + 2))*(*(CarreExp + 2)) + (*(BinaryValue + 3))*(*(CarreExp + 3)) + (*(BinaryValue + 4))*(*(CarreExp + 4)) + (*(BinaryValue + 5))*(*(CarreExp + 5))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + } + + //le calcul de LBP pour la première colonne : C(0) + if ((x != 0 && x != InputImage->height) && y == 0) + { + for (int x = 1; x < InputImage->height - 1; x++) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 6, 2); + *valLBP = 0; + *valLBP = *valLBP + ((*(BinaryValue))*(*(CarreExp + 5)) + (*(BinaryValue + 1))*(*(CarreExp + 6)) + (*(BinaryValue + 3))*(*(CarreExp + 3)) + (*(BinaryValue + 4))*(*(CarreExp)) + (*(BinaryValue + 5))*(*(CarreExp + 1))) / 255.0; + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + } + + //pour le reste des elements d'image + for (int y = 1; y < InputImage->height - 1; y++) + { + for (int x = 1; x < InputImage->width - 1; x++) + { + p.getNeighberhoodGrayPixel(InputImage, x, y, neighberPixel); + getBinValue(neighberPixel, BinaryValue, 9, 4); + //le calcul de la valeur du LBP pour chaque elem. d'im. + *valLBP = 0; + for (int l = 0; l < 9; l++) + *valLBP = *valLBP + ((*(BinaryValue + l)) * (*(CarreExp + l))) / 255.0; + //printf("\nvalLBP(%d,%d)=%f",x,y,*valLBP); + p.PutGrayPixel(LBPimage, x, y, *valLBP); + } + } + + free(neighberPixel); + free(BinaryValue); + free(CarreExp); + free(valLBP); +} + +void FuzzyUtils::getBinValue(float* neighberGrayPixel, float* BinaryValue, int m, int n) +{ + // la comparaison entre la valeur d'elem d'image central et les valeurs des elem. d'im. voisins + // m = le numero des elements (4, 6 ou 9); + // n = la position de l'element central; + + int h = 0; + for (int k = 0; k < m; k++) + { + if (*(neighberGrayPixel + k) >= *(neighberGrayPixel + n)) + { + *(BinaryValue + h) = 1; + h++; + } + else + { + *(BinaryValue + h) = 0; + h++; + } + } +} + +void FuzzyUtils::SimilarityDegreesImage(IplImage* CurrentImage, IplImage* BGImage, IplImage* DeltaImage, int n, int color_space) +{ + PixelUtils p; + int i, j; + + if (n == 1) + { + float* CurrentGrayPixel = (float*)malloc(1 * (sizeof(float))); + float* BGGrayPixel = (float*)malloc(1 * (sizeof(float))); + float* DeltaGrayPixel = (float*)malloc(1 * (sizeof(float))); + + for (i = 0; i < CurrentImage->width; i++) + { + for (j = 0; j < CurrentImage->height; j++) + { + p.GetGrayPixel(CurrentImage, i, j, CurrentGrayPixel); + p.GetGrayPixel(BGImage, i, j, BGGrayPixel); + RatioPixels(CurrentGrayPixel, BGGrayPixel, DeltaGrayPixel, 1); + p.PutGrayPixel(DeltaImage, i, j, *DeltaGrayPixel); + } + } + + free(CurrentGrayPixel); + free(BGGrayPixel); + free(DeltaGrayPixel); + } + + if (n != 1) + { + IplImage* ConvertedCurrentImage = cvCreateImage(cvSize(CurrentImage->width, CurrentImage->height), IPL_DEPTH_32F, 3); + IplImage* ConvertedBGImage = cvCreateImage(cvSize(CurrentImage->width, CurrentImage->height), IPL_DEPTH_32F, 3); + + float* ConvertedCurrentPixel = (float*)malloc(3 * (sizeof(float))); + float* ConvertedBGPixel = (float*)malloc(3 * (sizeof(float))); + float* DeltaConvertedPixel = (float*)malloc(3 * (sizeof(float))); + + p.ColorConversion(CurrentImage, ConvertedCurrentImage, color_space); + p.ColorConversion(BGImage, ConvertedBGImage, color_space); + + for (i = 0; i < CurrentImage->width; i++) + { + for (j = 0; j < CurrentImage->height; j++) + { + p.GetPixel(ConvertedCurrentImage, i, j, ConvertedCurrentPixel); + p.GetPixel(ConvertedBGImage, i, j, ConvertedBGPixel); + RatioPixels(ConvertedCurrentPixel, ConvertedBGPixel, DeltaConvertedPixel, 3); + p.PutPixel(DeltaImage, i, j, DeltaConvertedPixel); + } + } + + free(ConvertedCurrentPixel); + free(ConvertedBGPixel); + free(DeltaConvertedPixel); + + cvReleaseImage(&ConvertedCurrentImage); + cvReleaseImage(&ConvertedBGImage); + } +} + +void FuzzyUtils::RatioPixels(float* CurrentPixel, float* BGPixel, float* DeltaPixel, int n) +{ + if (n == 1) + { + if (*CurrentPixel < *BGPixel) + *DeltaPixel = *CurrentPixel / *BGPixel; + + if (*CurrentPixel > *BGPixel) + *DeltaPixel = *BGPixel / *CurrentPixel; + + if (*CurrentPixel == *BGPixel) + *DeltaPixel = 1.0; + } + + if (n == 3) + for (int i = 0; i < 3; i++) + { + if (*(CurrentPixel + i) < *(BGPixel + i)) + *(DeltaPixel + i) = *(CurrentPixel + i) / *(BGPixel + i); + + if (*(CurrentPixel + i) > *(BGPixel + i)) + *(DeltaPixel + i) = *(BGPixel + i) / *(CurrentPixel + i); + + if (*(CurrentPixel + i) == *(BGPixel + i)) + *(DeltaPixel + i) = 1.0; + } +} + +void FuzzyUtils::getFuzzyIntegralSugeno(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage) +{ + // MeasureG : est un vecteur contenant 3 mesure g (g1,g2,g3) tel que : g1+g2+g3=1 + // n : =2 cad aggreger les 2 images "H" et "Delta" + // =1 cad aggreger uniquement les valeurs des composantes couleurs de l'image "Delta" + + PixelUtils p; + + float* HTexturePixel = (float*)malloc(1 * sizeof(float)); + float* DeltaOhtaPixel = (float*)malloc(3 * (sizeof(float))); + int *Indice = (int*)malloc(3 * (sizeof(int))); + float *HI = (float*)malloc(3 * (sizeof(float))); + float *Integral = (float*)malloc(3 * (sizeof(float))); + float* X = (float*)malloc(1 * sizeof(float)); + float* XiXj = (float*)malloc(1 * sizeof(float)); + float IntegralFlou; + + *Indice = 0; + *(Indice + 1) = 1; + *(Indice + 2) = 2; + *X = 1.0; + + for (int i = 0; i < H->width; i++) + { + for (int j = 0; j < H->height; j++) + { + p.GetGrayPixel(H, i, j, HTexturePixel); + p.GetPixel(Delta, i, j, DeltaOhtaPixel); + + *(HI + 0) = *(HTexturePixel + 0); + *(HI + 1) = *(DeltaOhtaPixel + 0); + *(HI + 2) = *(DeltaOhtaPixel + 1); + + Trier(HI, 3, Indice); + + *XiXj = *(MeasureG + (*(Indice + 1))) + (*(MeasureG + (*(Indice + 2)))); + + *(Integral + 0) = min((HI + (*(Indice + 0))), X); + *(Integral + 1) = min((HI + (*(Indice + 1))), XiXj); + *(Integral + 2) = min((HI + (*(Indice + 2))), ((MeasureG + (*(Indice + 2))))); + + IntegralFlou = max(Integral, 3); + p.PutGrayPixel(OutputImage, i, j, IntegralFlou); + } + } + + free(HTexturePixel); + free(DeltaOhtaPixel); + free(Indice); + free(HI); + free(X); + free(XiXj); + free(Integral); +} + +void FuzzyUtils::getFuzzyIntegralChoquet(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage) +{ + // MeasureG : est un vecteur contenant 3 mesure g (g1,g2,g3) tel que : g1+g2+g3=1 + // n : =2 cad aggreger les 2 images "H" et "Delta" + // =1 cad aggreger uniquement les valeurs des composantes couleurs de l'image "Delta" + + PixelUtils p; + + float* HTexturePixel = (float*)malloc(1 * sizeof(float)); + float* DeltaOhtaPixel = (float*)malloc(3 * (sizeof(float))); + int *Indice = (int*)malloc(3 * (sizeof(int))); + float *HI = (float*)malloc(3 * (sizeof(float))); + float *Integral = (float*)malloc(3 * (sizeof(float))); + float* X = (float*)malloc(1 * sizeof(float)); + float* XiXj = (float*)malloc(1 * sizeof(float)); + float IntegralFlou; + + *Indice = 0; + *(Indice + 1) = 1; + *(Indice + 2) = 2; + *X = 1.0; + + for (int i = 0; i < Delta->width; i++) + { + for (int j = 0; j < Delta->height; j++) + { + if (n == 2) + { + p.GetGrayPixel(H, i, j, HTexturePixel); + p.GetPixel(Delta, i, j, DeltaOhtaPixel); + + *(HI + 0) = *(HTexturePixel + 0); + *(HI + 1) = *(DeltaOhtaPixel + 0); + *(HI + 2) = *(DeltaOhtaPixel + 1); + } + + if (n == 1) + { + //remplir HI par les valeurs des 3 composantes couleurs uniquement + p.GetPixel(Delta, i, j, DeltaOhtaPixel); + + *(HI + 0) = *(DeltaOhtaPixel + 0); + //*(HI+0) = *(DeltaOhtaPixel+2); + *(HI + 1) = *(DeltaOhtaPixel + 1); + *(HI + 2) = *(DeltaOhtaPixel + 2); + } + + Trier(HI, 3, Indice); + *XiXj = *(MeasureG + (*(Indice + 1))) + (*(MeasureG + (*(Indice + 2)))); + + *(Integral + 0) = *(HI + (*(Indice + 0)))* (*X - *XiXj); + *(Integral + 1) = *(HI + (*(Indice + 1)))* (*XiXj - *(MeasureG + (*(Indice + 2)))); + *(Integral + 2) = *(HI + (*(Indice + 2)))* (*(MeasureG + (*(Indice + 2)))); + + IntegralFlou = *(Integral + 0) + *(Integral + 1) + *(Integral + 2); + p.PutGrayPixel(OutputImage, i, j, IntegralFlou); + } + } + + free(HTexturePixel); + free(DeltaOhtaPixel); + free(Indice); + free(HI); + free(X); + free(XiXj); + free(Integral); +} + +void FuzzyUtils::FuzzyMeasureG(float g1, float g2, float g3, float *G) +{ + *(G + 0) = g1; + *(G + 1) = g2; + *(G + 2) = g3; +} + +void FuzzyUtils::Trier(float* g, int n, int* index) +{ + // Cette fonction trie un vecteur g par ordre croissant et + // sort egalement l'indice des elements selon le trie dans le vecteur "index" supposé initialisé par des valeurs de 1 a n + + float t; + int r, a, b; + + for (a = 1; a <= n; a++) + { + for (b = n - 1; b >= a; b--) + if (*(g + b - 1) < (*(g + b))) + { + // ordre croissant des élements + t = *(g + b - 1); + *(g + b - 1) = *(g + b); + *(g + b) = t; + + // ordre des indices des élements du vecteur g + r = *(index + b - 1); + *(index + b - 1) = *(index + b); + *(index + b) = r; + } + } +} + +float FuzzyUtils::min(float *a, float *b) +{ + float min = 0; + + if (*a >= (*b)) + min = *b; + else + min = *a; + + return min; +} + +float FuzzyUtils::max(float* g, int n) +{ + float max = 0; + + for (int i = 0; i < n; i++) + { + if (*(g + i) >= max) + max = *(g + i); + } + + return max; +} + +void FuzzyUtils::gDeDeux(float* a, float* b, float* lambda) +{ + float* c = (float*)malloc(1 * sizeof(float)); + *c = *a + (*b) + (*lambda) * (*a) * (*b); +} + +void FuzzyUtils::getLambda(float* g) +{ + float a, b; + float* lambda = (float*)malloc(1 * sizeof(float)); + + a = (*(g + 0) * (*(g + 1)) + (*(g + 1)) * (*(g + 2)) + (*(g + 0)) * (*(g + 2))); + *lambda = -(*(g + 0) * (*(g + 1)) + (*(g + 1)) * (*(g + 2)) + (*(g + 0)) * (*(g + 2))) / (*(g + 0) * (*(g + 1)) * (*(g + 2))); + b = (*(g + 0) * (*(g + 1)) * (*(g + 2))); + + //printf("\na:%f",a); + //printf("\nb:%f",b); + //printf("\nlambda:%f", *lambda); + + free(lambda); +} + +void FuzzyUtils::AdaptativeSelectiveBackgroundModelUpdate(IplImage* CurrentImage, IplImage* BGImage, IplImage* OutputImage, IplImage* Integral, float seuil, float alpha) +{ + PixelUtils p; + + float beta = 0.0; + float* CurentImagePixel = (float*)malloc(3 * sizeof(float)); + float* BGImagePixel = (float*)malloc(3 * sizeof(float)); + float* OutputImagePixel = (float*)malloc(3 * sizeof(float)); + float* IntegralImagePixel = (float*)malloc(1 * sizeof(float)); + float *Maximum = (float*)malloc(1 * sizeof(float)); + float *Minimum = (float*)malloc(1 * sizeof(float)); + + p.ForegroundMaximum(Integral, Maximum, 1); + p.ForegroundMinimum(Integral, Minimum, 1); + + for (int i = 0; i < CurrentImage->width; i++) + { + for (int j = 0; j < CurrentImage->height; j++) + { + p.GetPixel(CurrentImage, i, j, CurentImagePixel); + p.GetPixel(BGImage, i, j, BGImagePixel); + p.GetGrayPixel(Integral, i, j, IntegralImagePixel); + + beta = 1 - ((*IntegralImagePixel) - ((*Minimum / (*Minimum - *Maximum)) * (*IntegralImagePixel) - (*Minimum * (*Maximum) / (*Minimum - *Maximum)))); + + for (int k = 0; k < 3; k++) + *(OutputImagePixel + k) = beta * (*(BGImagePixel + k)) + (1 - beta) * (alpha * (*(CurentImagePixel + k)) + (1 - alpha) * (*(BGImagePixel + k))); + + p.PutPixel(OutputImage, i, j, OutputImagePixel); + } + } + + free(CurentImagePixel); + free(BGImagePixel); + free(OutputImagePixel); + free(IntegralImagePixel); + free(Maximum); + free(Minimum); +} diff --git a/package_bgs/tb/FuzzyUtils.h b/package_bgs/T2F/FuzzyUtils.h similarity index 86% rename from package_bgs/tb/FuzzyUtils.h rename to package_bgs/T2F/FuzzyUtils.h index 43fc9ad4b0fdbefb084655c7469f5a913e617050..9a53a83f23d06742be9c5d33c7ff4fc5b776bce8 100644 --- a/package_bgs/tb/FuzzyUtils.h +++ b/package_bgs/T2F/FuzzyUtils.h @@ -15,19 +15,8 @@ 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 -/* -Code provided by Thierry BOUWMANS - -Maitre de Conf�rences -Laboratoire MIA -Universit� de La Rochelle -17000 La Rochelle -France -tbouwman@univ-lr.fr -http://sites.google.com/site/thierrybouwmans/ -*/ -#include "PixelUtils.h" +#include "../../package_analysis/PixelUtils.h" class FuzzyUtils { @@ -44,7 +33,7 @@ public: 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); + 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); diff --git a/package_bgs/tb/MRF.cpp b/package_bgs/T2F/MRF.cpp similarity index 58% rename from package_bgs/tb/MRF.cpp rename to package_bgs/T2F/MRF.cpp index cfde8af470bdfdb588d9be501639738709be254a..291a84612f53b482317d1cc4eefae70c681d7de4 100644 --- a/package_bgs/tb/MRF.cpp +++ b/package_bgs/T2F/MRF.cpp @@ -58,68 +58,68 @@ MRF_TC::MRF_TC() MRF_TC::~MRF_TC() { - delete []classes; - delete []old_labeling; - delete []in_image_data; - delete []local_evidence; + delete[]classes; + delete[]old_labeling; + delete[]in_image_data; + delete[]local_evidence; } double MRF_TC::TimeEnergy2(int i, int j, int label) { double energy = 0.0; - - if(old_labeling[i][j] == (label*255)) + + if (old_labeling[i][j] == (label * 255)) energy -= beta_time; else energy += beta_time; - if(i != height-1) // south + if (i != height - 1) // south { - if(label*255 == old_labeling[i+1][j]) + if (label * 255 == old_labeling[i + 1][j]) energy -= beta_time; else energy += beta_time; - if((j != width-1) && (label*255 == old_labeling[i+1][j+1])) + if ((j != width - 1) && (label * 255 == old_labeling[i + 1][j + 1])) energy -= beta_time; else energy += beta_time; - - if((j != 0) && (label*255 == old_labeling[i+1][j-1])) + + if ((j != 0) && (label * 255 == old_labeling[i + 1][j - 1])) energy -= beta_time; else energy += beta_time; } - if(j != width-1) // east + if (j != width - 1) // east { - if(label*255 == old_labeling[i][j+1]) + if (label * 255 == old_labeling[i][j + 1]) energy -= beta_time; else energy += beta_time; } - if(i != 0) // nord + if (i != 0) // nord { - if(label*255 == old_labeling[i-1][j]) + if (label * 255 == old_labeling[i - 1][j]) energy -= beta_time; else energy += beta_time; - if((j != width-1) && (label*255 == old_labeling[i-1][j+1])) + if ((j != width - 1) && (label * 255 == old_labeling[i - 1][j + 1])) energy -= beta_time; else energy += beta_time; - - if((j != 0) && (label*255 == old_labeling[i-1][j-1])) + + if ((j != 0) && (label * 255 == old_labeling[i - 1][j - 1])) energy -= beta_time; else energy += beta_time; } - if(j != 0) // west + if (j != 0) // west { - if(label*255 == old_labeling[i][j-1]) + if (label * 255 == old_labeling[i][j - 1]) energy -= beta_time; else energy += beta_time; @@ -132,53 +132,53 @@ double MRF_TC::Doubleton2(int i, int j, int label) { double energy = 0.0; - if(i != height-1) // south + if (i != height - 1) // south { - if(label == classes[i+1][j]) + if (label == classes[i + 1][j]) energy -= beta; else energy += beta; - if((j != width-1) && (label == classes[i+1][j+1])) + if ((j != width - 1) && (label == classes[i + 1][j + 1])) energy -= beta; else energy += beta; - - if((j != 0) && (label == classes[i+1][j-1])) + + if ((j != 0) && (label == classes[i + 1][j - 1])) energy -= beta; else energy += beta; } - if(j != width-1) // east + if (j != width - 1) // east { - if(label == classes[i][j+1]) + if (label == classes[i][j + 1]) energy -= beta; else energy += beta; } - if(i != 0) // nord + if (i != 0) // nord { - if(label == classes[i-1][j]) + if (label == classes[i - 1][j]) energy -= beta; else energy += beta; - if((j != width-1) && (label == classes[i-1][j+1])) + if ((j != width - 1) && (label == classes[i - 1][j + 1])) energy -= beta; else energy += beta; - if((j != 0) && (label == classes[i-1][j-1])) + if ((j != 0) && (label == classes[i - 1][j - 1])) energy -= beta; else energy += beta; } - if(j != 0) // west + if (j != 0) // west { - if(label == classes[i][j-1]) + if (label == classes[i][j - 1]) energy -= beta; else energy += beta; @@ -196,17 +196,17 @@ void MRF_TC::OnIterationOver2(void) void MRF_TC::Build_Classes_OldLabeling_InImage_LocalEnergy() { int i; - classes = new int* [height]; + classes = new int*[height]; old_labeling = new int *[height]; - in_image_data = new int* [height]; - local_evidence = new float* [height]; + in_image_data = new int*[height]; + local_evidence = new float*[height]; - for(i = 0; i < height; ++i) + for (i = 0; i < height; ++i) { classes[i] = new int[width]; old_labeling[i] = new int[width]; in_image_data[i] = new int[width]; - local_evidence[i] = new float[width*2]; + local_evidence[i] = new float[width * 2]; } } @@ -215,19 +215,19 @@ void MRF_TC::InitEvidence2(GMM *gmm, HMM *hmm, IplImage *labeling) int i, j; background = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); - cvCopy(background2,background.Ptr()); + cvCopy(background2, background.Ptr()); unsigned char *in_data = (unsigned char *)(in_image->imageData); unsigned char *labeling_data = (unsigned char *)(labeling->imageData); - for(i = 0; i < height; ++i) + for (i = 0; i < height; ++i) { - for(j = 0; j < width; ++j) + for (j = 0; j < width; ++j) { - in_image_data[i][j] = in_data[(i*in_image->widthStep)+j]; - old_labeling[i][j] = labeling_data[i*width+j]; - - if(in_image_data[i][j] == 255) + in_image_data[i][j] = in_data[(i*in_image->widthStep) + j]; + old_labeling[i][j] = labeling_data[i*width + j]; + + if (in_image_data[i][j] == 255) classes[i][j] = 1; else classes[i][j] = 0; @@ -241,29 +241,29 @@ void MRF_TC::InitEvidence2(GMM *gmm, HMM *hmm, IplImage *labeling) float pixel; int modes = 3; - float mu; + float mu; - for(i = 0; i < height; ++i) + for (i = 0; i < height; ++i) { - for(j = 0; j < width; ++j) + for (j = 0; j < width; ++j) { - variance = gmm[(i*width+j) * modes+0].variance; - muR = gmm[(i*width+j) * modes+0].muR; - muG = gmm[(i*width+j) * modes+0].muG; - muB = gmm[(i*width+j) * modes+0].muB; + variance = gmm[(i*width + j) * modes + 0].variance; + muR = gmm[(i*width + j) * modes + 0].muR; + muG = gmm[(i*width + j) * modes + 0].muG; + muB = gmm[(i*width + j) * modes + 0].muB; - mu = (muR + muG + muB)/3; + mu = (muR + muG + muB) / 3; - pixel = (background(i,j,0) + background(i,j,1) + background(i,j,2))/3; + pixel = (background(i, j, 0) + background(i, j, 1) + background(i, j, 2)) / 3; - if(variance == 0) variance = 1; + if (variance == 0) variance = 1; - local_evidence[i][j*2+0] = pow((pixel-mu),2)/2/variance; + local_evidence[i][j * 2 + 0] = pow((pixel - mu), 2) / 2 / variance; - if(pixel >= mu) - local_evidence[i][j*2+1] = pow((pixel - mu - 2.5*sqrt(variance)),2)/2/variance; + if (pixel >= mu) + local_evidence[i][j * 2 + 1] = pow((pixel - mu - 2.5*sqrt(variance)), 2) / 2 / variance; else - local_evidence[i][j*2+1] = pow((pixel - mu + 2.5*sqrt(variance)),2)/2/variance; + local_evidence[i][j * 2 + 1] = pow((pixel - mu + 2.5*sqrt(variance)), 2) / 2 / variance; } } } @@ -274,12 +274,12 @@ void MRF_TC::CreateOutput2() int i, j; unsigned char *out_data; - out_data = (unsigned char *) out_image->imageData; + out_data = (unsigned char *)out_image->imageData; // create output image for (i = 0; i < height; ++i) - for(j = 0; j < width; ++j) - out_data[(i*width) + j] = (unsigned char)((classes[i][j])*255); + for (j = 0; j < width; ++j) + out_data[(i*width) + j] = (unsigned char)((classes[i][j]) * 255); } //calculate the whole energy @@ -288,12 +288,12 @@ double MRF_TC::CalculateEnergy2() double sum = 0.0; int i, j, k; // !FAIL! - for(i = 0; i < height; ++i) + for (i = 0; i < height; ++i) { - for(j = 0; j < width; ++j) + for (j = 0; j < width; ++j) { k = classes[i][j]; - sum = sum + local_evidence[i][j*2+k] + Doubleton2(i,j,k) + TimeEnergy2(i, j, k);//min the value + sum = sum + local_evidence[i][j * 2 + k] + Doubleton2(i, j, k) + TimeEnergy2(i, j, k);//min the value } } //sum = 0.1; @@ -303,7 +303,7 @@ double MRF_TC::CalculateEnergy2() // local energy double MRF_TC::LocalEnergy2(int i, int j, int label) { - return local_evidence[i][j*2+label] + Doubleton2(i,j,label) + TimeEnergy2(i,j,label); + return local_evidence[i][j * 2 + label] + Doubleton2(i, j, label) + TimeEnergy2(i, j, label); } void MRF_TC::ICM2() @@ -317,22 +317,22 @@ void MRF_TC::ICM2() do { - for(i = 0; i < height; ++i) - for(j = 0; j < width; ++j) + for (i = 0; i < height; ++i) + for (j = 0; j < width; ++j) { - localenergy0 = LocalEnergy2(i,j,0); - localenergy1 = LocalEnergy2(i,j,1); - - if(localenergy0 < localenergy1) + localenergy0 = LocalEnergy2(i, j, 0); + localenergy1 = LocalEnergy2(i, j, 1); + + if (localenergy0 < localenergy1) classes[i][j] = 0; else classes[i][j] = 1; } - //E = CalculateEnergy2(); - //summa_deltaE = fabs(E_old-E); - //E_old = E; - ++K; - OnIterationOver2(); - }while(K < 2); + //E = CalculateEnergy2(); + //summa_deltaE = fabs(E_old-E); + //E_old = E; + ++K; + OnIterationOver2(); + } while (K < 2); } diff --git a/package_bgs/tb/MRF.h b/package_bgs/T2F/MRF.h similarity index 95% rename from package_bgs/tb/MRF.h rename to package_bgs/T2F/MRF.h index c74589958988c2b9f38895650f651d8fdb57bbfe..1276a30da751e5ee936b19235b72338b1ea2bef8 100644 --- a/package_bgs/tb/MRF.h +++ b/package_bgs/T2F/MRF.h @@ -14,8 +14,7 @@ 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 MRF_H -#define MRF_H +#pragma once #include "T2FMRF.h" @@ -53,7 +52,7 @@ namespace Algorithms ////////////////////////////////////////////////////////////////////////// // alpha value for MMD - double alpha; + double alpha; ////////////////////////////////////////////////////////////////////////// //current global energy @@ -64,7 +63,7 @@ namespace Algorithms int K; ////////////////////////////////////////////////////////////////////////// - //labeling image + //labeling image int **classes; //input image int **in_image_data; @@ -75,7 +74,7 @@ namespace Algorithms /************************************************************************/ /* the Markov Random Field with time constraints for T2FGMM */ /************************************************************************/ - class MRF_TC: public MRF + class MRF_TC : public MRF { private: double beta_time; @@ -103,5 +102,3 @@ namespace Algorithms }; } } - -#endif diff --git a/package_bgs/tb/T2FGMM.cpp b/package_bgs/T2F/T2FGMM.cpp similarity index 69% rename from package_bgs/tb/T2FGMM.cpp rename to package_bgs/T2F/T2FGMM.cpp index a49407b7aa1005622c634b408132452dfdb8ed52..6ff99978d2804c3530e4950379ddf2506ed5e034 100644 --- a/package_bgs/tb/T2FGMM.cpp +++ b/package_bgs/T2F/T2FGMM.cpp @@ -17,8 +17,8 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. /**************************************************************************** * * T2FGMM.cpp -* -* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs) +* +* 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. @@ -33,9 +33,9 @@ int compareT2FGMM(const void* _gmm1, const void* _gmm2) GMM gmm1 = *(GMM*)_gmm1; GMM gmm2 = *(GMM*)_gmm2; - if(gmm1.significants < gmm2.significants) + if (gmm1.significants < gmm2.significants) return 1; - else if(gmm1.significants == gmm2.significants) + else if (gmm1.significants == gmm2.significants) return 0; else return -1; @@ -53,10 +53,10 @@ T2FGMM::~T2FGMM() void T2FGMM::Initalize(const BgsParams& param) { - m_params = (T2FGMMParams&) param; + m_params = (T2FGMMParams&)param; // Tbf - the threshold - m_bg_threshold = 0.75f; // 1-cf from the paper + m_bg_threshold = 0.75f; // 1-cf from the paper // Tgenerate - the threshold m_variance = 36.0f; // sigma for the new mode @@ -71,11 +71,11 @@ void T2FGMM::Initalize(const BgsParams& param) // Factor control for the T2FGMM-UM [0,3] //km = (float) 1.5; - km = (float) m_params.KM(); + km = (float)m_params.KM(); // Factor control for the T2FGMM-UV [0.3,1] //kv = (float) 0.6; - kv = (float) m_params.KV(); + kv = (float)m_params.KV(); } RgbImage* T2FGMM::Background() @@ -87,7 +87,7 @@ void T2FGMM::InitModel(const RgbImage& data) { m_modes_per_pixel.Clear(); - for(unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) + for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) { m_modes[i].weight = 0; m_modes[i].variance = 0; @@ -98,13 +98,13 @@ void T2FGMM::InitModel(const RgbImage& data) } } -void T2FGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +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) +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!!! @@ -119,19 +119,19 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& // calculate number of Gaussians to include in the background model int backgroundGaussians = 0; double sum = 0.0; - for(int i = 0; i < numModes; ++i) + for (int i = 0; i < numModes; ++i) { - if(sum < m_bg_threshold) + if (sum < m_bg_threshold) { backgroundGaussians++; - sum += m_modes[posPixel+i].weight; + 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++) + for (int iModes = 0; iModes < numModes; iModes++) { pos = posPixel + iModes; float weight = m_modes[pos].weight; @@ -159,45 +159,45 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& float HB; // T2FGMM-UM - if(m_params.Type() == TYPE_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; + 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; + 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; + 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; + 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; + 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; + HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2; } // T2FGMM-UV - if(m_params.Type() == TYPE_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); + 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) + 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) + if (dist < m_params.LowThreshold()*var) { bFitsPDF = true; // check if this Gaussian is part of the background model - if(iModes < backgroundGaussians) + if (iModes < backgroundGaussians) bBackgroundLow = true; //update distribution @@ -209,16 +209,16 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& 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; + 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) + if (weight < 0.0) { - weight=0.0; + weight = 0.0; numModes--; } @@ -229,9 +229,9 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& else { weight = fOneMinAlpha*weight; - if(weight < 0.0) + if (weight < 0.0) { - weight=0.0; + weight = 0.0; numModes--; } m_modes[pos].weight = weight; @@ -243,25 +243,25 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& // renormalize weights so they add to one double invTotalWeight = 1.0 / totalWeight; - for(int iLocal = 0; iLocal < numModes; iLocal++) + for (int iLocal = 0; iLocal < numModes; iLocal++) { m_modes[posPixel + iLocal].weight *= (float)invTotalWeight; - m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight + 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); + // 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 (!bFitsPDF) { - if(numModes < m_params.MaxModes()) + if (numModes < m_params.MaxModes()) numModes++; //else - // the weakest mode will be replaced - - pos = posPixel + numModes-1; + // the weakest mode will be replaced + + pos = posPixel + numModes - 1; m_modes[pos].muR = pixel.ch[0]; m_modes[pos].muG = pixel.ch[1]; @@ -277,26 +277,26 @@ void T2FGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& //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++) + 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. + // Sort significance values so they are in desending order. qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareT2FGMM); - if(bBackgroundLow) + if (bBackgroundLow) low_threshold = BACKGROUND; else low_threshold = FOREGROUND; - - if(bBackgroundHigh) + + if (bBackgroundHigh) high_threshold = BACKGROUND; else high_threshold = FOREGROUND; @@ -316,21 +316,21 @@ void T2FGMM::Subtract(int frame_num, const RgbImage& data, BwImage& low_threshol long posPixel; // update each pixel of the image - for(unsigned int r = 0; r < m_params.Height(); ++r) + for (unsigned int r = 0; r < m_params.Height(); ++r) { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { + 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); + 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; + 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; + 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/tb/T2FGMM.h b/package_bgs/T2F/T2FGMM.h similarity index 92% rename from package_bgs/tb/T2FGMM.h rename to package_bgs/T2F/T2FGMM.h index 7d966db3b313fb073e6765c6d0f8531350bdb4c8..203c3509275b72a85b90226d9ada0ce0791dcce5 100644 --- a/package_bgs/tb/T2FGMM.h +++ b/package_bgs/T2F/T2FGMM.h @@ -18,18 +18,16 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * T2FGMM.h * -* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs) +* 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: +* background subtraction algorithm: * * Zivkovic's code can be obtained at: www.zoranz.net ******************************************************************************/ - -#ifndef T2F_GMM_ -#define T2F_GMM_ +#pragma once #include "../dp/Bgs.h" #include "../dp/GrimsonGMM.h" @@ -55,9 +53,9 @@ namespace Algorithms 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 + // 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 @@ -66,7 +64,7 @@ namespace Algorithms float m_high_threshold; // alpha - speed of update - if the time interval you want to average over is T - // set alpha=1/T. + // set alpha=1/T. float m_alpha; // Maximum number of modes (Gaussian components) that will be used per pixel @@ -92,12 +90,12 @@ namespace Algorithms 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 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: + private: void SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold); // User adjustable parameters @@ -109,8 +107,8 @@ namespace Algorithms // 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. + // 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; @@ -131,5 +129,3 @@ namespace Algorithms }; } } - -#endif diff --git a/package_bgs/tb/T2FMRF.cpp b/package_bgs/T2F/T2FMRF.cpp similarity index 70% rename from package_bgs/tb/T2FMRF.cpp rename to package_bgs/T2F/T2FMRF.cpp index 372f564fe434ec0d9010e644cf8a8f2f65d32c87..e722d0240e7da9d898d37ce5b8f726201bcb95bd 100644 --- a/package_bgs/tb/T2FMRF.cpp +++ b/package_bgs/T2F/T2FMRF.cpp @@ -18,12 +18,12 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * T2FMRF.cpp * -* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs) +* 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: +* background subtraction algorithm: * * Zivkovic's code can be obtained at: www.zoranz.net ******************************************************************************/ @@ -37,9 +37,9 @@ int compareT2FMRF(const void* _gmm1, const void* _gmm2) GMM gmm1 = *(GMM*)_gmm1; GMM gmm2 = *(GMM*)_gmm2; - if(gmm1.significants < gmm2.significants) + if (gmm1.significants < gmm2.significants) return 1; - else if(gmm1.significants == gmm2.significants) + else if (gmm1.significants == gmm2.significants) return 0; else return -1; @@ -66,10 +66,10 @@ T2FMRF::~T2FMRF() void T2FMRF::Initalize(const BgsParams& param) { - m_params = (T2FMRFParams&) param; + m_params = (T2FMRFParams&)param; // Tbf - the threshold - m_bg_threshold = 0.75f; // 1-cf from the paper + m_bg_threshold = 0.75f; // 1-cf from the paper // Tgenerate - the threshold m_variance = 36.0f; // sigma for the new mode @@ -87,11 +87,11 @@ void T2FMRF::Initalize(const BgsParams& param) // Factor control for the T2FGMM-UM [0,3] // km = (float) 2; //1.5; - km = (float) m_params.KM(); + 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(); + kv = (float)m_params.KV(); } RgbImage* T2FMRF::Background() @@ -103,7 +103,7 @@ void T2FMRF::InitModel(const RgbImage& data) { m_modes_per_pixel.Clear(); - for(unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) + for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) { m_modes[i].weight = 0; m_modes[i].variance = 0; @@ -124,13 +124,13 @@ void T2FMRF::InitModel(const RgbImage& data) } } -void T2FMRF::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +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) +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!!! @@ -144,7 +144,7 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, 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 T = m_state[posPixel].T; float fOneMinAlpha = 1 - m_params.Alpha(); float totalWeight = 0.0f; @@ -152,12 +152,12 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, // calculate number of Gaussians to include in the background model int backgroundGaussians = 0; double sum = 0.0; - for(int i = 0; i < numModes; ++i) + for (int i = 0; i < numModes; ++i) { - if(sum < m_bg_threshold) + if (sum < m_bg_threshold) { backgroundGaussians++; - sum += m_modes[posGMode+i].weight; + sum += m_modes[posGMode + i].weight; } else break; @@ -192,57 +192,57 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, float HB; // T2FMRF-UM - if(m_params.Type() == TYPE_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; + 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; + 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; + 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; + 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; + 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; + HB = dB*dB / (2 * var*var) + km*dB / var + km*km / 2; } // T2FGMM-UV - if(m_params.Type() == TYPE_T2FMRF_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); + 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); + if (Ab2b != 0) ro = (Ab2f / Ab2b); else ro = 10; } else { - if(Af2b!=0) ro = (Af2f/Af2b); + 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) + 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) + if (dist < m_params.LowThreshold()*var) { bFitsPDF = true; // check if this Gaussian is part of the background model - if(iModes < backgroundGaussians) + if (iModes < backgroundGaussians) bBackgroundLow = true; //update distribution @@ -254,8 +254,8 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, 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; + 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 @@ -263,7 +263,7 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, weight = fOneMinAlpha*weight; if (weight < 0.0) { - weight=0.0; + weight = 0.0; numModes--; } @@ -276,7 +276,7 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, weight = fOneMinAlpha*weight; if (weight < 0.0) { - weight=0.0; + weight = 0.0; numModes--; } m_modes[pos].weight = weight; @@ -294,18 +294,18 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, 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); + // 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 (!bFitsPDF) { - if(numModes < m_params.MaxModes()) + if (numModes < m_params.MaxModes()) numModes++; //else - // the weakest mode will be replaced - - pos = posGMode + numModes-1; + // the weakest mode will be replaced + + pos = posGMode + numModes - 1; m_modes[pos].muR = pixel.ch[0]; m_modes[pos].muG = pixel.ch[1]; @@ -313,7 +313,7 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, m_modes[pos].variance = m_variance; m_modes[pos].significants = 0; // will be set below - if(numModes == 1) + if (numModes == 1) m_modes[pos].weight = 1; else m_modes[pos].weight = m_params.Alpha(); @@ -321,33 +321,33 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, //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++) + 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. + // Sort significance values so they are in desending order. qsort(&(m_modes[posGMode]), numModes, sizeof(GMM), compareT2FMRF); - if(bBackgroundLow) + if (bBackgroundLow) { low_threshold = BACKGROUND; m_state[posPixel].State = background; - if(CurrentState == 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].Ab2b = b2b / b; + m_state[posPixel].Ab2f = b2f / b; m_state[posPixel].T = m_state[posPixel].Ab2b; } else @@ -356,8 +356,8 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, float f2f = fOneMinAlpha*Af2f; float f = f2b + f2f; - m_state[posPixel].Af2b = f2b/f; - m_state[posPixel].Af2f = f2f/f; + m_state[posPixel].Af2b = f2b / f; + m_state[posPixel].Af2f = f2f / f; m_state[posPixel].T = m_state[posPixel].Af2b; } } @@ -366,14 +366,14 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, low_threshold = FOREGROUND; m_state[posPixel].State = foreground; - if(CurrentState == background) + 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].Ab2b = b2b / b; + m_state[posPixel].Ab2f = b2f / b; m_state[posPixel].T = m_state[posPixel].Ab2b; } else @@ -382,13 +382,13 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, 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].Af2b = f2b / f; + m_state[posPixel].Af2f = f2f / f; m_state[posPixel].T = m_state[posPixel].Af2b; } } - if(bBackgroundHigh) + if (bBackgroundHigh) high_threshold = BACKGROUND; else high_threshold = FOREGROUND; @@ -402,30 +402,30 @@ void T2FMRF::SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, // (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) +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 r = 0; r < m_params.Height(); ++r) { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { + 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); + 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; + 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; + 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/tb/T2FMRF.h b/package_bgs/T2F/T2FMRF.h similarity index 91% rename from package_bgs/tb/T2FMRF.h rename to package_bgs/T2F/T2FMRF.h index 00e464c310bfbb2f6795f22451b27aa4fe5a92ab..1015426eabeb83055fe3d4969c0d8fab4fda0775 100644 --- a/package_bgs/tb/T2FMRF.h +++ b/package_bgs/T2F/T2FMRF.h @@ -18,18 +18,16 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * T2FMRF.h * -* Purpose: Implementation of the T2 Fuzzy Gaussian Mixture Models (T2GMMs) +* 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: +* background subtraction algorithm: * * Zivkovic's code can be obtained at: www.zoranz.net ******************************************************************************/ - -#ifndef T2F_MRF_ -#define T2F_MRF_ +#pragma once #include "../dp/Bgs.h" #include "../dp/GrimsonGMM.h" @@ -41,9 +39,9 @@ namespace Algorithms const int TYPE_T2FMRF_UM = 0; const int TYPE_T2FMRF_UV = 1; - enum HiddenState {background, foreground}; + enum HiddenState { background, foreground }; - typedef struct HMMState + typedef struct HMMState { float T; //Hidden State @@ -80,9 +78,9 @@ namespace Algorithms 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 + // 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 @@ -91,7 +89,7 @@ namespace Algorithms float m_high_threshold; // alpha - speed of update - if the time interval you want to average over is T - // set alpha=1/T. + // set alpha=1/T. float m_alpha; // Maximum number of modes (Gaussian components) that will be used per pixel @@ -116,7 +114,7 @@ namespace Algorithms 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 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(); @@ -124,7 +122,7 @@ namespace Algorithms GMM *gmm(void); HMM *hmm(void); - private: + private: void SubtractPixel(long posPixel, long posGMode, const RgbPixel& pixel, unsigned char& numModes, unsigned char& lowThreshold, unsigned char& highThreshold); // User adjustable parameters @@ -136,8 +134,8 @@ namespace Algorithms // 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. + // 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; @@ -160,5 +158,3 @@ namespace Algorithms }; } } - -#endif diff --git a/package_bgs/tb/T2FGMM_UM.cpp b/package_bgs/T2FGMM_UM.cpp similarity index 64% rename from package_bgs/tb/T2FGMM_UM.cpp rename to package_bgs/T2FGMM_UM.cpp index 31a5338068580281d41a3d0af2c959a31d33b8a2..ad1b40e82ae8e504a7713a3f8d87afe8bc0897b8 100644 --- a/package_bgs/tb/T2FGMM_UM.cpp +++ b/package_bgs/T2FGMM_UM.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "T2FGMM_UM.h" -T2FGMM_UM::T2FGMM_UM() : firstTime(true), frameNumber(0), threshold(9.0), alpha(0.01), km(1.5f), kv(0.6f), gaussians(3), showOutput(true) +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() @@ -28,23 +32,16 @@ T2FGMM_UM::~T2FGMM_UM() void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +52,7 @@ void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & params.SetFrameSize(width, height); params.LowThreshold() = threshold; - params.HighThreshold() = 2*params.LowThreshold(); + params.HighThreshold() = 2 * params.LowThreshold(); params.Alpha() = alpha; params.MaxModes() = gaussians; params.Type() = TYPE_T2FGMM_UM; @@ -69,13 +66,18 @@ void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("T2FGMM-UM", foreground); - - foreground.copyTo(img_output); + 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; @@ -84,7 +86,7 @@ void T2FGMM_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & void T2FGMM_UM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FGMM_UM.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -98,14 +100,14 @@ void T2FGMM_UM::saveConfig() void T2FGMM_UM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FGMM_UM.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 9.0); - alpha = cvReadRealByName(fs, 0, "alpha", 0.01); - km = cvReadRealByName(fs, 0, "km", 1.5); - kv = cvReadRealByName(fs, 0, "kv", 0.6); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/tb/T2FGMM_UM.h b/package_bgs/T2FGMM_UM.h similarity index 52% rename from package_bgs/tb/T2FGMM_UM.h rename to package_bgs/T2FGMM_UM.h index ae6e29f89c52af779cd20a04afde16a5cd271e57..c58aeb756e40f43ba838901d5ff691df25338666 100644 --- a/package_bgs/tb/T2FGMM_UM.h +++ b/package_bgs/T2FGMM_UM.h @@ -16,43 +16,42 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "T2FGMM.h" +#include "IBGS.h" +#include "T2F/T2FGMM.h" using namespace Algorithms::BackgroundSubtraction; -class T2FGMM_UM : public IBGS +namespace bgslibrary { -private: - bool firstTime; - 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; - bool showOutput; - -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(); -}; - + 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/tb/T2FGMM_UV.cpp b/package_bgs/T2FGMM_UV.cpp similarity index 64% rename from package_bgs/tb/T2FGMM_UV.cpp rename to package_bgs/T2FGMM_UV.cpp index c6f99f198f2dd498402ea1d9526bd635358541b9..4e9708f68ef88b82f5495e8185c310858d982fa1 100644 --- a/package_bgs/tb/T2FGMM_UV.cpp +++ b/package_bgs/T2FGMM_UV.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "T2FGMM_UV.h" -T2FGMM_UV::T2FGMM_UV() : firstTime(true), frameNumber(0), threshold(9.0), alpha(0.01), km(1.5f), kv(0.6f), gaussians(3), showOutput(true) +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() @@ -28,23 +32,16 @@ T2FGMM_UV::~T2FGMM_UV() void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -55,7 +52,7 @@ void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & params.SetFrameSize(width, height); params.LowThreshold() = threshold; - params.HighThreshold() = 2*params.LowThreshold(); + params.HighThreshold() = 2 * params.LowThreshold(); params.Alpha() = alpha; params.MaxModes() = gaussians; params.Type() = TYPE_T2FGMM_UV; @@ -69,13 +66,18 @@ void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("T2FGMM-UV", foreground); - - foreground.copyTo(img_output); + 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; @@ -84,7 +86,7 @@ void T2FGMM_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & void T2FGMM_UV::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FGMM_UV.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -98,14 +100,14 @@ void T2FGMM_UV::saveConfig() void T2FGMM_UV::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FGMM_UV.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 9.0); - alpha = cvReadRealByName(fs, 0, "alpha", 0.01); - km = cvReadRealByName(fs, 0, "km", 1.5); - kv = cvReadRealByName(fs, 0, "kv", 0.6); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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/tb/T2FGMM_UV.h b/package_bgs/T2FGMM_UV.h similarity index 52% rename from package_bgs/tb/T2FGMM_UV.h rename to package_bgs/T2FGMM_UV.h index 79edcc229900ca6cef612e82661ec2c78f68e60d..6102f3a21c99939d0b71316768378b01e7e983f9 100644 --- a/package_bgs/tb/T2FGMM_UV.h +++ b/package_bgs/T2FGMM_UV.h @@ -16,43 +16,42 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "T2FGMM.h" +#include "IBGS.h" +#include "T2F/T2FGMM.h" using namespace Algorithms::BackgroundSubtraction; -class T2FGMM_UV : public IBGS +namespace bgslibrary { -private: - bool firstTime; - 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; - bool showOutput; - -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(); -}; - + 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/tb/T2FMRF_UM.cpp b/package_bgs/T2FMRF_UM.cpp similarity index 59% rename from package_bgs/tb/T2FMRF_UM.cpp rename to package_bgs/T2FMRF_UM.cpp index 5b41d8ae2c1acb72f43eb9bbedd6662577f22b3a..e0e6dae44dc315f70e0c5b93ca817438f656da17 100644 --- a/package_bgs/tb/T2FMRF_UM.cpp +++ b/package_bgs/T2FMRF_UM.cpp @@ -16,10 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "T2FMRF_UM.h" -T2FMRF_UM::T2FMRF_UM() : firstTime(true), frameNumber(0), threshold(9.0), alpha(0.01), -km(2.f), kv(0.9f), gaussians(3), showOutput(true) +using namespace bgslibrary::algorithms; + +T2FMRF_UM::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"); } T2FMRF_UM::~T2FMRF_UM() @@ -29,23 +32,16 @@ T2FMRF_UM::~T2FMRF_UM() void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -56,7 +52,7 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & params.SetFrameSize(width, height); params.LowThreshold() = threshold; - params.HighThreshold() = 2*params.LowThreshold(); + params.HighThreshold() = 2 * params.LowThreshold(); params.Alpha() = alpha; params.MaxModes() = gaussians; params.Type() = TYPE_T2FMRF_UM; @@ -70,7 +66,7 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & old = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); mrf.height = height; - mrf.width = width; + mrf.width = width; mrf.Build_Classes_OldLabeling_InImage_LocalEnergy(); firstTime = false; @@ -80,32 +76,37 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & cvCopy(lowThresholdMask.Ptr(), old); /************************************************************************/ - /* the code for MRF, it can be noted when using other methods */ - /************************************************************************/ - //the optimization process is done when the foreground detection is stable, - if(frameNumber >= 10) - { - gmm = bgs.gmm(); - hmm = bgs.hmm(); - mrf.background2 = frame_data.Ptr(); - mrf.in_image = lowThresholdMask.Ptr(); - mrf.out_image = lowThresholdMask.Ptr(); - mrf.InitEvidence2(gmm,hmm,old_labeling); - mrf.ICM2(); - cvCopy(mrf.out_image, lowThresholdMask.Ptr()); - } + /* the code for MRF, it can be noted when using other methods */ + /************************************************************************/ + //the optimization process is done when the foreground detection is stable, + if (frameNumber >= 10) + { + gmm = bgs.gmm(); + hmm = bgs.hmm(); + mrf.background2 = frame_data.Ptr(); + mrf.in_image = lowThresholdMask.Ptr(); + mrf.out_image = lowThresholdMask.Ptr(); + mrf.InitEvidence2(gmm, hmm, old_labeling); + mrf.ICM2(); + cvCopy(mrf.out_image, lowThresholdMask.Ptr()); + } cvCopy(old, old_labeling); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("T2FMRF-UM", foreground); - - foreground.copyTo(img_output); + 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("T2FMRF-UM", img_foreground); +#endif + + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); delete frame; frameNumber++; @@ -113,7 +114,7 @@ void T2FMRF_UM::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & void T2FMRF_UM::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FMRF_UM.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -127,14 +128,14 @@ void T2FMRF_UM::saveConfig() void T2FMRF_UM::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FMRF_UM.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 9.0); - alpha = cvReadRealByName(fs, 0, "alpha", 0.01); - km = cvReadRealByName(fs, 0, "km", 2); - kv = cvReadRealByName(fs, 0, "kv", 0.9); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); } diff --git a/package_bgs/T2FMRF_UM.h b/package_bgs/T2FMRF_UM.h new file mode 100644 index 0000000000000000000000000000000000000000..01f6014c44dfb33526f0c9e97646d52ccad8cb48 --- /dev/null +++ b/package_bgs/T2FMRF_UM.h @@ -0,0 +1,64 @@ +/* +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/tb/T2FMRF_UV.cpp b/package_bgs/T2FMRF_UV.cpp similarity index 59% rename from package_bgs/tb/T2FMRF_UV.cpp rename to package_bgs/T2FMRF_UV.cpp index 03f259557a9b2a514e74926839a3a5cdfb93a780..7f43c027541c7953b9aa91c2031ff0b256b8e729 100644 --- a/package_bgs/tb/T2FMRF_UV.cpp +++ b/package_bgs/T2FMRF_UV.cpp @@ -16,10 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "T2FMRF_UV.h" -T2FMRF_UV::T2FMRF_UV() : firstTime(true), frameNumber(0), threshold(9.0), alpha(0.01), -km(2.f), kv(0.9f), gaussians(3), showOutput(true) +using namespace bgslibrary::algorithms; + +T2FMRF_UV::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"); } T2FMRF_UV::~T2FMRF_UV() @@ -29,23 +32,16 @@ T2FMRF_UV::~T2FMRF_UV() void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - + init(img_input, img_output, img_bgmodel); frame = new IplImage(img_input); - - if(firstTime) + + if (firstTime) frame_data.ReleaseMemory(false); frame_data = frame; - if(firstTime) + if (firstTime) { - int width = img_input.size().width; + int width = img_input.size().width; int height = img_input.size().height; lowThresholdMask = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); @@ -56,7 +52,7 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & params.SetFrameSize(width, height); params.LowThreshold() = threshold; - params.HighThreshold() = 2*params.LowThreshold(); + params.HighThreshold() = 2 * params.LowThreshold(); params.Alpha() = alpha; params.MaxModes() = gaussians; params.Type() = TYPE_T2FMRF_UV; @@ -70,7 +66,7 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & old = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); mrf.height = height; - mrf.width = width; + mrf.width = width; mrf.Build_Classes_OldLabeling_InImage_LocalEnergy(); firstTime = false; @@ -80,32 +76,37 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & cvCopy(lowThresholdMask.Ptr(), old); /************************************************************************/ - /* the code for MRF, it can be noted when using other methods */ - /************************************************************************/ - //the optimization process is done when the foreground detection is stable, - if(frameNumber >= 10) - { - gmm = bgs.gmm(); - hmm = bgs.hmm(); - mrf.background2 = frame_data.Ptr(); - mrf.in_image = lowThresholdMask.Ptr(); - mrf.out_image = lowThresholdMask.Ptr(); - mrf.InitEvidence2(gmm,hmm,old_labeling); - mrf.ICM2(); - cvCopy(mrf.out_image, lowThresholdMask.Ptr()); - } + /* the code for MRF, it can be noted when using other methods */ + /************************************************************************/ + //the optimization process is done when the foreground detection is stable, + if (frameNumber >= 10) + { + gmm = bgs.gmm(); + hmm = bgs.hmm(); + mrf.background2 = frame_data.Ptr(); + mrf.in_image = lowThresholdMask.Ptr(); + mrf.out_image = lowThresholdMask.Ptr(); + mrf.InitEvidence2(gmm, hmm, old_labeling); + mrf.ICM2(); + cvCopy(mrf.out_image, lowThresholdMask.Ptr()); + } cvCopy(old, old_labeling); lowThresholdMask.Clear(); bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - if(showOutput) - cv::imshow("T2FMRF-UV", foreground); - - foreground.copyTo(img_output); + 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("T2FMRF-UV", img_foreground); +#endif + + img_foreground.copyTo(img_output); + img_background.copyTo(img_bgmodel); delete frame; frameNumber++; @@ -113,7 +114,7 @@ void T2FMRF_UV::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat & void T2FMRF_UV::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FMRF_UV.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); cvWriteReal(fs, "threshold", threshold); cvWriteReal(fs, "alpha", alpha); @@ -127,14 +128,14 @@ void T2FMRF_UV::saveConfig() void T2FMRF_UV::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/T2FMRF_UV.xml", 0, CV_STORAGE_READ); - - threshold = cvReadRealByName(fs, 0, "threshold", 9.0); - alpha = cvReadRealByName(fs, 0, "alpha", 0.01); - km = cvReadRealByName(fs, 0, "km", 2); - kv = cvReadRealByName(fs, 0, "kv", 0.9); - gaussians = cvReadIntByName(fs, 0, "gaussians", 3); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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); } diff --git a/package_bgs/T2FMRF_UV.h b/package_bgs/T2FMRF_UV.h new file mode 100644 index 0000000000000000000000000000000000000000..1c6917185365563acdc11d0aec41556ddd0ab429 --- /dev/null +++ b/package_bgs/T2FMRF_UV.h @@ -0,0 +1,64 @@ +/* +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/TwoPoints.cpp b/package_bgs/TwoPoints.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aee46848fd6b87082b0d42bb2bd4849aca319b9b --- /dev/null +++ b/package_bgs/TwoPoints.cpp @@ -0,0 +1,112 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..b42c2311a09c07d7ef3c4146f7c2cccc65769742 --- /dev/null +++ b/package_bgs/TwoPoints.h @@ -0,0 +1,46 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..d8ee86b49c7c21c82c8b47b018caff354a389d13 --- /dev/null +++ b/package_bgs/TwoPoints/two_points.cpp @@ -0,0 +1,394 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..a64152a2b6ca84857775ffd68c64461ab1fbe940 --- /dev/null +++ b/package_bgs/TwoPoints/two_points.h @@ -0,0 +1,50 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..0d3125f0759d14cc00a608350f97e8883e8a8c22 --- /dev/null +++ b/package_bgs/ViBe.cpp @@ -0,0 +1,98 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..c8014cbc15b99175947ed1115f3bd8b4144249d4 --- /dev/null +++ b/package_bgs/ViBe.h @@ -0,0 +1,52 @@ +/* +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/LICENSE b/package_bgs/ViBe/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..7f22a77a7a03a5c0dfe893128692c47b79a59d15 --- /dev/null +++ b/package_bgs/ViBe/LICENSE @@ -0,0 +1,44 @@ + Authors: + -------- + Olivier Barnich and + Marc Van Droogenbroeck <m.vandroogenbroeck@ulg.ac.be> + + Licence: + -------- + ViBe is covered by a patent (see http://www.ulg.ac.be/telecom/research/vibe). + We do not provide the source code but provide an object file and an interface. + + Permission to use ViBe without payment of fee is granted + for nonprofit educational and research purposes only. + + This work may not be copied or reproduced in whole or in part for any + purpose. + + Copying, reproduction, or republishing for any purpose shall require + a license. Please contact the author in such cases. + All the code is provided without any guarantee. + + + How to refer to us: + ------------------- + + If you want to refer to this work, please cite the following publications: + + Barnich and M. Van Droogenbroeck. ViBe: A universal background subtraction algorithm for video sequences. In IEEE Transactions on Image Processing, 20(6):1709-1724, June 2011. + +@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/81248/1/Barnich2011ViBe.pdf}, + doi = {10.1109/TIP.2010.2101613}, + url = {http://hdl.handle.net/2268/81248} +} + + diff --git a/package_bgs/ViBe/vibe-background-sequential.cpp b/package_bgs/ViBe/vibe-background-sequential.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4b91781d4662220f54eec84a6d74b1669d94ce7 --- /dev/null +++ b/package_bgs/ViBe/vibe-background-sequential.cpp @@ -0,0 +1,929 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..068c7d1b70365d88cb9931b8ce96e337ac0ca4f1 --- /dev/null +++ b/package_bgs/ViBe/vibe-background-sequential.h @@ -0,0 +1,293 @@ +/* +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/av/VuMeter.cpp b/package_bgs/VuMeter.cpp similarity index 52% rename from package_bgs/av/VuMeter.cpp rename to package_bgs/VuMeter.cpp index 29a1477f536a06058f76bc51384c12712b0db761..99baee9c28d48391d96634dd0931624050402226 100644 --- a/package_bgs/av/VuMeter.cpp +++ b/package_bgs/VuMeter.cpp @@ -16,9 +16,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "VuMeter.h" -VuMeter::VuMeter() : firstTime(true), showOutput(true), enableFilter(true), binSize(8), alpha(0.995), threshold(0.03) +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() @@ -32,69 +36,62 @@ VuMeter::~VuMeter() void VuMeter::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - else - frame = new IplImage(img_input); - - loadConfig(); + init(img_input, img_output, img_bgmodel); + frame = new IplImage(img_input); - if(firstTime) + if (firstTime) { bgs.SetAlpha(alpha); bgs.SetBinSize(binSize); bgs.SetThreshold(threshold); - gray = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1); - cvCvtColor(frame,gray,CV_RGB2GRAY); + gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1); + cvCvtColor(frame, gray, CV_RGB2GRAY); - background = cvCreateImage(cvGetSize(gray),IPL_DEPTH_8U,1); + background = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1); cvCopy(gray, background); - mask = cvCreateImage(cvGetSize(gray),IPL_DEPTH_8U,1); + mask = cvCreateImage(cvGetSize(gray), IPL_DEPTH_8U, 1); cvZero(mask); - - saveConfig(); } else - cvCvtColor(frame,gray,CV_RGB2GRAY); - - bgs.UpdateBackground(gray,background,mask); - cv::Mat img_foreground(mask); - cv::Mat img_bkg(background); + cvCvtColor(frame, gray, CV_RGB2GRAY); + + bgs.UpdateBackground(gray, background, mask); + img_foreground = cv::cvarrToMat(mask); + img_background = cv::cvarrToMat(background); - if(enableFilter) + if (enableFilter) { - cv::erode(img_foreground,img_foreground,cv::Mat()); + cv::erode(img_foreground, img_foreground, cv::Mat()); cv::medianBlur(img_foreground, img_foreground, 5); } - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) { - if(!img_foreground.empty()) - cv::imshow("VuMeter", img_foreground); - - if(!img_bkg.empty()) - cv::imshow("VuMeter Bkg Model", img_bkg); + cv::imshow("VuMeter", img_foreground); + cv::imshow("VuMeter Bkg Model", img_background); } +#endif img_foreground.copyTo(img_output); - img_bkg.copyTo(img_bgmodel); - + img_background.copyTo(img_bgmodel); + delete frame; firstTime = false; } void VuMeter::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/VuMeter.xml", 0, CV_STORAGE_WRITE); + 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); @@ -102,15 +99,15 @@ void VuMeter::saveConfig() void VuMeter::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/VuMeter.xml", 0, CV_STORAGE_READ); - - enableFilter = cvReadIntByName(fs, 0, "enableFilter", true); - - binSize = cvReadIntByName(fs, 0, "binSize", 8); - alpha = cvReadRealByName(fs, 0, "alpha", 0.995); - threshold = cvReadRealByName(fs, 0, "threshold", 0.03); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..fefd3ec724e3d57455abc2657540c498468bc468 --- /dev/null +++ b/package_bgs/VuMeter.h @@ -0,0 +1,52 @@ +/* +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/av/TBackground.cpp b/package_bgs/VuMeter/TBackground.cpp similarity index 77% rename from package_bgs/av/TBackground.cpp rename to package_bgs/VuMeter/TBackground.cpp index d05bbd27db892c71b2e9788c25278813039763ae..4e93729fa376894c1406a94314e74e5b8a15cec1 100644 --- a/package_bgs/av/TBackground.cpp +++ b/package_bgs/VuMeter/TBackground.cpp @@ -72,19 +72,19 @@ bool TBackground::isInitOk(IplImage * pSource, IplImage *pBackground, IplImage * { bool bResult = true; - if(pSource == NULL || pSource->nChannels != 1 || pSource->depth != IPL_DEPTH_8U) + if (pSource == NULL || pSource->nChannels != 1 || pSource->depth != IPL_DEPTH_8U) bResult = false; - if(bResult) + if (bResult) { int nbl, nbc; nbl = pSource->height; nbc = pSource->width; - - if(pBackground == NULL || pBackground->width != nbc || pBackground->height != nbl || pBackground->imageSize != pSource->imageSize) + + if (pBackground == NULL || pBackground->width != nbc || pBackground->height != nbl || pBackground->imageSize != pSource->imageSize) bResult = false; - - if(pMotionMask == NULL || pMotionMask->width != nbc || pMotionMask->height != nbl || pMotionMask->imageSize != pSource->imageSize) + + if (pMotionMask == NULL || pMotionMask->width != nbc || pMotionMask->height != nbl || pMotionMask->imageSize != pSource->imageSize) bResult = false; } @@ -100,7 +100,7 @@ IplImage *TBackground::CreateTestImg() { IplImage *pImage = cvCreateImage(cvSize(256, 256), IPL_DEPTH_8U, 3); - if(pImage != NULL) + if (pImage != NULL) cvSetZero(pImage); return pImage; @@ -112,33 +112,33 @@ int TBackground::UpdateTest(IplImage *pSource, IplImage *pBackground, IplImage * CvScalar Color; unsigned char *ptr; - if(pTest == NULL || !isInitOk(pSource, pBackground, pSource)) + if (pTest == NULL || !isInitOk(pSource, pBackground, pSource)) nErr = 1; - if(!nErr) + if (!nErr) { - if(pTest->width != 256 || pTest->height != 256 || pTest->nChannels != 3) + if (pTest->width != 256 || pTest->height != 256 || pTest->nChannels != 3) nErr = 1; - if(nX < 0 || nX > pSource->width || nY < 0 || nY > pSource->height) + if (nX < 0 || nX > pSource->width || nY < 0 || nY > pSource->height) nErr = 1; - switch(nInd) + switch (nInd) { - case 0 : Color = cvScalar(128, 0, 0); break; - case 1 : Color = cvScalar(0, 128, 0); break; - case 2 : Color = cvScalar(0, 0, 128); break; - default : nErr = 1; + case 0: Color = cvScalar(128, 0, 0); break; + case 1: Color = cvScalar(0, 128, 0); break; + case 2: Color = cvScalar(0, 0, 128); break; + default: nErr = 1; } } - if(!nErr) + if (!nErr) { int l, c; // recupere l'indice de la colonne ptr = (unsigned char *)(pTest->imageData); c = *ptr; - + // efface la colonne cvLine(pTest, cvPoint(c, 0), cvPoint(c, 255), cvScalar(0)); *ptr += 1; diff --git a/package_bgs/av/TBackground.h b/package_bgs/VuMeter/TBackground.h similarity index 99% rename from package_bgs/av/TBackground.h rename to package_bgs/VuMeter/TBackground.h index 463063f6e15046398dcfd5ea8867fd66bafedfd2..dbaaa6c3e672f7b3360bd7229a047e4e9351bab1 100644 --- a/package_bgs/av/TBackground.h +++ b/package_bgs/VuMeter/TBackground.h @@ -26,7 +26,6 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include <iostream> #include <opencv2/opencv.hpp> - class TBackground { public: diff --git a/package_bgs/av/TBackgroundVuMeter.cpp b/package_bgs/VuMeter/TBackgroundVuMeter.cpp similarity index 74% rename from package_bgs/av/TBackgroundVuMeter.cpp rename to package_bgs/VuMeter/TBackgroundVuMeter.cpp index 7fade7a5a2a10629df3d63798d347771749d50b2..c4fd7a7511fb08bd2604617a51aa775917d81a07 100644 --- a/package_bgs/av/TBackgroundVuMeter.cpp +++ b/package_bgs/VuMeter/TBackgroundVuMeter.cpp @@ -46,11 +46,11 @@ void TBackgroundVuMeter::Clear(void) { TBackground::Clear(); - if(m_pHist != NULL) + if (m_pHist != NULL) { - for(int i = 0; i < m_nBinCount; ++i) + for (int i = 0; i < m_nBinCount; ++i) { - if(m_pHist[i] != NULL) + if (m_pHist[i] != NULL) cvReleaseImage(&m_pHist[i]); } @@ -68,14 +68,14 @@ void TBackgroundVuMeter::Reset(void) TBackground::Reset(); - if(m_pHist != NULL) + 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) + for (int i = 0; i < m_nBinCount; ++i) { - if(m_pHist[i] != NULL) + if (m_pHist[i] != NULL) { cvSetZero(m_pHist[i]); cvAddS(m_pHist[i], cvScalar(fVal), m_pHist[i]); @@ -98,18 +98,18 @@ std::string TBackgroundVuMeter::GetParameterName(int nInd) nNb = TBackground::GetParameterCount(); - if(nInd >= nNb) + if (nInd >= nNb) { nInd -= nNb; - switch(nInd) + switch (nInd) { - case 0 : csResult = "Bin size"; break; - case 1 : csResult = "Alpha"; break; - case 2 : csResult = "Threshold"; break; + case 0: csResult = "Bin size"; break; + case 1: csResult = "Alpha"; break; + case 2: csResult = "Threshold"; break; } } - else + else csResult = TBackground::GetParameterName(nInd); return csResult; @@ -122,22 +122,22 @@ std::string TBackgroundVuMeter::GetParameterValue(int nInd) nNb = TBackground::GetParameterCount(); - if(nInd >= nNb) + if (nInd >= nNb) { nInd -= nNb; char buff[100]; - - switch(nInd) + + 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; + 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 + else csResult = TBackground::GetParameterValue(nInd); return csResult; @@ -151,19 +151,19 @@ int TBackgroundVuMeter::SetParameterValue(int nInd, std::string csNew) nNb = TBackground::GetParameterCount(); - if(nInd >= nNb) + if (nInd >= nNb) { nInd -= nNb; - switch(nInd) + 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; + 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 + else nErr = TBackground::SetParameterValue(nInd, csNew); return nErr; @@ -178,42 +178,42 @@ int TBackgroundVuMeter::Init(IplImage * pSource) nErr = TBackground::Init(pSource); - if(pSource == NULL) + if (pSource == NULL) nErr = 1; // calcul le nb de bin - if(!nErr) + if (!nErr) { nbl = pSource->height; nbc = pSource->width; m_nBinCount = (m_nBinSize != 0) ? 256 / m_nBinSize : 0; - if(m_nBinCount <= 0 || m_nBinCount > 256) + if (m_nBinCount <= 0 || m_nBinCount > 256) nErr = 1; } // creation du tableau de pointeur - if(!nErr) + if (!nErr) { m_pHist = new IplImage *[m_nBinCount]; - if(m_pHist == NULL) + if (m_pHist == NULL) nErr = 1; } // creation des images - if(!nErr) + if (!nErr) { - for(int i = 0; i < m_nBinCount; ++i) + for (int i = 0; i < m_nBinCount; ++i) { m_pHist[i] = cvCreateImage(cvSize(nbc, nbl), IPL_DEPTH_32F, 1); - if(m_pHist[i] == NULL) + if (m_pHist[i] == NULL) nErr = 1; } } - if(!nErr) + if (!nErr) Reset(); else Clear(); @@ -228,28 +228,28 @@ bool TBackgroundVuMeter::isInitOk(IplImage * pSource, IplImage *pBackground, Ipl bResult = TBackground::isInitOk(pSource, pBackground, pMotionMask); - if(pSource == NULL) + if (pSource == NULL) bResult = false; - if(m_nBinSize == 0) + if (m_nBinSize == 0) bResult = false; - if(bResult) + if (bResult) { i = (m_nBinSize != 0) ? 256 / m_nBinSize : 0; - if(i != m_nBinCount || m_pHist == NULL) + if (i != m_nBinCount || m_pHist == NULL) bResult = false; } - if(bResult) + if (bResult) { int nbl = pSource->height; int nbc = pSource->width; - for(i = 0; i < m_nBinCount; ++i) + for (i = 0; i < m_nBinCount; ++i) { - if(m_pHist[i] == NULL || m_pHist[i]->width != nbc || m_pHist[i]->height != nbl) + if (m_pHist[i] == NULL || m_pHist[i]->width != nbc || m_pHist[i]->height != nbl) bResult = false; } } @@ -263,10 +263,10 @@ int TBackgroundVuMeter::UpdateBackground(IplImage *pSource, IplImage *pBackgroun unsigned char *ptrs, *ptrb, *ptrm; float *ptr1, *ptr2; - if(!isInitOk(pSource, pBackground, pMotionMask)) + if (!isInitOk(pSource, pBackground, pMotionMask)) nErr = Init(pSource); - - if(!nErr) + + if (!nErr) { m_nCount++; int nbc = pSource->width; @@ -274,23 +274,23 @@ int TBackgroundVuMeter::UpdateBackground(IplImage *pSource, IplImage *pBackgroun unsigned char v = m_nBinSize; // multiplie tout par alpha - for(int i = 0; i < m_nBinCount; ++i) + 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) + 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++) + for (int c = 0; c < nbc; ++c, ptrs++, ptrb++, ptrm++) { - // recherche le bin � augmenter + // recherche le bin à augmenter int i = *ptrs / v; - - if(i < 0 || i >= m_nBinCount) + + if (i < 0 || i >= m_nBinCount) i = 0; - + ptr1 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l); ptr1 += c; @@ -299,19 +299,19 @@ int TBackgroundVuMeter::UpdateBackground(IplImage *pSource, IplImage *pBackgroun // recherche le bin du fond actuel i = *ptrb / v; - - if(i < 0 || i >= m_nBinCount) + + if (i < 0 || i >= m_nBinCount) i = 0; - + ptr2 = (float *)(m_pHist[i]->imageData + m_pHist[i]->widthStep * l); ptr2 += c; - if(*ptr2 < *ptr1) + if (*ptr2 < *ptr1) *ptrb = *ptrs; } } - if(m_nCount < 5) + if (m_nCount < 5) cvSetZero(pMotionMask); } @@ -322,10 +322,10 @@ IplImage *TBackgroundVuMeter::CreateTestImg() { IplImage *pImage = NULL; - if(m_nBinCount > 0) + if (m_nBinCount > 0) pImage = cvCreateImage(cvSize(m_nBinCount, 100), IPL_DEPTH_8U, 3); - if(pImage != NULL) + if (pImage != NULL) cvSetZero(pImage); return pImage; @@ -336,31 +336,31 @@ int TBackgroundVuMeter::UpdateTest(IplImage *pSource, IplImage *pBackground, Ipl int nErr = 0; float *ptrf; - if(pTest == NULL || !isInitOk(pSource, pBackground, pSource)) + if (pTest == NULL || !isInitOk(pSource, pBackground, pSource)) nErr = 1; - if(!nErr) + if (!nErr) { int nbl = pTest->height; int nbc = pTest->width; - if(nbl != 100 || nbc != m_nBinCount) + if (nbl != 100 || nbc != m_nBinCount) nErr = 1; - if(nX < 0 || nX >= pSource->width || nY < 0 || nY >= pSource->height) + if (nX < 0 || nX >= pSource->width || nY < 0 || nY >= pSource->height) nErr = 1; } - if(!nErr) + if (!nErr) { cvSetZero(pTest); - for(int i = 0; i < m_nBinCount; ++i) + 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) { + if (*ptrf >= 0 || *ptrf <= 1.0) { cvLine(pTest, cvPoint(i, 100), cvPoint(i, (int)(100.0 * (1.0 - *ptrf))), cvScalar(0, 255, 0)); } } diff --git a/package_bgs/av/TBackgroundVuMeter.h b/package_bgs/VuMeter/TBackgroundVuMeter.h similarity index 95% rename from package_bgs/av/TBackgroundVuMeter.h rename to package_bgs/VuMeter/TBackgroundVuMeter.h index 1a19324f08c8d20b4bb2fd972a9920e73b2adae8..36fe0d0b99ad0b8da8c4696cd931ecec1713bad6 100644 --- a/package_bgs/av/TBackgroundVuMeter.h +++ b/package_bgs/VuMeter/TBackgroundVuMeter.h @@ -44,13 +44,13 @@ public: 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 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 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 void SetThreshold(double fNew) { m_fThreshold = (fNew > 0.0 && fNew < 1.0) ? fNew : 0.03; } inline double GetThreshold() { return m_fThreshold; } protected: diff --git a/package_bgs/WeightedMovingMeanBGS.cpp b/package_bgs/WeightedMovingMean.cpp similarity index 51% rename from package_bgs/WeightedMovingMeanBGS.cpp rename to package_bgs/WeightedMovingMean.cpp index 841c467393c3012aff42eac1a36b44321b024b80..3a427fc0e6926b721f809fca66a86b05841a29fd 100644 --- a/package_bgs/WeightedMovingMeanBGS.cpp +++ b/package_bgs/WeightedMovingMean.cpp @@ -14,77 +14,72 @@ 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 "WeightedMovingMeanBGS.h" +#include "WeightedMovingMean.h" -WeightedMovingMeanBGS::WeightedMovingMeanBGS() : firstTime(true), enableWeight(true), enableThreshold(true), threshold(15), showOutput(true), showBackground(false) +using namespace bgslibrary::algorithms; + +WeightedMovingMean::WeightedMovingMean() : + enableWeight(true), enableThreshold(true), threshold(15) { - std::cout << "WeightedMovingMeanBGS()" << std::endl; + std::cout << "WeightedMovingMean()" << std::endl; + setup("./config/WeightedMovingMean.xml"); } -WeightedMovingMeanBGS::~WeightedMovingMeanBGS() +WeightedMovingMean::~WeightedMovingMean() { - std::cout << "~WeightedMovingMeanBGS()" << std::endl; + std::cout << "~WeightedMovingMean()" << std::endl; } -void WeightedMovingMeanBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void WeightedMovingMean::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); + init(img_input, img_output, img_bgmodel); - if(img_input_prev_1.empty()) - { + if (img_input_prev_1.empty()) { img_input.copyTo(img_input_prev_1); return; } - if(img_input_prev_2.empty()) - { + if (img_input_prev_2.empty()) { img_input_prev_1.copyTo(img_input_prev_2); img_input.copyTo(img_input_prev_1); return; } - + cv::Mat img_input_f(img_input.size(), CV_32F); - img_input.convertTo(img_input_f, CV_32F, 1./255.); + img_input.convertTo(img_input_f, CV_32F, 1. / 255.); cv::Mat img_input_prev_1_f(img_input.size(), CV_32F); - img_input_prev_1.convertTo(img_input_prev_1_f, CV_32F, 1./255.); + img_input_prev_1.convertTo(img_input_prev_1_f, CV_32F, 1. / 255.); cv::Mat img_input_prev_2_f(img_input.size(), CV_32F); - img_input_prev_2.convertTo(img_input_prev_2_f, CV_32F, 1./255.); + img_input_prev_2.convertTo(img_input_prev_2_f, CV_32F, 1. / 255.); cv::Mat img_background_f(img_input.size(), CV_32F); - - if(enableWeight) + + if (enableWeight) img_background_f = ((img_input_f * 0.5) + (img_input_prev_1_f * 0.3) + (img_input_prev_2_f * 0.2)); else - img_background_f = ((img_input_f) + (img_input_prev_1_f) + (img_input_prev_2_f)) / 3.0; - - cv::Mat img_background(img_background_f.size(), CV_8U); + img_background_f = ((img_input_f)+(img_input_prev_1_f)+(img_input_prev_2_f)) / 3.0; double minVal, maxVal; minVal = 0.; maxVal = 1.; - img_background_f.convertTo(img_background, CV_8U, 255.0/(maxVal - minVal), -minVal); - - if(showBackground) - cv::imshow("W Moving Mean BG Model", img_background); + img_background_f.convertTo(img_background, CV_8U, 255.0 / (maxVal - minVal), -minVal); - cv::Mat img_foreground; cv::absdiff(img_input, img_background, img_foreground); - if(img_foreground.channels() == 3) + if (img_foreground.channels() == 3) cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY); - if(enableThreshold) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) + { cv::imshow("W Moving Mean FG Mask", img_foreground); + cv::imshow("W Moving Mean BG Model", img_background); + } +#endif img_foreground.copyTo(img_output); img_background.copyTo(img_bgmodel); @@ -95,28 +90,26 @@ void WeightedMovingMeanBGS::process(const cv::Mat &img_input, cv::Mat &img_outpu firstTime = false; } -void WeightedMovingMeanBGS::saveConfig() +void WeightedMovingMean::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/WeightedMovingMeanBGS.xml", 0, CV_STORAGE_WRITE); + 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); - cvWriteInt(fs, "showBackground", showBackground); cvReleaseFileStorage(&fs); } -void WeightedMovingMeanBGS::loadConfig() +void WeightedMovingMean::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/WeightedMovingMeanBGS.xml", 0, CV_STORAGE_READ); - - enableWeight = cvReadIntByName(fs, 0, "enableWeight", true); - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - showBackground = cvReadIntByName(fs, 0, "showBackground", false); + 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); -} \ No newline at end of file +} diff --git a/package_bgs/WeightedMovingMean.h b/package_bgs/WeightedMovingMean.h new file mode 100644 index 0000000000000000000000000000000000000000..4a1a3c5fddb5c68c5c4eb8025f2427b143ff6b3a --- /dev/null +++ b/package_bgs/WeightedMovingMean.h @@ -0,0 +1,45 @@ +/* +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/WeightedMovingVarianceBGS.cpp b/package_bgs/WeightedMovingVariance.cpp similarity index 62% rename from package_bgs/WeightedMovingVarianceBGS.cpp rename to package_bgs/WeightedMovingVariance.cpp index 0317a3cfe24438995a6f9a538140539e401ce0e9..2855a92629094c5e6314b351181d9d7cb806032d 100644 --- a/package_bgs/WeightedMovingVarianceBGS.cpp +++ b/package_bgs/WeightedMovingVariance.cpp @@ -14,68 +14,61 @@ 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 "WeightedMovingVarianceBGS.h" +#include "WeightedMovingVariance.h" -WeightedMovingVarianceBGS::WeightedMovingVarianceBGS() : firstTime(true), enableWeight(true), - enableThreshold(true), threshold(15), showOutput(true) +using namespace bgslibrary::algorithms; + +WeightedMovingVariance::WeightedMovingVariance() : + enableWeight(true), enableThreshold(true), threshold(15) { - std::cout << "WeightedMovingVarianceBGS()" << std::endl; + std::cout << "WeightedMovingVariance()" << std::endl; + setup("./config/WeightedMovingVariance.xml"); } -WeightedMovingVarianceBGS::~WeightedMovingVarianceBGS() +WeightedMovingVariance::~WeightedMovingVariance() { - std::cout << "~WeightedMovingVarianceBGS()" << std::endl; + std::cout << "~WeightedMovingVariance()" << std::endl; } -void WeightedMovingVarianceBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +void WeightedMovingVariance::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) { - if(img_input.empty()) - return; - - loadConfig(); + init(img_input, img_output, img_bgmodel); - if(firstTime) - saveConfig(); - - if(img_input_prev_1.empty()) - { + if (img_input_prev_1.empty()) { img_input.copyTo(img_input_prev_1); return; } - if(img_input_prev_2.empty()) - { + if (img_input_prev_2.empty()) { img_input_prev_1.copyTo(img_input_prev_2); img_input.copyTo(img_input_prev_1); return; } cv::Mat img_input_f(img_input.size(), CV_32F); - img_input.convertTo(img_input_f, CV_32F, 1./255.); + img_input.convertTo(img_input_f, CV_32F, 1. / 255.); cv::Mat img_input_prev_1_f(img_input.size(), CV_32F); - img_input_prev_1.convertTo(img_input_prev_1_f, CV_32F, 1./255.); + img_input_prev_1.convertTo(img_input_prev_1_f, CV_32F, 1. / 255.); cv::Mat img_input_prev_2_f(img_input.size(), CV_32F); - img_input_prev_2.convertTo(img_input_prev_2_f, CV_32F, 1./255.); - - cv::Mat img_foreground; + img_input_prev_2.convertTo(img_input_prev_2_f, CV_32F, 1. / 255.); // Weighted mean cv::Mat img_mean_f(img_input.size(), CV_32F); - - if(enableWeight) + + if (enableWeight) img_mean_f = ((img_input_f * 0.5) + (img_input_prev_1_f * 0.3) + (img_input_prev_2_f * 0.2)); else img_mean_f = ((img_input_f * 0.3) + (img_input_prev_1_f * 0.3) + (img_input_prev_2_f * 0.3)); - + // Weighted variance cv::Mat img_1_f(img_input.size(), CV_32F); cv::Mat img_2_f(img_input.size(), CV_32F); cv::Mat img_3_f(img_input.size(), CV_32F); cv::Mat img_4_f(img_input.size(), CV_32F); - if(enableWeight) + if (enableWeight) { img_1_f = computeWeightedVariance(img_input_f, img_mean_f, 0.5); img_2_f = computeWeightedVariance(img_input_prev_1_f, img_mean_f, 0.3); @@ -89,73 +82,71 @@ void WeightedMovingVarianceBGS::process(const cv::Mat &img_input, cv::Mat &img_o img_3_f = computeWeightedVariance(img_input_prev_2_f, img_mean_f, 0.3); img_4_f = (img_1_f + img_2_f + img_3_f); } - + // Standard deviation cv::Mat img_sqrt_f(img_input.size(), CV_32F); cv::sqrt(img_4_f, img_sqrt_f); cv::Mat img_sqrt(img_input.size(), CV_8U); double minVal, maxVal; minVal = 0.; maxVal = 1.; - img_sqrt_f.convertTo(img_sqrt, CV_8U, 255.0/(maxVal - minVal), -minVal); + img_sqrt_f.convertTo(img_sqrt, CV_8U, 255.0 / (maxVal - minVal), -minVal); img_sqrt.copyTo(img_foreground); - if(img_foreground.channels() == 3) + if (img_foreground.channels() == 3) cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY); - if(enableThreshold) + if (enableThreshold) cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY); - if(showOutput) +#ifndef MEX_COMPILE_FLAG + if (showOutput) cv::imshow("W Moving Variance", img_foreground); +#endif img_foreground.copyTo(img_output); + img_background = cv::Mat::zeros(img_input.size(), img_input.type()); + img_background.copyTo(img_bgmodel); + img_input_prev_1.copyTo(img_input_prev_2); img_input.copyTo(img_input_prev_1); - - firstTime = false; -} -//unused -cv::Mat WeightedMovingVarianceBGS::computeWeightedMean(const std::vector<cv::Mat> &v_img_input_f, const std::vector<double> &weights) -{ - cv::Mat img; - return img; + firstTime = false; } -cv::Mat WeightedMovingVarianceBGS::computeWeightedVariance(const cv::Mat &img_input_f, const cv::Mat &img_mean_f, const double weight) +cv::Mat WeightedMovingVariance::computeWeightedVariance(const cv::Mat &img_input_f, const cv::Mat &img_mean_f, const double weight) { //ERROR in return (weight * ((cv::abs(img_input_f - img_mean_f))^2.)); - + cv::Mat img_f_absdiff(img_input_f.size(), CV_32F); cv::absdiff(img_input_f, img_mean_f, img_f_absdiff); cv::Mat img_f_pow(img_input_f.size(), CV_32F); cv::pow(img_f_absdiff, 2.0, img_f_pow); cv::Mat img_f = weight * img_f_pow; - + return img_f; } -void WeightedMovingVarianceBGS::saveConfig() +void WeightedMovingVariance::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/WeightedMovingVarianceBGS.xml", 0, CV_STORAGE_WRITE); + 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 WeightedMovingVarianceBGS::loadConfig() +void WeightedMovingVariance::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/WeightedMovingVarianceBGS.xml", 0, CV_STORAGE_READ); - - enableWeight = cvReadIntByName(fs, 0, "enableWeight", true); - enableThreshold = cvReadIntByName(fs, 0, "enableThreshold", true); - threshold = cvReadIntByName(fs, 0, "threshold", 15); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - + 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); } diff --git a/package_bgs/WeightedMovingVariance.h b/package_bgs/WeightedMovingVariance.h new file mode 100644 index 0000000000000000000000000000000000000000..79198b4a9e2fadd0c21f701e0b45e67a9b3dc488 --- /dev/null +++ b/package_bgs/WeightedMovingVariance.h @@ -0,0 +1,46 @@ +/* +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/WeightedMovingVarianceBGS.h b/package_bgs/WeightedMovingVarianceBGS.h deleted file mode 100644 index 88c2ec821399aea86f6895e4c23263c3bcb996bb..0000000000000000000000000000000000000000 --- a/package_bgs/WeightedMovingVarianceBGS.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "IBGS.h" - -class WeightedMovingVarianceBGS : public IBGS -{ -private: - bool firstTime; - cv::Mat img_input_prev_1; - cv::Mat img_input_prev_2; - bool enableWeight; - bool enableThreshold; - int threshold; - bool showOutput; - -public: - WeightedMovingVarianceBGS(); - ~WeightedMovingVarianceBGS(); - - cv::Mat computeWeightedMean(const std::vector<cv::Mat> &v_img_input_f, const std::vector<double> &weights); - cv::Mat computeWeightedVariance(const cv::Mat &img_input_f, const cv::Mat &img_mean_f, const double weight); - - 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.cpp b/package_bgs/_template_/Amber.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e29ac07369b7a84c16b6bbab0e03cdcf23344d2 --- /dev/null +++ b/package_bgs/_template_/Amber.cpp @@ -0,0 +1,112 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..37f0f8deca5fc5c0d32ce8614bd0820be1f3dfd2 --- /dev/null +++ b/package_bgs/_template_/Amber.h @@ -0,0 +1,45 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..10d55884f8d33c9980d71f653e7c3b26227e7f8d --- /dev/null +++ b/package_bgs/_template_/MyBGS.cpp @@ -0,0 +1,44 @@ +/* +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/ck/LbpMrf.h b/package_bgs/_template_/MyBGS.h similarity index 65% rename from package_bgs/ck/LbpMrf.h rename to package_bgs/_template_/MyBGS.h index 6fd72673a16d0f649b58d08b9f16b6ca5b786c2d..dea2a2fa3bbc2163a9afc822351f8c2f9bcbfb3e 100644 --- a/package_bgs/ck/LbpMrf.h +++ b/package_bgs/_template_/MyBGS.h @@ -16,29 +16,28 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #pragma once -#include <iostream> #include <opencv2/opencv.hpp> #include "../IBGS.h" -class MotionDetection; - -class LbpMrf : public IBGS +namespace bgslibrary { -private: - bool firstTime; - MotionDetection* Detector; - cv::Mat img_foreground; - cv::Mat img_segmentation; - bool showOutput; - -public: - LbpMrf(); - ~LbpMrf(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; + 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 new file mode 100644 index 0000000000000000000000000000000000000000..00bdfb14a5006b825448657d8f565469eaa6dc93 --- /dev/null +++ b/package_bgs/_template_/amber/amber.c @@ -0,0 +1,80 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..02061795f1ef211b8907c3d16f43123e6099d380 --- /dev/null +++ b/package_bgs/_template_/amber/amber.h @@ -0,0 +1,64 @@ +/* +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/ae/KDE.h b/package_bgs/ae/KDE.h deleted file mode 100644 index adcc659f1a0bc93f00962eb4039dcb3a751e0724..0000000000000000000000000000000000000000 --- a/package_bgs/ae/KDE.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "NPBGSubtractor.h" -#include "../IBGS.h" - -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; - bool firstTime; - bool showOutput; - - cv::Mat img_foreground; - 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/ae/NPBGSubtractor.cpp b/package_bgs/ae/NPBGSubtractor.cpp deleted file mode 100644 index 3f0620f6281e24f6a3eddd34024835bb0adc3b29..0000000000000000000000000000000000000000 --- a/package_bgs/ae/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/av/VuMeter.h b/package_bgs/av/VuMeter.h deleted file mode 100644 index a2334cafdc99e695a8d36dcdef200ceaf4d80d91..0000000000000000000000000000000000000000 --- a/package_bgs/av/VuMeter.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "TBackgroundVuMeter.h" -#include "../IBGS.h" - -class VuMeter : public IBGS -{ -private: - TBackgroundVuMeter bgs; - - IplImage *frame; - IplImage *gray; - IplImage *background; - IplImage *mask; - - bool firstTime; - bool showOutput; - 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/bgslibrary.h b/package_bgs/bgslibrary.h new file mode 100644 index 0000000000000000000000000000000000000000..3895ba85b6f9e646e76965506563f3a0c635eb26 --- /dev/null +++ b/package_bgs/bgslibrary.h @@ -0,0 +1,65 @@ +/* +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 "MixtureOfGaussianV2.h" +#include "AdaptiveBackgroundLearning.h" +#include "AdaptiveSelectiveBackgroundLearning.h" +#include "KNN.h" // Only for OpenCV >= 3 +#include "GMG.h" // Only for OpenCV >= 2.4.3 +#include "DPAdaptiveMedian.h" +#include "DPGrimsonGMM.h" +#include "DPZivkovicAGMM.h" +#include "DPMean.h" +#include "DPWrenGA.h" +#include "DPPratiMediod.h" +#include "DPEigenbackground.h" +#include "DPTexture.h" +#include "T2FGMM_UM.h" +#include "T2FGMM_UV.h" +#include "T2FMRF_UM.h" +#include "T2FMRF_UV.h" +#include "FuzzySugenoIntegral.h" +#include "FuzzyChoquetIntegral.h" +#include "LBSimpleGaussian.h" +#include "LBFuzzyGaussian.h" +#include "LBMixtureOfGaussians.h" +#include "LBAdaptiveSOM.h" +#include "LBFuzzyAdaptiveSOM.h" +#include "LBP_MRF.h" +#include "MultiLayer.h" +#include "PixelBasedAdaptiveSegmenter.h" +#include "VuMeter.h" +#include "KDE.h" +#include "IndependentMultimodal.h" +#include "MultiCue.h" +#include "SigmaDelta.h" +#include "SuBSENSE.h" +#include "LOBSTER.h" +#include "PAWCS.h" +#include "TwoPoints.h" +#include "ViBe.h" + +//#include "_template_/MyBGS.h" +//#include "_template_/Amber.h" + +using namespace bgslibrary::algorithms; diff --git a/package_bgs/bl/SigmaDeltaBGS.cpp b/package_bgs/bl/SigmaDeltaBGS.cpp deleted file mode 100644 index a9c7914f427dc5cecd75b2fa6e7fa51247096d2b..0000000000000000000000000000000000000000 --- a/package_bgs/bl/SigmaDeltaBGS.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "SigmaDeltaBGS.h" - -SigmaDeltaBGS::SigmaDeltaBGS() : -firstTime(true), -ampFactor(1), -minVar(15), -maxVar(255), -algorithm(sdLaMa091New()), -showOutput(true) { - - applyParams(); - std::cout << "SigmaDeltaBGS()" << std::endl; -} - -SigmaDeltaBGS::~SigmaDeltaBGS() { - sdLaMa091Free(algorithm); - std::cout << "~SigmaDeltaBGS()" << std::endl; -} - -void SigmaDeltaBGS::process( - const cv::Mat &img_input, - cv::Mat &img_output, - cv::Mat &img_bgmodel - ) { - if (img_input.empty()) - return; - - loadConfig(); - - if (firstTime) { - saveConfig(); - sdLaMa091AllocInit_8u_C3R(algorithm, img_input.data, img_input.cols, img_input.rows, img_input.step); - - firstTime = false; - return; - } - - img_output = cv::Mat(img_input.rows, img_input.cols, CV_8UC1); - 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_output.data; - - for (size_t i = 0; i < img_output.total(); ++i) { - *outBuffer = *tmpBuffer; - - ++outBuffer; - tmpBuffer += img_output_tmp.channels(); - } - - if (showOutput) - cv::imshow("Sigma-Delta", img_output); -} - -void SigmaDeltaBGS::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/SigmaDeltaBGS.xml", 0, CV_STORAGE_WRITE); - - cvWriteInt(fs, "ampFactor", ampFactor); - cvWriteInt(fs, "minVar", minVar); - cvWriteInt(fs, "maxVar", maxVar); - cvWriteInt(fs, "showOutput", showOutput); - - cvReleaseFileStorage(&fs); -} - -void SigmaDeltaBGS::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/SigmaDeltaBGS.xml", 0, CV_STORAGE_READ); - - ampFactor = cvReadIntByName(fs, 0, "ampFactor", 1); - minVar = cvReadIntByName(fs, 0, "minVar", 15); - maxVar = cvReadIntByName(fs, 0, "maxVar", 255); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - applyParams(); - - cvReleaseFileStorage(&fs); -} - -void SigmaDeltaBGS::applyParams() { - sdLaMa091SetAmplificationFactor(algorithm, ampFactor); - sdLaMa091SetMinimalVariance(algorithm, minVar); - sdLaMa091SetMaximalVariance(algorithm, maxVar); -} diff --git a/package_bgs/bl/SigmaDeltaBGS.h b/package_bgs/bl/SigmaDeltaBGS.h deleted file mode 100644 index a4be2711d634982d9e3af8266476e91ec85efeaf..0000000000000000000000000000000000000000 --- a/package_bgs/bl/SigmaDeltaBGS.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -//extern "C" { -#include "sdLaMa091.h" -//} - -class SigmaDeltaBGS : public IBGS { -private: - - bool firstTime; - unsigned int ampFactor; - unsigned int minVar; - unsigned int maxVar; - sdLaMa091_t* algorithm; - bool showOutput; - -public: - - SigmaDeltaBGS(); - - ~SigmaDeltaBGS(); - - 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/bl/stdbool.h b/package_bgs/bl/stdbool.h deleted file mode 100644 index abeb3b877f62de18eec0e6a32694d80ef5ced273..0000000000000000000000000000000000000000 --- a/package_bgs/bl/stdbool.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -//#ifndef false -// #define false 0 -//#endif - -//#ifndef true -// #define true 1 -//#endif - -//#ifndef bool -// #define bool int -//#endif - -// #ifdef _WIN32 -// #endif diff --git a/package_bgs/ck/MEDefs.cpp b/package_bgs/ck/MEDefs.cpp deleted file mode 100644 index 93473537cbd5b7de0ce6ffc1dcc17f380004b91f..0000000000000000000000000000000000000000 --- a/package_bgs/ck/MEDefs.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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/ck/README.TXT b/package_bgs/ck/README.TXT deleted file mode 100644 index d76c6a3438d3b26fb98b3355f6359b2474ccea34..0000000000000000000000000000000000000000 --- a/package_bgs/ck/README.TXT +++ /dev/null @@ -1,135 +0,0 @@ -################################################################### -# # -# MAXFLOW - software for computing mincut/maxflow in a graph # -# Version 2.2 # -# http://www.cs.cornell.edu/People/vnk/software.html # -# # -# Yuri Boykov (yuri@csd.uwo.ca) # -# Vladimir Kolmogorov (vnk@cs.cornell.edu) # -# 2001 # -# # -################################################################### - -1. Introduction. - -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. - -Tested under windows, Visual C++ 6.0 compiler and unix (SunOS 5.8 -and RedHat Linux 7.0, GNU c++ compiler). - -################################################################## - -2. License. - - 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 - -################################################################## - -3. Graph representation. - -There are two versions of the algorithm using different -graph representations (adjacency list and forward star). -The former one uses more than twice as much memory as the -latter one but is 10-20% faster. - -Memory allocation (assuming that all capacities are 'short' - 2 bytes): - - | Nodes | Arcs ------------------------------------------- -Adjacency list | *24 bytes | *14 bytes -Forward star | *28 bytes | 6 bytes - -(* means that often it should be rounded up to be a multiple of 4 -- some compilers (e.g. Visual C++) seem to round up elements -of arrays unless the are structures containing only char[].) - -Note that arcs are always added in pairs - in forward and reverse directions. -Arcs between nodes and terminals (the source and the sink) are -not stored as arcs, but rather as a part of nodes. - -The assumption for the forward star representation is that -the maximum number of arcs per node (except the source -and the sink) is much less than ARC_BLOCK_SIZE (1024 by default). - -Both versions have the same interface. - -################################################################## - -4. Example usage. - -This section shows how to use the library to compute -a minimum cut on the following graph: - - SOURCE - / \ - 1/ \2 - / 3 \ - node0 -----> node1 - | <----- | - | 4 | - \ / - 5\ /6 - \ / - SINK - -/////////////////////////////////////////////////// - -#include <stdio.h> -#include "graph.h" - -void main() -{ - Graph::node_id nodes[2]; - Graph *g = new Graph(); - - nodes[0] = g -> add_node(); - nodes[1] = g -> add_node(); - g -> set_tweights(nodes[0], 1, 5); - g -> set_tweights(nodes[1], 2, 6); - g -> add_edge(nodes[0], nodes[1], 3, 4); - - Graph::flowtype flow = g -> maxflow(); - - printf("Flow = %d\n", flow); - printf("Minimum cut:\n"); - if (g->what_segment(nodes[0]) == Graph::SOURCE) - printf("node0 is in the SOURCE set\n"); - else - printf("node0 is in the SINK set\n"); - if (g->what_segment(nodes[1]) == Graph::SOURCE) - printf("node1 is in the SOURCE set\n"); - else - printf("node1 is in the SINK set\n"); - - delete g; -} - -/////////////////////////////////////////////////// diff --git a/package_bgs/db/IndependentMultimodalBGS.cpp b/package_bgs/db/IndependentMultimodalBGS.cpp deleted file mode 100644 index 5312075379640840adfa22993158942cf6fe7c86..0000000000000000000000000000000000000000 --- a/package_bgs/db/IndependentMultimodalBGS.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "IndependentMultimodalBGS.h" - -IndependentMultimodalBGS::IndependentMultimodalBGS() : fps(10), firstTime(true), showOutput(true){ - pIMBS = new BackgroundSubtractorIMBS(fps); -} -IndependentMultimodalBGS::~IndependentMultimodalBGS(){ - delete pIMBS; -} - -void IndependentMultimodalBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) -{ - if(img_input.empty()) - return; - - loadConfig(); - - if (firstTime) - saveConfig(); - - //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); - - if (showOutput) - { - cv::imshow("IMBS FG", img_foreground); - cv::imshow("IMBS BG", img_background); - } - - firstTime = false; -} - -void IndependentMultimodalBGS::saveConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/IndependentMultimodalBGS.xml", 0, CV_STORAGE_WRITE); - - cvWriteInt(fs, "showOutput", showOutput); - - cvReleaseFileStorage(&fs); -} - -void IndependentMultimodalBGS::loadConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/IndependentMultimodalBGS.xml", 0, CV_STORAGE_READ); - - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - cvReleaseFileStorage(&fs); -} diff --git a/package_bgs/db/IndependentMultimodalBGS.h b/package_bgs/db/IndependentMultimodalBGS.h deleted file mode 100644 index 64b83bde099398725cffea0dc26bf69843ae61f7..0000000000000000000000000000000000000000 --- a/package_bgs/db/IndependentMultimodalBGS.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include <opencv2/opencv.hpp> - - -#include "imbs.hpp" - -#include "../IBGS.h" - -class IndependentMultimodalBGS : public IBGS -{ -private: - BackgroundSubtractorIMBS* pIMBS; - int fps; - bool firstTime; - cv::Mat img_foreground; - cv::Mat img_background; - bool showOutput; - -public: - IndependentMultimodalBGS(); - ~IndependentMultimodalBGS(); - - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file diff --git a/package_bgs/dp/AdaptiveMedianBGS.cpp b/package_bgs/dp/AdaptiveMedianBGS.cpp index 16b3988c17c67cc60531f2cb9ea135d1336c6adc..da1add9124b0e3488df2fb2a57f4a2704f992c5c 100644 --- a/package_bgs/dp/AdaptiveMedianBGS.cpp +++ b/package_bgs/dp/AdaptiveMedianBGS.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * AdaptiveMedianBGS.cpp * -* Purpose: Implementation of the simple adaptive median background +* Purpose: Implementation of the simple adaptive median background * subtraction algorithm described in: * "Segmentation and tracking of piglets in images" * by McFarlane and Schofield @@ -37,77 +37,77 @@ using namespace Algorithms::BackgroundSubtraction; void AdaptiveMedianBGS::Initalize(const BgsParams& param) { - m_params = (AdaptiveMedianParams&)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)); + m_median = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); + cvSet(m_median.Ptr(), CV_RGB(BACKGROUND, BACKGROUND, BACKGROUND)); } RgbImage* AdaptiveMedianBGS::Background() { - return &m_median; + return &m_median; } void AdaptiveMedianBGS::InitModel(const RgbImage& data) { - // initialize the background model - for (unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - m_median(r,c) = data(r,c); - } - } + // initialize the background model + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + m_median(r, c) = data(r, c); + } + } } -void AdaptiveMedianBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void AdaptiveMedianBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - if(frame_num % m_params.SamplingRate() == 1) - { - // update background model - for (unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - // perform conditional updating only if we are passed the learning phase - if(update_mask(r,c) == BACKGROUND || frame_num < m_params.LearningFrames()) - { - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - if(data(r,c,ch) > m_median(r,c,ch)) - { - m_median(r,c,ch)++; - } - else if(data(r,c,ch) < m_median(r,c,ch)) - { - m_median(r,c,ch)--; - } - } - } - } - } - } + if (frame_num % m_params.SamplingRate() == 1) + { + // update background model + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + // perform conditional updating only if we are passed the learning phase + if (update_mask(r, c) == BACKGROUND || frame_num < m_params.LearningFrames()) + { + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + if (data(r, c, ch) > m_median(r, c, ch)) + { + m_median(r, c, ch)++; + } + else if (data(r, c, ch) < m_median(r, c, ch)) + { + m_median(r, c, ch)--; + } + } + } + } + } + } } -void AdaptiveMedianBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, - unsigned char& low_threshold, unsigned char& high_threshold) +void AdaptiveMedianBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, + unsigned char& low_threshold, unsigned char& high_threshold) { - // perform background subtraction - low_threshold = high_threshold = FOREGROUND; - - int diffR = abs(pixel(0) - m_median(r,c,0)); - int diffG = abs(pixel(1) - m_median(r,c,1)); - int diffB = abs(pixel(2) - m_median(r,c,2)); - - if(diffR <= m_params.LowThreshold() && diffG <= m_params.LowThreshold() && diffB <= m_params.LowThreshold()) - { - low_threshold = BACKGROUND; - } - - if(diffR <= m_params.HighThreshold() && diffG <= m_params.HighThreshold() && diffB <= m_params.HighThreshold()) - { - high_threshold = BACKGROUND; - } + // perform background subtraction + low_threshold = high_threshold = FOREGROUND; + + int diffR = abs(pixel(0) - m_median(r, c, 0)); + int diffG = abs(pixel(1) - m_median(r, c, 1)); + int diffB = abs(pixel(2) - m_median(r, c, 2)); + + if (diffR <= m_params.LowThreshold() && diffG <= m_params.LowThreshold() && diffB <= m_params.LowThreshold()) + { + low_threshold = BACKGROUND; + } + + if (diffR <= m_params.HighThreshold() && diffG <= m_params.HighThreshold() && diffB <= m_params.HighThreshold()) + { + high_threshold = BACKGROUND; + } } /////////////////////////////////////////////////////////////////////////////// @@ -118,23 +118,23 @@ void AdaptiveMedianBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, // (the memory should already be reserved) // values: 255-foreground, 0-background /////////////////////////////////////////////////////////////////////////////// -void AdaptiveMedianBGS::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mask, BwImage& high_threshold_mask) +void AdaptiveMedianBGS::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mask, BwImage& high_threshold_mask) { - unsigned char low_threshold, high_threshold; - - // 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) - { - // perform background subtraction - SubtractPixel(r, c, data(r,c), low_threshold, high_threshold); - - // setup silhouette mask - low_threshold_mask(r,c) = low_threshold; - high_threshold_mask(r,c) = high_threshold; - } - } + unsigned char low_threshold, high_threshold; + + // 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) + { + // perform background subtraction + SubtractPixel(r, c, data(r, c), low_threshold, high_threshold); + + // setup silhouette mask + low_threshold_mask(r, c) = low_threshold; + high_threshold_mask(r, c) = high_threshold; + } + } } diff --git a/package_bgs/dp/AdaptiveMedianBGS.h b/package_bgs/dp/AdaptiveMedianBGS.h index d199b81896bae228d42d8685566502344ecbeb29..79a04b39ab60dae865fb0b38af2f1108c4e18df7 100644 --- a/package_bgs/dp/AdaptiveMedianBGS.h +++ b/package_bgs/dp/AdaptiveMedianBGS.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * AdaptiveMedianBGS.hpp * -* Purpose: Implementation of the simple adaptive median background +* Purpose: Implementation of the simple adaptive median background * subtraction algorithm described in: * "Segmentation and tracking of piglets in images" * by McFarlane and Schofield @@ -26,64 +26,65 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * 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); + 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; } + 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; } + int &SamplingRate() { return m_samplingRate; } + int &LearningFrames() { return m_learning_frames; } - private: - unsigned char m_low_threshold; - unsigned char m_high_threshold; + private: + unsigned char m_low_threshold; + unsigned char m_high_threshold; - int m_samplingRate; - int m_learning_frames; - }; + int m_samplingRate; + int m_learning_frames; + }; - // --- Adaptive Median BGS algorithm --- - class AdaptiveMedianBGS : public Bgs - { - public: - virtual ~AdaptiveMedianBGS() {} + // --- Adaptive Median BGS algorithm --- + class AdaptiveMedianBGS : public Bgs + { + public: + virtual ~AdaptiveMedianBGS() {} - void Initalize(const BgsParams& param); + 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); + 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(); + RgbImage* Background(); - private: - void SubtractPixel(int r, int c, const RgbPixel& pixel, - unsigned char& low_threshold, unsigned char& high_threshold); + private: + void SubtractPixel(int r, int c, const RgbPixel& pixel, + unsigned char& low_threshold, unsigned char& high_threshold); - AdaptiveMedianParams m_params; + AdaptiveMedianParams m_params; - RgbImage m_median; - }; - } + RgbImage m_median; + }; + } } diff --git a/package_bgs/dp/Bgs.h b/package_bgs/dp/Bgs.h index 5f91246e0aa87fd2a43e86d58e663998fbb56e7c..26fff70ea503cfb5737f53ae1991efbb529ff598 100644 --- a/package_bgs/dp/Bgs.h +++ b/package_bgs/dp/Bgs.h @@ -23,45 +23,41 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * Author: Donovan Parks, October 2007 * ******************************************************************************/ - -#ifndef BGS_H_ -#define BGS_H_ +#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; +namespace BackgroundSubtraction +{ +class Bgs +{ +public: + static const int BACKGROUND = 0; + static const int FOREGROUND = 255; - virtual ~Bgs() {} + 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 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; + // 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; + // 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; + // 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; - }; - } + // Return the current background model. + virtual RgbImage *Background() = 0; +}; +} } - -#endif diff --git a/package_bgs/dp/BgsParams.h b/package_bgs/dp/BgsParams.h index a63b1ac3cff432124bd0608c20f586f0e97eefab..d2e7d29e084cffc798f968c0290b304e62071a50 100644 --- a/package_bgs/dp/BgsParams.h +++ b/package_bgs/dp/BgsParams.h @@ -24,36 +24,32 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * Author: Donovan Parks, May 2008 * ******************************************************************************/ - -#ifndef BGS_PARAMS_H_ -#define BGS_PARAMS_H_ +#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; - }; - } +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; +}; +} } - -#endif diff --git a/package_bgs/dp/DPAdaptiveMedianBGS.cpp b/package_bgs/dp/DPAdaptiveMedianBGS.cpp deleted file mode 100644 index 0ae68fe830c77accbac22ac58227a56785a326fe..0000000000000000000000000000000000000000 --- a/package_bgs/dp/DPAdaptiveMedianBGS.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 "DPAdaptiveMedianBGS.h" - -DPAdaptiveMedianBGS::DPAdaptiveMedianBGS() : firstTime(true), frameNumber(0), threshold(40), samplingRate(7), learningFrames(30), showOutput(true) -{ - std::cout << "DPAdaptiveMedianBGS()" << std::endl; -} - -DPAdaptiveMedianBGS::~DPAdaptiveMedianBGS() -{ - std::cout << "~DPAdaptiveMedianBGS()" << std::endl; -} - -void DPAdaptiveMedianBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) -{ - if(img_input.empty()) - return; - - loadConfig(); - - if(firstTime) - saveConfig(); - - 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); - - std::cout << "threshold: " << threshold << std::endl; - std::cout << "samplingRate: " << samplingRate << std::endl; - std::cout << "learningFrames: " << learningFrames << std::endl; - std::cout << "showOutput: " << showOutput << std::endl; - } - - bgs.Subtract(frameNumber, frame_data, lowThresholdMask, highThresholdMask); - lowThresholdMask.Clear(); - bgs.Update(frameNumber, frame_data, lowThresholdMask); - - cv::Mat foreground(highThresholdMask.Ptr()); - cv::Mat background(bgs.Background()->Ptr()); - - if(showOutput){ - cv::imshow("Adaptive Median FG (McFarlane&Schofield)", foreground); - cv::imshow("Adaptive Median BG (McFarlane&Schofield)", background); - } - - foreground.copyTo(img_output); - background.copyTo(img_bgmodel); - - delete frame; - firstTime = false; - frameNumber++; -} - -void DPAdaptiveMedianBGS::saveConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/DPAdaptiveMedianBGS.xml", 0, CV_STORAGE_WRITE); - - cvWriteInt(fs, "threshold", threshold); - cvWriteInt(fs, "samplingRate", samplingRate); - cvWriteInt(fs, "learningFrames", learningFrames); - cvWriteInt(fs, "showOutput", showOutput); - - cvReleaseFileStorage(&fs); -} - -void DPAdaptiveMedianBGS::loadConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/DPAdaptiveMedianBGS.xml", 0, CV_STORAGE_READ); - - threshold = cvReadIntByName(fs, 0, "threshold", 40); - samplingRate = cvReadIntByName(fs, 0, "samplingRate", 7); - learningFrames = cvReadIntByName(fs, 0, "learningFrames", 30); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - cvReleaseFileStorage(&fs); -} diff --git a/package_bgs/dp/DPAdaptiveMedianBGS.h b/package_bgs/dp/DPAdaptiveMedianBGS.h deleted file mode 100644 index a5dd3879b383f91664b22341e433a6683aed4407..0000000000000000000000000000000000000000 --- a/package_bgs/dp/DPAdaptiveMedianBGS.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "AdaptiveMedianBGS.h" - -using namespace Algorithms::BackgroundSubtraction; - -class DPAdaptiveMedianBGS : public IBGS -{ -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - AdaptiveMedianParams params; - AdaptiveMedianBGS bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - int threshold; - int samplingRate; - int learningFrames; - bool showOutput; - -public: - DPAdaptiveMedianBGS(); - ~DPAdaptiveMedianBGS(); - - 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/dp/DPPratiMediodBGS.h b/package_bgs/dp/DPPratiMediodBGS.h deleted file mode 100644 index 8aa641622bf1d57c7e4e3540ceafcf7ed4b5fdcf..0000000000000000000000000000000000000000 --- a/package_bgs/dp/DPPratiMediodBGS.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "PratiMediodBGS.h" - -using namespace Algorithms::BackgroundSubtraction; - -class DPPratiMediodBGS : public IBGS -{ -private: - bool firstTime; - long frameNumber; - IplImage* frame; - RgbImage frame_data; - - PratiParams params; - PratiMediodBGS bgs; - BwImage lowThresholdMask; - BwImage highThresholdMask; - - int threshold; - int samplingRate; - int historySize; - int weight; - bool showOutput; - -public: - DPPratiMediodBGS(); - ~DPPratiMediodBGS(); - - 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/dp/DPTextureBGS.h b/package_bgs/dp/DPTextureBGS.h deleted file mode 100644 index c29e7e92d5048348d67e080b377ed227b1874967..0000000000000000000000000000000000000000 --- a/package_bgs/dp/DPTextureBGS.h +++ /dev/null @@ -1,60 +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 "../IBGS.h" -#include "TextureBGS.h" -//#include "ConnectedComponents.h" - -class DPTextureBGS : public IBGS -{ -private: - bool firstTime; - bool showOutput; - - 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: - DPTextureBGS(); - ~DPTextureBGS(); - - 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/dp/Eigenbackground.cpp b/package_bgs/dp/Eigenbackground.cpp index 2d2c3ef3d85a26d0653e7b17f3486a4e4affa903..dceb4cd2c4442d53703bf21ea957ed341535fd64 100644 --- a/package_bgs/dp/Eigenbackground.cpp +++ b/package_bgs/dp/Eigenbackground.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Eigenbackground.cpp * -* Purpose: Implementation of the Eigenbackground background subtraction +* Purpose: Implementation of the Eigenbackground background subtraction * algorithm developed by Oliver et al. * * Author: Donovan Parks, September 2007 @@ -34,157 +34,157 @@ using namespace Algorithms::BackgroundSubtraction; Eigenbackground::Eigenbackground() { - m_pcaData = NULL; - m_pcaAvg = NULL; - m_eigenValues = NULL; - m_eigenVectors = NULL; + m_pcaData = NULL; + m_pcaAvg = NULL; + m_eigenValues = NULL; + m_eigenVectors = NULL; } Eigenbackground::~Eigenbackground() { - if(m_pcaData != NULL) cvReleaseMat(&m_pcaData); - if(m_pcaAvg != NULL) cvReleaseMat(&m_pcaAvg); - if(m_eigenValues != NULL) cvReleaseMat(&m_eigenValues); - if(m_eigenVectors != NULL) cvReleaseMat(&m_eigenVectors); + if (m_pcaData != NULL) cvReleaseMat(&m_pcaData); + if (m_pcaAvg != NULL) cvReleaseMat(&m_pcaAvg); + if (m_eigenValues != NULL) cvReleaseMat(&m_eigenValues); + if (m_eigenVectors != NULL) cvReleaseMat(&m_eigenVectors); } void Eigenbackground::Initalize(const BgsParams& param) { - m_params = (EigenbackgroundParams&)param; - - m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); - m_background.Clear(); + m_params = (EigenbackgroundParams&)param; + + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); + m_background.Clear(); } void Eigenbackground::InitModel(const RgbImage& data) { - if(m_pcaData != NULL) cvReleaseMat(&m_pcaData); - if(m_pcaAvg != NULL) cvReleaseMat(&m_pcaAvg); - if(m_eigenValues != NULL) cvReleaseMat(&m_eigenValues); - if(m_eigenVectors != NULL) cvReleaseMat(&m_eigenVectors); + if (m_pcaData != NULL) cvReleaseMat(&m_pcaData); + if (m_pcaAvg != NULL) cvReleaseMat(&m_pcaAvg); + if (m_eigenValues != NULL) cvReleaseMat(&m_eigenValues); + if (m_eigenVectors != NULL) cvReleaseMat(&m_eigenVectors); - m_pcaData = cvCreateMat(m_params.HistorySize(), m_params.Size()*3, CV_8UC1); + m_pcaData = cvCreateMat(m_params.HistorySize(), m_params.Size() * 3, CV_8UC1); - m_background.Clear(); + m_background.Clear(); } -void Eigenbackground::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void Eigenbackground::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - // the eigenbackground model is not updated (serious limitation!) + // the eigenbackground model is not updated (serious limitation!) } -void Eigenbackground::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mask, BwImage& high_threshold_mask) +void Eigenbackground::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mask, BwImage& high_threshold_mask) { - // create eigenbackground - if(frame_num == m_params.HistorySize()) - { - // create the eigenspace - m_pcaAvg = cvCreateMat( 1, m_pcaData->cols, CV_32F ); - m_eigenValues = cvCreateMat( m_pcaData->rows, 1, CV_32F ); - m_eigenVectors = cvCreateMat( m_pcaData->rows, m_pcaData->cols, CV_32F ); - cvCalcPCA(m_pcaData, m_pcaAvg, m_eigenValues, m_eigenVectors, CV_PCA_DATA_AS_ROW); - - int index = 0; - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - for(int ch = 0; ch < m_background.Ptr()->nChannels; ++ch) - { - m_background(r,c,0) = static_cast<unsigned char>(cvmGet(m_pcaAvg,0,index)+0.5); - index++; - } - } - } - } - - if(frame_num >= m_params.HistorySize()) - { - // project new image into the eigenspace - int w = data.Ptr()->width; - int h = data.Ptr()->height; - int ch = data.Ptr()->nChannels; - CvMat* dataPt = cvCreateMat(1, w*h*ch, CV_8UC1); - CvMat data_row; - cvGetRow(dataPt, &data_row, 0); - cvReshape(&data_row, &data_row, 3, data.Ptr()->height); - cvCopy(data.Ptr(), &data_row); - - CvMat* proj = cvCreateMat(1, m_params.EmbeddedDim(), CV_32F); - cvProjectPCA(dataPt, m_pcaAvg, m_eigenVectors, proj); - - // reconstruct point - CvMat* result = cvCreateMat(1, m_pcaData->cols, CV_32F); - cvBackProjectPCA(proj, m_pcaAvg, m_eigenVectors, result); - - // calculate Euclidean distance between new image and its eigenspace projection - int index = 0; - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - double dist = 0; - bool bgLow = true; - bool bgHigh = true; - for(int ch = 0; ch < 3; ++ch) - { - dist = (data(r,c,ch) - cvmGet(result,0,index))*(data(r,c,ch) - cvmGet(result,0,index)); - if(dist > m_params.LowThreshold()) - bgLow = false; - if(dist > m_params.HighThreshold()) - bgHigh = false; - index++; - } - - if(!bgLow) - { - low_threshold_mask(r,c) = FOREGROUND; - } - else - { - low_threshold_mask(r,c) = BACKGROUND; - } - - if(!bgHigh) - { - high_threshold_mask(r,c) = FOREGROUND; - } - else - { - high_threshold_mask(r,c) = BACKGROUND; - } - } - } - - cvReleaseMat(&result); - cvReleaseMat(&proj); - cvReleaseMat(&dataPt); - } - else - { - // set entire image to background since there is not enough information yet - // to start performing background subtraction - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - low_threshold_mask(r,c) = BACKGROUND; - high_threshold_mask(r,c) = BACKGROUND; - } - } - } - - UpdateHistory(frame_num, data); + // create eigenbackground + if (frame_num == m_params.HistorySize()) + { + // create the eigenspace + m_pcaAvg = cvCreateMat(1, m_pcaData->cols, CV_32F); + m_eigenValues = cvCreateMat(m_pcaData->rows, 1, CV_32F); + m_eigenVectors = cvCreateMat(m_pcaData->rows, m_pcaData->cols, CV_32F); + cvCalcPCA(m_pcaData, m_pcaAvg, m_eigenValues, m_eigenVectors, CV_PCA_DATA_AS_ROW); + + int index = 0; + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + for (int ch = 0; ch < m_background.Ptr()->nChannels; ++ch) + { + m_background(r, c, 0) = static_cast<unsigned char>(cvmGet(m_pcaAvg, 0, index) + 0.5); + index++; + } + } + } + } + + if (frame_num >= m_params.HistorySize()) + { + // project new image into the eigenspace + int w = data.Ptr()->width; + int h = data.Ptr()->height; + int ch = data.Ptr()->nChannels; + CvMat* dataPt = cvCreateMat(1, w*h*ch, CV_8UC1); + CvMat data_row; + cvGetRow(dataPt, &data_row, 0); + cvReshape(&data_row, &data_row, 3, data.Ptr()->height); + cvCopy(data.Ptr(), &data_row); + + CvMat* proj = cvCreateMat(1, m_params.EmbeddedDim(), CV_32F); + cvProjectPCA(dataPt, m_pcaAvg, m_eigenVectors, proj); + + // reconstruct point + CvMat* result = cvCreateMat(1, m_pcaData->cols, CV_32F); + cvBackProjectPCA(proj, m_pcaAvg, m_eigenVectors, result); + + // calculate Euclidean distance between new image and its eigenspace projection + int index = 0; + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + double dist = 0; + bool bgLow = true; + bool bgHigh = true; + for (int ch = 0; ch < 3; ++ch) + { + dist = (data(r, c, ch) - cvmGet(result, 0, index))*(data(r, c, ch) - cvmGet(result, 0, index)); + if (dist > m_params.LowThreshold()) + bgLow = false; + if (dist > m_params.HighThreshold()) + bgHigh = false; + index++; + } + + if (!bgLow) + { + low_threshold_mask(r, c) = FOREGROUND; + } + else + { + low_threshold_mask(r, c) = BACKGROUND; + } + + if (!bgHigh) + { + high_threshold_mask(r, c) = FOREGROUND; + } + else + { + high_threshold_mask(r, c) = BACKGROUND; + } + } + } + + cvReleaseMat(&result); + cvReleaseMat(&proj); + cvReleaseMat(&dataPt); + } + else + { + // set entire image to background since there is not enough information yet + // to start performing background subtraction + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + low_threshold_mask(r, c) = BACKGROUND; + high_threshold_mask(r, c) = BACKGROUND; + } + } + } + + UpdateHistory(frame_num, data); } void Eigenbackground::UpdateHistory(int frame_num, const RgbImage& new_frame) { - if(frame_num < m_params.HistorySize()) - { - CvMat src_row; - cvGetRow(m_pcaData, &src_row, frame_num); - cvReshape(&src_row, &src_row, 3, new_frame.Ptr()->height); - cvCopy(new_frame.Ptr(), &src_row); - } + if (frame_num < m_params.HistorySize()) + { + CvMat src_row; + cvGetRow(m_pcaData, &src_row, frame_num); + cvReshape(&src_row, &src_row, 3, new_frame.Ptr()->height); + cvCopy(new_frame.Ptr(), &src_row); + } } diff --git a/package_bgs/dp/Eigenbackground.h b/package_bgs/dp/Eigenbackground.h index 721b7356e453be4903f19698de7b2b4b150578e7..10ed189696c08296181fc0c1eb54a61a81f2dd7a 100644 --- a/package_bgs/dp/Eigenbackground.h +++ b/package_bgs/dp/Eigenbackground.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Eigenbackground.hpp * -* Purpose: Implementation of the Eigenbackground background subtraction +* Purpose: Implementation of the Eigenbackground background subtraction * algorithm developed by Oliver et al. * * Author: Donovan Parks, September 2007 @@ -30,16 +30,14 @@ 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.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); ******************************************************************************/ - -#ifndef _ELGAMMAL_H_ -#define _ELGAMMAL_H_ +#pragma once #include "Bgs.h" @@ -77,9 +75,9 @@ namespace Algorithms 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); + 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; } @@ -90,12 +88,10 @@ namespace Algorithms CvMat* m_pcaData; CvMat* m_pcaAvg; - CvMat* m_eigenValues; + CvMat* m_eigenValues; CvMat* m_eigenVectors; RgbImage m_background; }; } } - -#endif diff --git a/package_bgs/dp/Error.h b/package_bgs/dp/Error.h index cdbb222c4bdc9ec92b5c2aad3bd02c06fd39c2b9..81cbbebcf8181bc40bddc526bc3ebb88ec6a0ea8 100644 --- a/package_bgs/dp/Error.h +++ b/package_bgs/dp/Error.h @@ -23,14 +23,9 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * Author: Donovan Parks, July 2007 * ******************************************************************************/ - -#ifndef ERROR_H -#define ERROR_H +#pragma once bool Error(const char* msg, const char* code, int data); - bool TraceInit(const char* filename); void Trace(const char* msg); void TraceClose(); - -#endif diff --git a/package_bgs/dp/GrimsonGMM.cpp b/package_bgs/dp/GrimsonGMM.cpp index ff9c26261b4775d89f8207da29c646e001087877..4cf6f35e8e9ae30c19481c8fbcc7ef4f250df15f 100644 --- a/package_bgs/dp/GrimsonGMM.cpp +++ b/package_bgs/dp/GrimsonGMM.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * GrimsonGMM.cpp * -* Purpose: Implementation of the Gaussian mixture model (GMM) background +* 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 @@ -26,16 +26,16 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * Author: Donovan Parks, September 2007 * * This code is based on code by Z. Zivkovic's written for his enhanced GMM -* background subtraction algorithm: +* background subtraction algorithm: * * "Improved adaptive Gausian mixture model for background subtraction" -* Z.Zivkovic +* Z.Zivkovic * International Conference Pattern Recognition, UK, August, 2004 * * -* "Efficient Adaptive Density Estimapion per Image Pixel for the +* "Efficient Adaptive Density Estimapion per Image Pixel for the * Task of Background Subtraction" -* Z.Zivkovic, F. van der Heijden +* 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 @@ -47,252 +47,252 @@ 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; + 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; + m_modes = NULL; } GrimsonGMM::~GrimsonGMM() { - delete[] m_modes; + delete[] m_modes; } void GrimsonGMM::Initalize(const BgsParams& param) { - m_params = (GrimsonParams&)param; + m_params = (GrimsonParams&)param; - // Tbf - the threshold - m_bg_threshold = 0.75f; // 1-cf from the paper + // 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 + // 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()]; + // 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); + // 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); + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); } RgbImage* GrimsonGMM::Background() { - return &m_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; - } + 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) +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 + // 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) +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; - } + // 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; + } } /////////////////////////////////////////////////////////////////////////////// @@ -303,29 +303,29 @@ void GrimsonGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned ch // (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) +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; - } - } + 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/GrimsonGMM.h b/package_bgs/dp/GrimsonGMM.h index a177a803bbd81f8da79f0b9afbe86ff1cdd276fc..2c0f77232801d24f14d7b8b8b04d2af536565a1e 100644 --- a/package_bgs/dp/GrimsonGMM.h +++ b/package_bgs/dp/GrimsonGMM.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * GrimsonGMM.cpp * -* Purpose: Implementation of the Gaussian mixture model (GMM) background +* 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 @@ -26,125 +26,121 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * Author: Donovan Parks, September 2007 * * This code is based on code by Z. Zivkovic's written for his enhanced GMM -* background subtraction algorithm: +* background subtraction algorithm: * * "Improved adaptive Gausian mixture model for background subtraction" -* Z.Zivkovic +* Z.Zivkovic * International Conference Pattern Recognition, UK, August, 2004 * * -* "Efficient Adaptive Density Estimapion per Image Pixel for the +* "Efficient Adaptive Density Estimapion per Image Pixel for the * Task of Background Subtraction" -* Z.Zivkovic, F. van der Heijden +* 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); + 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); ******************************************************************************/ - -#ifndef GRIMSON_GMM_ -#define GRIMSON_GMM_ +#pragma once #include "Bgs.h" namespace Algorithms { - namespace BackgroundSubtraction - { - 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 Grimson GMM BGS algorithm --- - class GrimsonParams : 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; } - - 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; - }; - - // --- Grimson GMM BGS algorithm --- - class GrimsonGMM : public Bgs - { - public: - GrimsonGMM(); - ~GrimsonGMM(); - - 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 - GrimsonParams 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; - }; - } + namespace BackgroundSubtraction + { + 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 Grimson GMM BGS algorithm --- + class GrimsonParams : 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; } + + 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; + }; + + // --- Grimson GMM BGS algorithm --- + class GrimsonGMM : public Bgs + { + public: + GrimsonGMM(); + ~GrimsonGMM(); + + 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 + GrimsonParams 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; + }; + } } - -#endif diff --git a/package_bgs/dp/Image.cpp b/package_bgs/dp/Image.cpp index f00febda47ff02b170ddbed9e9d5ed9bf1d4214e..92119c246c8d366b3f7addaabefe0c013fa25b7e 100644 --- a/package_bgs/dp/Image.cpp +++ b/package_bgs/dp/Image.cpp @@ -18,59 +18,59 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Image.hpp * -* Purpose: C++ wrapper for OpenCV IplImage which supports simple and +* 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: +* 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) +{ + if (imgp != NULL && m_bReleaseMemory) cvReleaseImage(&imgp); - imgp = NULL; + 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 r = 1; r < image.Ptr()->height - 1; ++r) { - for(int c = 1; c < image.Ptr()->width-1; ++c) + for (int c = 1; c < image.Ptr()->width - 1; ++c) { int count = 0; - if(image(r,c) == fgValue) + if (image(r, c) == fgValue) { - if(image(r-1,c-1) == fgValue) + if (image(r - 1, c - 1) == fgValue) count++; - if(image(r-1,c) == fgValue) + if (image(r - 1, c) == fgValue) count++; - if(image(r-1,c+1) == fgValue) + if (image(r - 1, c + 1) == fgValue) count++; - if(image(r,c-1) == fgValue) + if (image(r, c - 1) == fgValue) count++; - if(image(r,c+1) == fgValue) + if (image(r, c + 1) == fgValue) count++; - if(image(r+1,c-1) == fgValue) + if (image(r + 1, c - 1) == fgValue) count++; - if(image(r+1,c) == fgValue) + if (image(r + 1, c) == fgValue) count++; - if(image(r+1,c+1) == fgValue) + if (image(r + 1, c + 1) == fgValue) count++; - if(count < minDensity) - filtered(r,c) = 0; + if (count < minDensity) + filtered(r, c) = 0; else - filtered(r,c) = fgValue; + filtered(r, c) = fgValue; } else { - filtered(r,c) = 0; + filtered(r, c) = 0; } } } -} \ No newline at end of file +} diff --git a/package_bgs/dp/Image.h b/package_bgs/dp/Image.h index 58fe50d922442141de026d128b4d0cc99335e1cd..6c0b5b3257486489597f8c9dae47dc6cec304d8b 100644 --- a/package_bgs/dp/Image.h +++ b/package_bgs/dp/Image.h @@ -18,17 +18,15 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Image.h * -* Purpose: C++ wrapper for OpenCV IplImage which supports simple and +* 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: +* Based on code from: * http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html ******************************************************************************/ - -#ifndef _IMAGE_H_ -#define _IMAGE_H_ +#pragma once #include <opencv2/opencv.hpp> //#include <cxcore.h> @@ -36,30 +34,30 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. // --- Image Iterator --------------------------------------------------------- template <class T> -class ImageIterator +class ImageIterator { -public: - ImageIterator(IplImage* image, int x=0, int y=0, int dx= 0, int dy=0) : - i(x), j(y), i0(0) - { +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; + nl = image->height; + if ((y + dy) > 0 && (y + dy) < nl) + nl = y + dy; - if (y<0) - j=0; + if (y < 0) + j = 0; data += step*j; nc = image->width; - if ((x+dx) > 0 && (x+dx) < nc) - nc = x+dx; + if ((x + dx) > 0 && (x + dx) < nc) + nc = x + dx; nc *= image->nChannels; - if (x>0) + if (x > 0) i0 = x*image->nChannels; i = i0; @@ -71,26 +69,26 @@ public: bool operator!() const { return j < nl; } /* next pixel */ - ImageIterator& operator++() + ImageIterator& operator++() { i++; - if (i >= nc) - { - i=i0; - j++; - data += step; + if (i >= nc) + { + i = i0; + j++; + data += step; } return *this; } - ImageIterator& operator+=(int s) + ImageIterator& operator+=(int s) { - i+=s; - if (i >= nc) - { - i=i0; - j++; - data += step; + i += s; + if (i >= nc) + { + i = i0; + j++; + data += step; } return *this; } @@ -101,18 +99,18 @@ public: const T operator*() const { return data[i]; } const T neighbor(int dx, int dy) const - { - return *(data+dy*step+i+dx); + { + return *(data + dy*step + i + dx); } - T* operator&() const { return data+i; } + T* operator&() const { return data + i; } /* current pixel coordinates */ - int column() const { return i/nch; } + int column() const { return i / nch; } int line() const { return j; } private: - int i, i0,j; + int i, i0, j; T* data; int step; int nl, nc; @@ -128,7 +126,7 @@ const unsigned char NUM_CHANNELS = 3; class RgbPixel { public: - RgbPixel() {;} + RgbPixel() { ; } RgbPixel(unsigned char _r, unsigned char _g, unsigned char _b) { ch[0] = _r; ch[1] = _g; ch[2] = _b; @@ -156,7 +154,7 @@ public: class RgbPixelFloat { public: - RgbPixelFloat() {;} + RgbPixelFloat() { ; } RgbPixelFloat(float _r, float _g, float _b) { ch[0] = _r; ch[1] = _g; ch[2] = _b; @@ -199,14 +197,14 @@ public: cvReleaseImage(&imgp); } - void operator=(IplImage* img) - { + void operator=(IplImage* img) + { imgp = img; } // copy-constructor ImageBase(const ImageBase& rhs) - { + { // it is very inefficent if this copy-constructor is called assert(false); } @@ -237,31 +235,31 @@ public: cvZero(imgp); } - void operator=(IplImage* img) - { + 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]; + 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]; + 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) + inline RgbPixel& operator()(const int r, const int c) { - return (RgbPixel &)imgp->imageData[r*imgp->widthStep+c*imgp->nChannels]; + 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]; + return (RgbPixel &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels]; } }; @@ -275,31 +273,31 @@ public: cvZero(imgp); } - void operator=(IplImage* img) - { + 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)]; + 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)]; + 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) + inline RgbPixelFloat& operator()(const int r, const int c) { - return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep+c*imgp->nChannels*sizeof(float)]; + 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)]; + return (RgbPixelFloat &)imgp->imageData[r*imgp->widthStep + c*imgp->nChannels * sizeof(float)]; } }; @@ -313,20 +311,20 @@ public: cvZero(imgp); } - void operator=(IplImage* img) - { + 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]; + 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]; + return (unsigned char)imgp->imageData[r*imgp->widthStep + c]; } }; @@ -340,25 +338,23 @@ public: cvZero(imgp); } - void operator=(IplImage* img) - { + 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)]; + 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)]; + 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/package_bgs/dp/MeanBGS.cpp index b8df8958dec2e8fd1a0735861134be91b3b7d25e..51781588671b3714278c9614cecd8cfef5f5baa0 100644 --- a/package_bgs/dp/MeanBGS.cpp +++ b/package_bgs/dp/MeanBGS.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * MeanBGS.h * -* Purpose: Implementation of a simple temporal mean background +* Purpose: Implementation of a simple temporal mean background * subtraction algorithm. * * Author: Donovan Parks, September 2007 @@ -31,72 +31,72 @@ using namespace Algorithms::BackgroundSubtraction; void MeanBGS::Initalize(const BgsParams& param) { - m_params = (MeanParams&)param; + m_params = (MeanParams&)param; - m_mean = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_32F, 3); - m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); + m_mean = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_32F, 3); + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); } void MeanBGS::InitModel(const RgbImage& data) { - for (unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - m_mean(r,c,ch) = (float)data(r,c,ch); - } - } - } + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + m_mean(r, c, ch) = (float)data(r, c, ch); + } + } + } } -void MeanBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void MeanBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - // update background model - for (unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - // perform conditional updating only if we are passed the learning phase - if(update_mask(r,c) == BACKGROUND || frame_num < m_params.LearningFrames()) - { - // update B/G model - float mean; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - mean = m_params.Alpha() * m_mean(r,c,ch) + (1.0f-m_params.Alpha()) * data(r,c,ch); - m_mean(r,c,ch) = mean; - m_background(r,c,ch) = (unsigned char)(mean + 0.5); - } - } - } - } + // update background model + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + // perform conditional updating only if we are passed the learning phase + if (update_mask(r, c) == BACKGROUND || frame_num < m_params.LearningFrames()) + { + // update B/G model + float mean; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + mean = m_params.Alpha() * m_mean(r, c, ch) + (1.0f - m_params.Alpha()) * data(r, c, ch); + m_mean(r, c, ch) = mean; + m_background(r, c, ch) = (unsigned char)(mean + 0.5); + } + } + } + } } -void MeanBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, - unsigned char& low_threshold, - unsigned char& high_threshold) +void MeanBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, + unsigned char& low_threshold, + unsigned char& high_threshold) { - // calculate distance to sample point - float dist = 0; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - dist += (pixel(ch)-m_mean(r,c,ch))*(pixel(ch)-m_mean(r,c,ch)); - } - - // determine if sample point is F/G or B/G pixel - low_threshold = BACKGROUND; - if(dist > m_params.LowThreshold()) - { - low_threshold = FOREGROUND; - } - - high_threshold = BACKGROUND; - if(dist > m_params.HighThreshold()) - { - high_threshold = FOREGROUND; - } + // calculate distance to sample point + float dist = 0; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + dist += (pixel(ch) - m_mean(r, c, ch))*(pixel(ch) - m_mean(r, c, ch)); + } + + // determine if sample point is F/G or B/G pixel + low_threshold = BACKGROUND; + if (dist > m_params.LowThreshold()) + { + low_threshold = FOREGROUND; + } + + high_threshold = BACKGROUND; + if (dist > m_params.HighThreshold()) + { + high_threshold = FOREGROUND; + } } /////////////////////////////////////////////////////////////////////////////// @@ -106,26 +106,22 @@ void MeanBGS::SubtractPixel(int r, int c, const RgbPixel& pixel, // output - a pointer to the data of a gray value image of the same size // values: 255-foreground, 0-background /////////////////////////////////////////////////////////////////////////////// -void MeanBGS::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mask, BwImage& high_threshold_mask) +void MeanBGS::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mask, BwImage& high_threshold_mask) { - unsigned char low_threshold, high_threshold; - - // 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) - { - // perform background subtraction + update background model - SubtractPixel(r, c, data(r,c), low_threshold, high_threshold); - - // setup silhouette mask - low_threshold_mask(r,c) = low_threshold; - high_threshold_mask(r,c) = high_threshold; - } - } + unsigned char low_threshold, high_threshold; + + // 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) + { + // perform background subtraction + update background model + SubtractPixel(r, c, data(r, c), low_threshold, high_threshold); + + // setup silhouette mask + low_threshold_mask(r, c) = low_threshold; + high_threshold_mask(r, c) = high_threshold; + } + } } - - - - diff --git a/package_bgs/dp/MeanBGS.h b/package_bgs/dp/MeanBGS.h index 247e09493a6af6bd954d2c6be825f31007fe5c76..306af1a8083dba5d34354354f6093f42661846b1 100644 --- a/package_bgs/dp/MeanBGS.h +++ b/package_bgs/dp/MeanBGS.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * MeanBGS.hpp * -* Purpose: Implementation of a simple temporal mean background +* Purpose: Implementation of a simple temporal mean background * subtraction algorithm. * * Author: Donovan Parks, September 2007 @@ -28,13 +28,14 @@ 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.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" @@ -54,7 +55,7 @@ namespace Algorithms int &LearningFrames() { return m_learning_frames; } private: - // A pixel is considered to be from the background if the squared distance between + // A pixel is considered to be from the background if the squared distance between // it and the background model is less than the threshold. unsigned int m_low_threshold; unsigned int m_high_threshold; @@ -73,14 +74,14 @@ namespace Algorithms 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); + 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, + private: + void SubtractPixel(int r, int c, const RgbPixel& pixel, unsigned char& lowThreshold, unsigned char& highThreshold); MeanParams m_params; @@ -91,8 +92,3 @@ namespace Algorithms } } - - - - - diff --git a/package_bgs/dp/PratiMediodBGS.cpp b/package_bgs/dp/PratiMediodBGS.cpp index 2256ceba6fa5eb911729303c6ba1d891a5cedce3..5a15cec302737468bbc2b5376cd3286af4871c00 100644 --- a/package_bgs/dp/PratiMediodBGS.cpp +++ b/package_bgs/dp/PratiMediodBGS.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * PratiMediodBGS.h * -* Purpose: Implementation of the temporal median background +* Purpose: Implementation of the temporal median background * subtraction algorithm described in: * * [1] "Detecting Moving Objects, Shosts, and Shadows in Video Stream" @@ -29,7 +29,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Author: Donovan Parks, September 2007 * -* Please note that this is not an implementation of the complete system +* 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. ******************************************************************************/ @@ -40,202 +40,202 @@ using namespace Algorithms::BackgroundSubtraction; PratiMediodBGS::PratiMediodBGS() { - m_median_buffer = NULL; + m_median_buffer = NULL; } PratiMediodBGS::~PratiMediodBGS() { - delete[] m_median_buffer; + delete[] m_median_buffer; } void PratiMediodBGS::Initalize(const BgsParams& param) { - m_params = (PratiParams&)param; + m_params = (PratiParams&)param; - m_mask_low_threshold = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1); - m_mask_high_threshold = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1); + m_mask_low_threshold = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1); + m_mask_high_threshold = 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); + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); - m_median_buffer = new MEDIAN_BUFFER[m_params.Size()]; + m_median_buffer = new MEDIAN_BUFFER[m_params.Size()]; } void PratiMediodBGS::InitModel(const RgbImage& data) { - // there is no need to initialize the mode since it needs a buffer of frames - // before it can performing background subtraction + // there is no need to initialize the mode since it needs a buffer of frames + // before it can performing background subtraction } -void PratiMediodBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void PratiMediodBGS::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - // update the image buffer with the new frame and calculate new median values - if(frame_num % m_params.SamplingRate() == 0) - { - if(m_median_buffer[0].dist.size() == m_params.HistorySize()) - { - // subtract distance to sample being removed from all distances - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - int i = r*m_params.Width()+c; - - if(update_mask(r,c) == BACKGROUND) - { - int oldPos = m_median_buffer[i].pos; - for(unsigned int s = 0; s < m_median_buffer[i].pixels.size(); ++s) - { - int maxDist = 0; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - int tempDist = abs(m_median_buffer[i].pixels.at(oldPos)(ch) - - m_median_buffer[i].pixels.at(s)(ch)); - if(tempDist > maxDist) - maxDist = tempDist; - } - - m_median_buffer[i].dist.at(s) -= maxDist; - } - - int dist; - UpdateMediod(r, c, data, dist); - m_median_buffer[i].dist.at(oldPos) = dist; - m_median_buffer[i].pixels.at(oldPos) = data(r,c); - m_median_buffer[i].pos++; - if(m_median_buffer[i].pos >= m_params.HistorySize()) - m_median_buffer[i].pos = 0; - } - } - } - } - else - { - // calculate sum of L-inf distances for new point and - // add distance from each sample point to this point to their L-inf sum - int dist; - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - int index = r*m_params.Width()+c; - UpdateMediod(r, c, data, dist); - m_median_buffer[index].dist.push_back(dist); - m_median_buffer[index].pos = 0; - m_median_buffer[index].pixels.push_back(data(r,c)); - } - } - } - } + // update the image buffer with the new frame and calculate new median values + if (frame_num % m_params.SamplingRate() == 0) + { + if (m_median_buffer[0].dist.size() == m_params.HistorySize()) + { + // subtract distance to sample being removed from all distances + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + int i = r*m_params.Width() + c; + + if (update_mask(r, c) == BACKGROUND) + { + int oldPos = m_median_buffer[i].pos; + for (unsigned int s = 0; s < m_median_buffer[i].pixels.size(); ++s) + { + int maxDist = 0; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + int tempDist = abs(m_median_buffer[i].pixels.at(oldPos)(ch) + - m_median_buffer[i].pixels.at(s)(ch)); + if (tempDist > maxDist) + maxDist = tempDist; + } + + m_median_buffer[i].dist.at(s) -= maxDist; + } + + int dist; + UpdateMediod(r, c, data, dist); + m_median_buffer[i].dist.at(oldPos) = dist; + m_median_buffer[i].pixels.at(oldPos) = data(r, c); + m_median_buffer[i].pos++; + if (m_median_buffer[i].pos >= m_params.HistorySize()) + m_median_buffer[i].pos = 0; + } + } + } + } + else + { + // calculate sum of L-inf distances for new point and + // add distance from each sample point to this point to their L-inf sum + int dist; + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + int index = r*m_params.Width() + c; + UpdateMediod(r, c, data, dist); + m_median_buffer[index].dist.push_back(dist); + m_median_buffer[index].pos = 0; + m_median_buffer[index].pixels.push_back(data(r, c)); + } + } + } + } } void PratiMediodBGS::UpdateMediod(int r, int c, const RgbImage& new_frame, int& dist) { - // calculate sum of L-inf distances for new point and - // add distance from each sample point to this point to their L-inf sum - unsigned int i = (r*m_params.Width()+c); - - m_median_buffer[i].medianDist = INT_MAX; - - int L_inf_dist = 0; - for(unsigned int s = 0; s < m_median_buffer[i].dist.size(); ++s) - { - int maxDist = 0; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - int tempDist = abs(m_median_buffer[i].pixels.at(s)(ch) - new_frame(r,c,ch)); - if(tempDist > maxDist) - maxDist = tempDist; - } - - // check if point from this frame in the image buffer is the median - m_median_buffer[i].dist.at(s) += maxDist; - if(m_median_buffer[i].dist.at(s) < m_median_buffer[i].medianDist) - { - m_median_buffer[i].medianDist = m_median_buffer[i].dist.at(s); - m_median_buffer[i].median = m_median_buffer[i].pixels.at(s); - } - - L_inf_dist += maxDist; - } - - dist = L_inf_dist; - - // check if the new point is the median - if(L_inf_dist < m_median_buffer[i].medianDist) - { - m_median_buffer[i].medianDist = L_inf_dist; - m_median_buffer[i].median = new_frame(r,c); - } + // calculate sum of L-inf distances for new point and + // add distance from each sample point to this point to their L-inf sum + unsigned int i = (r*m_params.Width() + c); + + m_median_buffer[i].medianDist = INT_MAX; + + int L_inf_dist = 0; + for (unsigned int s = 0; s < m_median_buffer[i].dist.size(); ++s) + { + int maxDist = 0; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + int tempDist = abs(m_median_buffer[i].pixels.at(s)(ch) - new_frame(r, c, ch)); + if (tempDist > maxDist) + maxDist = tempDist; + } + + // check if point from this frame in the image buffer is the median + m_median_buffer[i].dist.at(s) += maxDist; + if (m_median_buffer[i].dist.at(s) < m_median_buffer[i].medianDist) + { + m_median_buffer[i].medianDist = m_median_buffer[i].dist.at(s); + m_median_buffer[i].median = m_median_buffer[i].pixels.at(s); + } + + L_inf_dist += maxDist; + } + + dist = L_inf_dist; + + // check if the new point is the median + if (L_inf_dist < m_median_buffer[i].medianDist) + { + m_median_buffer[i].medianDist = L_inf_dist; + m_median_buffer[i].median = new_frame(r, c); + } } void PratiMediodBGS::Combine(const BwImage& low_mask, const BwImage& high_mask, BwImage& output) { - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - output(r,c) = BACKGROUND; - - if(r == 0 || c == 0 || r == m_params.Height()-1 || c == m_params.Width()-1) - continue; - - if(high_mask(r,c) == FOREGROUND) - { - output(r,c) = FOREGROUND; - } - else if(low_mask(r,c) == FOREGROUND) - { - // consider the pixel to be a F/G pixel if it is 8-connected to - // a F/G pixel in the high mask - // check if there is an 8-connected foreground pixel - if(high_mask(r-1,c-1)) - output(r,c) = FOREGROUND; - else if(high_mask(r-1,c)) - output(r,c) = FOREGROUND; - else if(high_mask(r-1,c+1)) - output(r,c) = FOREGROUND; - else if(high_mask(r,c-1)) - output(r,c) = FOREGROUND; - else if(high_mask(r,c+1)) - output(r,c) = FOREGROUND; - else if(high_mask(r+1,c-1)) - output(r,c) = FOREGROUND; - else if(high_mask(r+1,c)) - output(r,c) = FOREGROUND; - else if(high_mask(r+1,c+1)) - output(r,c) = FOREGROUND; - } - } - } + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + output(r, c) = BACKGROUND; + + if (r == 0 || c == 0 || r == m_params.Height() - 1 || c == m_params.Width() - 1) + continue; + + if (high_mask(r, c) == FOREGROUND) + { + output(r, c) = FOREGROUND; + } + else if (low_mask(r, c) == FOREGROUND) + { + // consider the pixel to be a F/G pixel if it is 8-connected to + // a F/G pixel in the high mask + // check if there is an 8-connected foreground pixel + if (high_mask(r - 1, c - 1)) + output(r, c) = FOREGROUND; + else if (high_mask(r - 1, c)) + output(r, c) = FOREGROUND; + else if (high_mask(r - 1, c + 1)) + output(r, c) = FOREGROUND; + else if (high_mask(r, c - 1)) + output(r, c) = FOREGROUND; + else if (high_mask(r, c + 1)) + output(r, c) = FOREGROUND; + else if (high_mask(r + 1, c - 1)) + output(r, c) = FOREGROUND; + else if (high_mask(r + 1, c)) + output(r, c) = FOREGROUND; + else if (high_mask(r + 1, c + 1)) + output(r, c) = FOREGROUND; + } + } + } } void PratiMediodBGS::CalculateMasks(int r, int c, const RgbPixel& pixel) { - int pos = r*m_params.Width()+c; - - // calculate l-inf distance between current value and median value - unsigned char dist = 0; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - int tempDist = abs(pixel(ch) - m_median_buffer[pos].median(ch)); - if(tempDist > dist) - dist = tempDist; - } - m_background(r,c) = m_median_buffer[pos].median; - - // check if pixel is a B/G or F/G pixel according to the low threshold B/G model - m_mask_low_threshold(r,c) = BACKGROUND; - if(dist > m_params.LowThreshold()) - { - m_mask_low_threshold(r,c) = FOREGROUND; - } - - // check if pixel is a B/G or F/G pixel according to the high threshold B/G model - m_mask_high_threshold(r,c)= BACKGROUND; - if(dist > m_params.HighThreshold()) - { - m_mask_high_threshold(r,c) = FOREGROUND; - } + int pos = r*m_params.Width() + c; + + // calculate l-inf distance between current value and median value + unsigned char dist = 0; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + int tempDist = abs(pixel(ch) - m_median_buffer[pos].median(ch)); + if (tempDist > dist) + dist = tempDist; + } + m_background(r, c) = m_median_buffer[pos].median; + + // check if pixel is a B/G or F/G pixel according to the low threshold B/G model + m_mask_low_threshold(r, c) = BACKGROUND; + if (dist > m_params.LowThreshold()) + { + m_mask_low_threshold(r, c) = FOREGROUND; + } + + // check if pixel is a B/G or F/G pixel according to the high threshold B/G model + m_mask_high_threshold(r, c) = BACKGROUND; + if (dist > m_params.HighThreshold()) + { + m_mask_high_threshold(r, c) = FOREGROUND; + } } /////////////////////////////////////////////////////////////////////////////// @@ -245,29 +245,29 @@ void PratiMediodBGS::CalculateMasks(int r, int c, const RgbPixel& pixel) // output - a pointer to the data of a gray value image of the same size // values: 255-foreground, 0-background /////////////////////////////////////////////////////////////////////////////// -void PratiMediodBGS::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mark, BwImage& high_threshold_mark) +void PratiMediodBGS::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mark, BwImage& high_threshold_mark) { - if(frame_num < m_params.HistorySize()) - { - low_threshold_mark.Clear(); - high_threshold_mark.Clear(); - return; - } - - // 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) - { - // need at least one frame of data before we can start calculating the masks - CalculateMasks(r, c, data(r,c)); - } - } - - // combine low and high threshold masks - Combine(m_mask_low_threshold, m_mask_high_threshold, low_threshold_mark); - Combine(m_mask_low_threshold, m_mask_high_threshold, high_threshold_mark); + if (frame_num < m_params.HistorySize()) + { + low_threshold_mark.Clear(); + high_threshold_mark.Clear(); + return; + } + + // 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) + { + // need at least one frame of data before we can start calculating the masks + CalculateMasks(r, c, data(r, c)); + } + } + + // combine low and high threshold masks + Combine(m_mask_low_threshold, m_mask_high_threshold, low_threshold_mark); + Combine(m_mask_low_threshold, m_mask_high_threshold, high_threshold_mark); } diff --git a/package_bgs/dp/PratiMediodBGS.h b/package_bgs/dp/PratiMediodBGS.h index bc8cb7fdf94a8eead4b79cdf5403ce4f0d74d8f4..6bc8f922411e1fbfabb322248fca0d4c295fb58e 100644 --- a/package_bgs/dp/PratiMediodBGS.h +++ b/package_bgs/dp/PratiMediodBGS.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * PratiMediodBGS.hpp * -* Purpose: Implementation of the temporal median background +* Purpose: Implementation of the temporal median background * subtraction algorithm described in: * * [1] "Detecting Moving Objects, Shosts, and Shadows in Video Stream" @@ -29,7 +29,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * Author: Donovan Parks, September 2007 * -* Please note that this is not an implementation of the complete system +* 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. @@ -37,7 +37,7 @@ 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.HighThreshold() = 2*params.LowThreshold(); // Note: high threshold is used by post-processing params.SamplingRate() = 5; params.HistorySize() = 16; params.Weight() = 5; @@ -45,9 +45,7 @@ params.Weight() = 5; Algorithms::BackgroundSubtraction::PratiMediodBGS bgs; bgs.Initalize(params); ******************************************************************************/ - -#ifndef PRATI_MEDIA_BGS_H -#define PRATI_MEDIA_BGS_H +#pragma once #include <vector> #include "Bgs.h" @@ -68,9 +66,9 @@ namespace Algorithms int &HistorySize() { return m_history_size; } private: - // The low threshold is used to supress noise. The high thresohld is used - // to find pixels highly likely to be foreground. This implementation uses an L-inf - // distance measure and a pixel p is considered F/G if D(I(p), B(p)) > threshold. + // The low threshold is used to supress noise. The high thresohld is used + // to find pixels highly likely to be foreground. This implementation uses an L-inf + // distance measure and a pixel p is considered F/G if D(I(p), B(p)) > threshold. // The two threshold maps are combined as in [2]. unsigned int m_low_threshold; unsigned int m_high_threshold; @@ -88,9 +86,9 @@ namespace Algorithms }; // --- Prati Mediod BGS algorithm --- - class PratiMediodBGS : public Bgs + class PratiMediodBGS : public Bgs { - private: + private: // sum of L-inf distances from a sample point to all other sample points struct MEDIAN_BUFFER { @@ -109,13 +107,13 @@ namespace Algorithms 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); + 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: + private: MEDIAN_BUFFER* m_median_buffer; void CalculateMasks(int r, int c, const RgbPixel& pixel); @@ -132,11 +130,3 @@ namespace Algorithms } } - -#endif - - - - - - diff --git a/package_bgs/dp/TextureBGS.cpp b/package_bgs/dp/TextureBGS.cpp index 62684f8df6b8bcbbf4db38e9d32c456045d77153..920f140eecbf302c3e9b4faeecfb08d22c5c9fbd 100644 --- a/package_bgs/dp/TextureBGS.cpp +++ b/package_bgs/dp/TextureBGS.cpp @@ -16,40 +16,40 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. */ #include "TextureBGS.h" -TextureBGS::TextureBGS(){} -TextureBGS::~TextureBGS(){} +TextureBGS::TextureBGS() {} +TextureBGS::~TextureBGS() {} void TextureBGS::LBP(RgbImage& image, RgbImage& texture) { - for(int y = TEXTURE_R; y < image.Ptr()->height-TEXTURE_R; ++y) + for (int y = TEXTURE_R; y < image.Ptr()->height - TEXTURE_R; ++y) { - for(int x = TEXTURE_R; x < image.Ptr()->width-TEXTURE_R; ++x) - { - for(int ch = 0; ch < NUM_CHANNELS; ++ch) + for (int x = TEXTURE_R; x < image.Ptr()->width - TEXTURE_R; ++x) + { + for (int ch = 0; ch < NUM_CHANNELS; ++ch) { unsigned char textureCode = 0; int centerValue = (int)image(y, x, ch); // this only works for a texture radius of 2 - if(centerValue - (int)image(y-2, x, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y - 2, x, ch) + HYSTERSIS >= 0) textureCode += 1; - if(centerValue - (int)image(y-1, x-2, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y - 1, x - 2, ch) + HYSTERSIS >= 0) textureCode += 2; - if(centerValue - (int)image(y-1, x+2, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y - 1, x + 2, ch) + HYSTERSIS >= 0) textureCode += 4; - if(centerValue - (int)image(y+1, x-2, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y + 1, x - 2, ch) + HYSTERSIS >= 0) textureCode += 8; - if(centerValue - (int)image(y+1, x+2, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y + 1, x + 2, ch) + HYSTERSIS >= 0) textureCode += 16; - if(centerValue - (int)image(y+2, x, ch) + HYSTERSIS >= 0) + if (centerValue - (int)image(y + 2, x, ch) + HYSTERSIS >= 0) textureCode += 32; - texture(y,x,ch) = textureCode; + texture(y, x, ch) = textureCode; } } } @@ -58,14 +58,14 @@ void TextureBGS::LBP(RgbImage& image, RgbImage& texture) void TextureBGS::Histogram(RgbImage& texture, TextureHistogram* curTextureHist) { // calculate histogram within a 2*REGION_R square - for(int y = REGION_R+TEXTURE_R; y < texture.Ptr()->height-REGION_R-TEXTURE_R; ++y) + for (int y = REGION_R + TEXTURE_R; y < texture.Ptr()->height - REGION_R - TEXTURE_R; ++y) { - for(int x = REGION_R+TEXTURE_R; x < texture.Ptr()->width-REGION_R-TEXTURE_R; ++x) - { - int index = x+y*(texture.Ptr()->width); + for (int x = REGION_R + TEXTURE_R; x < texture.Ptr()->width - REGION_R - TEXTURE_R; ++x) + { + int index = x + y*(texture.Ptr()->width); // clear histogram - for(int i = 0; i < NUM_BINS; ++i) + for (int i = 0; i < NUM_BINS; ++i) { curTextureHist[index].r[i] = 0; curTextureHist[index].g[i] = 0; @@ -73,13 +73,13 @@ void TextureBGS::Histogram(RgbImage& texture, TextureHistogram* curTextureHist) } // calculate histogram - for(int j = -REGION_R; j <= REGION_R; ++j) + for (int j = -REGION_R; j <= REGION_R; ++j) { - for(int i = -REGION_R; i <= REGION_R; ++i) + for (int i = -REGION_R; i <= REGION_R; ++i) { - curTextureHist[index].r[texture(y+j,x+i,2)]++; - curTextureHist[index].g[texture(y+j,x+i,1)]++; - curTextureHist[index].b[texture(y+j,x+i,0)]++; + curTextureHist[index].r[texture(y + j, x + i, 2)]++; + curTextureHist[index].g[texture(y + j, x + i, 1)]++; + curTextureHist[index].b[texture(y + j, x + i, 0)]++; } } } @@ -88,66 +88,66 @@ void TextureBGS::Histogram(RgbImage& texture, TextureHistogram* curTextureHist) int TextureBGS::ProximityMeasure(TextureHistogram& bgTexture, TextureHistogram& curTextureHist) { - int proximity = 0; - for(int i = 0; i < NUM_BINS; ++i) + int proximity = 0; + for (int i = 0; i < NUM_BINS; ++i) { proximity += std::min(bgTexture.r[i], curTextureHist.r[i]); proximity += std::min(bgTexture.g[i], curTextureHist.g[i]); proximity += std::min(bgTexture.b[i], curTextureHist.b[i]); } - return proximity; + return proximity; } -void TextureBGS::BgsCompare(TextureArray* bgModel, TextureHistogram* curTextureHist, - unsigned char* modeArray, float threshold, BwImage& fgMask) +void TextureBGS::BgsCompare(TextureArray* bgModel, TextureHistogram* curTextureHist, + unsigned char* modeArray, float threshold, BwImage& fgMask) { cvZero(fgMask.Ptr()); - for(int y = REGION_R+TEXTURE_R; y < fgMask.Ptr()->height-REGION_R-TEXTURE_R; ++y) + for (int y = REGION_R + TEXTURE_R; y < fgMask.Ptr()->height - REGION_R - TEXTURE_R; ++y) { - for(int x = REGION_R+TEXTURE_R; x < fgMask.Ptr()->width-REGION_R-TEXTURE_R; ++x) - { - int index = x+y*(fgMask.Ptr()->width); + for (int x = REGION_R + TEXTURE_R; x < fgMask.Ptr()->width - REGION_R - TEXTURE_R; ++x) + { + int index = x + y*(fgMask.Ptr()->width); // find closest matching texture in background model int maxProximity = -1; - for(int m = 0; m < NUM_MODES; ++m) + for (int m = 0; m < NUM_MODES; ++m) { int proximity = ProximityMeasure(bgModel[index].mode[m], curTextureHist[index]); - if(proximity > maxProximity) + if (proximity > maxProximity) { maxProximity = proximity; modeArray[index] = m; } } - if(maxProximity < threshold) - fgMask(y,x) = 255; + if (maxProximity < threshold) + fgMask(y, x) = 255; } } } -void TextureBGS::UpdateModel(BwImage& fgMask, TextureArray* bgModel, - TextureHistogram* curTextureHist, unsigned char* modeArray) +void TextureBGS::UpdateModel(BwImage& fgMask, TextureArray* bgModel, + TextureHistogram* curTextureHist, unsigned char* modeArray) { - for(int y = REGION_R+TEXTURE_R; y < fgMask.Ptr()->height-REGION_R-TEXTURE_R; ++y) + for (int y = REGION_R + TEXTURE_R; y < fgMask.Ptr()->height - REGION_R - TEXTURE_R; ++y) { - for(int x = REGION_R+TEXTURE_R; x < fgMask.Ptr()->width-REGION_R-TEXTURE_R; ++x) - { - int index = x+y*(fgMask.Ptr()->width); + for (int x = REGION_R + TEXTURE_R; x < fgMask.Ptr()->width - REGION_R - TEXTURE_R; ++x) + { + int index = x + y*(fgMask.Ptr()->width); - if(fgMask(y,x) == 0) + if (fgMask(y, x) == 0) { - for(int i = 0; i < NUM_BINS; ++i) + for (int i = 0; i < NUM_BINS; ++i) { bgModel[index].mode[modeArray[index]].r[i] - = (unsigned char)(ALPHA*curTextureHist[index].r[i] - + (1-ALPHA)*bgModel[index].mode[modeArray[index]].r[i] + 0.5); + = (unsigned char)(ALPHA*curTextureHist[index].r[i] + + (1 - ALPHA)*bgModel[index].mode[modeArray[index]].r[i] + 0.5); } - } + } } - } + } } diff --git a/package_bgs/dp/TextureBGS.h b/package_bgs/dp/TextureBGS.h index 573e6f9af7992833f310dba72aa9a4e5e72bc771..2650f04cb1b55a8a71ce157e40b9806a73d7a8af 100644 --- a/package_bgs/dp/TextureBGS.h +++ b/package_bgs/dp/TextureBGS.h @@ -14,6 +14,8 @@ 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" @@ -23,7 +25,7 @@ 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 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 @@ -48,8 +50,8 @@ public: 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); + 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.cpp b/package_bgs/dp/WrenGA.cpp index 16e2640b79b02fe51bf486c62754a6a21455f534..80a9e27e746cf14789f7001f412b50adafa87f0d 100644 --- a/package_bgs/dp/WrenGA.cpp +++ b/package_bgs/dp/WrenGA.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * WrenGA.h * -* Purpose: Implementation of the running Gaussian average background +* 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) @@ -36,114 +36,114 @@ using namespace Algorithms::BackgroundSubtraction; WrenGA::WrenGA() { - m_gaussian = NULL; + m_gaussian = NULL; } WrenGA::~WrenGA() { - delete[] m_gaussian; + delete[] m_gaussian; } void WrenGA::Initalize(const BgsParams& param) { - m_params = (WrenParams&)param; - - m_variance = 36.0f; - - // GMM for each pixel - m_gaussian = new GAUSSIAN[m_params.Size()]; - for(unsigned int i = 0; i < m_params.Size(); ++i) - { - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - m_gaussian[i].mu[ch] = 0; - m_gaussian[i].var[ch] = 0; - } - } - - m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); + m_params = (WrenParams&)param; + + m_variance = 36.0f; + + // GMM for each pixel + m_gaussian = new GAUSSIAN[m_params.Size()]; + for (unsigned int i = 0; i < m_params.Size(); ++i) + { + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + m_gaussian[i].mu[ch] = 0; + m_gaussian[i].var[ch] = 0; + } + } + + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); } void WrenGA::InitModel(const RgbImage& data) { - int pos = 0; - - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - m_gaussian[pos].mu[ch] = data(r,c,ch); - m_gaussian[pos].var[ch] = m_variance; - } - - pos++; - } - } + int pos = 0; + + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + m_gaussian[pos].mu[ch] = data(r, c, ch); + m_gaussian[pos].var[ch] = m_variance; + } + + pos++; + } + } } -void WrenGA::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void WrenGA::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - int pos = 0; - - for(unsigned int r = 0; r < m_params.Height(); ++r) - { - for(unsigned int c = 0; c < m_params.Width(); ++c) - { - // perform conditional updating only if we are passed the learning phase - if(update_mask(r,c) == BACKGROUND || frame_num < m_params.LearningFrames()) - { - float dR = m_gaussian[pos].mu[0] - data(r,c,0); - float dG = m_gaussian[pos].mu[1] - data(r,c,1); - float dB = m_gaussian[pos].mu[2] - data(r,c,2); - - float dist = (dR*dR + dG*dG + dB*dB); - - m_gaussian[pos].mu[0] -= m_params.Alpha()*(dR); - m_gaussian[pos].mu[1] -= m_params.Alpha()*(dG); - m_gaussian[pos].mu[2] -= m_params.Alpha()*(dB); - - float sigmanew = m_gaussian[pos].var[0] + m_params.Alpha()*(dist-m_gaussian[pos].var[0]); - m_gaussian[pos].var[0] = sigmanew < 4 ? 4 : sigmanew > 5*m_variance ? 5*m_variance : sigmanew; - - m_background(r, c, 0) = (unsigned char)(m_gaussian[pos].mu[0] + 0.5); - m_background(r, c, 1) = (unsigned char)(m_gaussian[pos].mu[1] + 0.5); - m_background(r, c, 2) = (unsigned char)(m_gaussian[pos].mu[2] + 0.5); - } - - pos++; - } - } + int pos = 0; + + for (unsigned int r = 0; r < m_params.Height(); ++r) + { + for (unsigned int c = 0; c < m_params.Width(); ++c) + { + // perform conditional updating only if we are passed the learning phase + if (update_mask(r, c) == BACKGROUND || frame_num < m_params.LearningFrames()) + { + float dR = m_gaussian[pos].mu[0] - data(r, c, 0); + float dG = m_gaussian[pos].mu[1] - data(r, c, 1); + float dB = m_gaussian[pos].mu[2] - data(r, c, 2); + + float dist = (dR*dR + dG*dG + dB*dB); + + m_gaussian[pos].mu[0] -= m_params.Alpha()*(dR); + m_gaussian[pos].mu[1] -= m_params.Alpha()*(dG); + m_gaussian[pos].mu[2] -= m_params.Alpha()*(dB); + + float sigmanew = m_gaussian[pos].var[0] + m_params.Alpha()*(dist - m_gaussian[pos].var[0]); + m_gaussian[pos].var[0] = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew; + + m_background(r, c, 0) = (unsigned char)(m_gaussian[pos].mu[0] + 0.5); + m_background(r, c, 1) = (unsigned char)(m_gaussian[pos].mu[1] + 0.5); + m_background(r, c, 2) = (unsigned char)(m_gaussian[pos].mu[2] + 0.5); + } + + pos++; + } + } } -void WrenGA::SubtractPixel(int r, int c, const RgbPixel& pixel, - unsigned char& low_threshold, - unsigned char& high_threshold) +void WrenGA::SubtractPixel(int r, int c, const RgbPixel& pixel, + unsigned char& low_threshold, + unsigned char& high_threshold) { - unsigned int pos = r*m_params.Width()+c; - - // calculate distance between model and pixel - float mu[NUM_CHANNELS]; - float var[1]; - float delta[NUM_CHANNELS]; - float dist = 0; - for(int ch = 0; ch < NUM_CHANNELS; ++ch) - { - mu[ch] = m_gaussian[pos].mu[ch]; - var[0] = m_gaussian[pos].var[0]; - delta[ch] = mu[ch] - pixel(ch); - dist += delta[ch]*delta[ch]; - } - - // calculate the squared distance and see if pixel fits the B/G model - low_threshold = BACKGROUND; - high_threshold = BACKGROUND; - - if(dist > m_params.LowThreshold()*var[0]) - low_threshold = FOREGROUND; - if(dist > m_params.HighThreshold()*var[0]) - high_threshold = FOREGROUND; + unsigned int pos = r*m_params.Width() + c; + + // calculate distance between model and pixel + float mu[NUM_CHANNELS]; + float var[1]; + float delta[NUM_CHANNELS]; + float dist = 0; + for (int ch = 0; ch < NUM_CHANNELS; ++ch) + { + mu[ch] = m_gaussian[pos].mu[ch]; + var[0] = m_gaussian[pos].var[0]; + delta[ch] = mu[ch] - pixel(ch); + dist += delta[ch] * delta[ch]; + } + + // calculate the squared distance and see if pixel fits the B/G model + low_threshold = BACKGROUND; + high_threshold = BACKGROUND; + + if (dist > m_params.LowThreshold()*var[0]) + low_threshold = FOREGROUND; + if (dist > m_params.HighThreshold()*var[0]) + high_threshold = FOREGROUND; } /////////////////////////////////////////////////////////////////////////////// @@ -154,20 +154,20 @@ void WrenGA::SubtractPixel(int r, int c, const RgbPixel& pixel, // (the memory should already be reserved) // values: 255-foreground, 125-shadow, 0-background /////////////////////////////////////////////////////////////////////////////// -void WrenGA::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mask, BwImage& high_threshold_mask) +void WrenGA::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mask, BwImage& high_threshold_mask) { - unsigned char low_threshold, high_threshold; - - // 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) - { - SubtractPixel(r, c, data(r,c), low_threshold, high_threshold); - low_threshold_mask(r,c) = low_threshold; - high_threshold_mask(r,c) = high_threshold; - } - } + unsigned char low_threshold, high_threshold; + + // 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) + { + SubtractPixel(r, c, data(r, c), low_threshold, high_threshold); + low_threshold_mask(r, c) = low_threshold; + high_threshold_mask(r, c) = high_threshold; + } + } } diff --git a/package_bgs/dp/WrenGA.h b/package_bgs/dp/WrenGA.h index 116c292a9adfc6f9c80313865d5b501daec8e269..97e97ee7022c0ff3964332d083e93858fabe038c 100644 --- a/package_bgs/dp/WrenGA.h +++ b/package_bgs/dp/WrenGA.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * WrenGA.hpp * -* Purpose: Implementation of the running Gaussian average background +* 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) @@ -33,16 +33,14 @@ 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.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); ******************************************************************************/ - -#ifndef WREN_GA_H -#define WREN_GA_H +#pragma once #include "Bgs.h" @@ -74,7 +72,7 @@ namespace Algorithms // --- Mean BGS algorithm --- class WrenGA : public Bgs { - private: + private: struct GAUSSIAN { float mu[NUM_CHANNELS]; @@ -88,19 +86,19 @@ namespace Algorithms 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); + 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, + 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. + // Initial variance for the newly generated components. float m_variance; // dynamic array for the mixture of Gaussians @@ -110,11 +108,3 @@ namespace Algorithms }; } } - -#endif - - - - - - diff --git a/package_bgs/dp/ZivkovicAGMM.cpp b/package_bgs/dp/ZivkovicAGMM.cpp index 041ffc43ca598d9035dc20018602e1a6ac22d905..f73d5a145b80710cff510063b1762c260b9c333f 100644 --- a/package_bgs/dp/ZivkovicAGMM.cpp +++ b/package_bgs/dp/ZivkovicAGMM.cpp @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * ZivkovicAGMM.cpp * -* Purpose: Implementation of the Gaussian mixture model (GMM) background +* Purpose: Implementation of the Gaussian mixture model (GMM) background * subtraction algorithm developed by Z. Zivkovic. * * Author: Donovan Parks, September 2007 @@ -28,13 +28,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * following papers: * * "Improved adaptive Gausian mixture model for background subtraction" -* Z.Zivkovic +* Z.Zivkovic * International Conference Pattern Recognition, UK, August, 2004 * * -* "Efficient Adaptive Density Estimapion per Image Pixel for the +* "Efficient Adaptive Density Estimapion per Image Pixel for the * Task of Background Subtraction" -* Z.Zivkovic, F. van der Heijden +* 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 @@ -46,328 +46,328 @@ using namespace Algorithms::BackgroundSubtraction; ZivkovicAGMM::ZivkovicAGMM() { - m_modes = NULL; - m_modes_per_pixel = NULL; + m_modes = NULL; + m_modes_per_pixel = NULL; } ZivkovicAGMM::~ZivkovicAGMM() { - delete[] m_modes; - delete[] m_modes_per_pixel; + delete[] m_modes; + delete[] m_modes_per_pixel; } void ZivkovicAGMM::Initalize(const BgsParams& param) { - m_params = (ZivkovicParams&)param; + m_params = (ZivkovicParams&)param; - m_num_bands = 3; //always 3 - not implemented for other values! - m_bg_threshold = 0.75f; //1-cf from the paper - m_variance = 36.0f; // variance for the new mode - m_complexity_prior = 0.05f; // complexity reduction prior constant + m_num_bands = 3; //always 3 - not implemented for other values! + m_bg_threshold = 0.75f; //1-cf from the paper + m_variance = 36.0f; // variance for the new mode + m_complexity_prior = 0.05f; // complexity reduction prior constant - // GMM for each pixel - m_modes = new GMM[m_params.Size()*m_params.MaxModes()]; + // GMM for each pixel + m_modes = new GMM[m_params.Size()*m_params.MaxModes()]; - // used modes per pixel - m_modes_per_pixel = new unsigned char[m_params.Size()]; + // used modes per pixel + m_modes_per_pixel = new unsigned char[m_params.Size()]; - m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); + m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3); } void ZivkovicAGMM::InitModel(const RgbImage& data) { - for(unsigned int i = 0; i < m_params.Size(); ++i) - { - m_modes_per_pixel[i] = 0; - } - - for(unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) - { - m_modes[i].weight = 0; - m_modes[i].sigma = 0; - m_modes[i].muR = 0; - m_modes[i].muG = 0; - m_modes[i].muB = 0; - } + for (unsigned int i = 0; i < m_params.Size(); ++i) + { + m_modes_per_pixel[i] = 0; + } + + for (unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i) + { + m_modes[i].weight = 0; + m_modes[i].sigma = 0; + m_modes[i].muR = 0; + m_modes[i].muG = 0; + m_modes[i].muB = 0; + } } -void ZivkovicAGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) +void ZivkovicAGMM::Update(int frame_num, const RgbImage& data, const BwImage& update_mask) { - // it doesn't make sense to have conditional updates in the GMM framework + // it doesn't make sense to have conditional updates in the GMM framework } -void ZivkovicAGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char* pModesUsed, - unsigned char& low_threshold, unsigned char& high_threshold) +void ZivkovicAGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char* pModesUsed, + 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=0; - bool bBackgroundLow=false; - bool bBackgroundHigh=false; - - float fOneMinAlpha = 1-m_params.Alpha(); - - float prune = -m_params.Alpha()*m_complexity_prior; - - int nModes =* pModesUsed; - 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 < nModes; ++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 < nModes; 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].sigma; - 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; - - //check fit - if (dist < m_params.LowThreshold()*var) - { - ///// - //belongs to the mode - 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+prune; - 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 update speed for cov matrice - //not needed - //k=k>20*m_m_params.Alpha()?20*m_m_params.Alpha():k; - //float sigmanew = var + k*((0.33*(dR*dR+dG*dG+dB*dB))-var); - //float sigmanew = var + k*((dR*dR+dG*dG+dB*dB)-var); - //float sigmanew = var + k*((0.33*dist)-var); - float sigmanew = var + k*(dist-var); - - //limit the variance - m_modes[pos].sigma = sigmanew < 4 ? 4 : sigmanew > 5*m_variance ? 5*m_variance : sigmanew; - - // Sort weights so they are in desending order. Note that only the weight for this - // mode will increase and that the weight for all modes that were previously larger than - // this one have already been modified and will not be modified again. Thus, we just need to - // the correct position of this mode in the already sorted list. - - // Zivkovic implementation has been modified for clarity, but the results are equivalent - /* - for (int iLocal = iModes;iLocal>0;iLocal--) - { - long posLocal=posPixel + iLocal; - if (weight < (m_modes[posLocal-1].weight)) - { - break; - } - else - { - //swap - GMM temp = m_modes[posLocal]; - m_modes[posLocal] = m_modes[posLocal-1]; - m_modes[posLocal-1] = temp; - } - } - */ - - for (int iLocal = iModes; iLocal > 0; iLocal--) - { - long posLocal = posPixel + iLocal; - if (m_modes[posLocal].weight > m_modes[posLocal-1].weight) - { - //swap - GMM temp = m_modes[posLocal]; - m_modes[posLocal] = m_modes[posLocal-1]; - m_modes[posLocal-1] = temp; - } - else - { - break; - } - } - } - else - { - weight = fOneMinAlpha*weight+prune; - //check prune - if (weight < -prune) - { - weight=0.0; - nModes--; - } - m_modes[pos].weight = weight; - } - //check if it fits the current mode (2.5 sigma) - /////// - } - //fit not found yet - ///// - else - { - weight = fOneMinAlpha*weight + prune; - //check prune - if (weight < -prune) - { - weight=0.0; - nModes--; - } - m_modes[pos].weight = weight; - } - totalWeight += weight; - } - - //renormalize weights so they sum to 1 - for (int iLocal = 0; iLocal < nModes; iLocal++) - { - m_modes[posPixel+ iLocal].weight = m_modes[posPixel+ iLocal].weight/totalWeight; - } - - //make new mode if needed and exit - if (!bFitsPDF) - { - if (nModes == m_params.MaxModes()) - { - //replace the weakest - } - else - { - nModes++; - } - pos = posPixel + nModes-1; - - if (nModes==1) - m_modes[pos].weight=1; - else - m_modes[pos].weight=m_params.Alpha(); - - // Zivkovic implementation changes as this will not result in the - // weights adding to 1 - /* - int iLocal; - for (iLocal = 0; iLocal < m_params.MaxModes()odes-1; iLocal++) - { - m_modes[posPixel+ iLocal].weight *= fOneMinAlpha; - } - */ - - // Revised implementation: - //renormalize weights - int iLocal; - float sum = 0.0; - for (iLocal = 0; iLocal < nModes; iLocal++) - { - sum += m_modes[posPixel+ iLocal].weight; - } - - float invSum = 1.0f/sum; - for (iLocal = 0; iLocal < nModes; iLocal++) - { - m_modes[posPixel+ iLocal].weight *= invSum; - } - - m_modes[pos].muR=pixel(0); - m_modes[pos].muG=pixel(1); - m_modes[pos].muB=pixel(2); - m_modes[pos].sigma=m_variance; - - // Zivkovic implementation to sort GMM so they are sorted in descending order according to their weight. - // It has been revised for clarity, but the results are equivalent - /* - for (iLocal = m_params.MaxModes()odes-1; iLocal > 0; iLocal--) - { - long posLocal = posPixel + iLocal; - if (m_params.Alpha() < (m_modes[posLocal-1].weight)) - { - break; - } - else - { - //swap - GMM temp = m_modes[posLocal]; - m_modes[posLocal] = m_modes[posLocal-1]; - m_modes[posLocal-1] = temp; - } - } - */ - - // sort GMM so they are sorted in descending order according to their weight - for (iLocal = nModes-1; iLocal > 0; iLocal--) - { - long posLocal = posPixel + iLocal; - if (m_modes[posLocal].weight > m_modes[posLocal-1].weight) - { - //swap - GMM temp = m_modes[posLocal]; - m_modes[posLocal] = m_modes[posLocal-1]; - m_modes[posLocal-1] = temp; - } - else - { - break; - } - } - } - - //set the number of modes - *pModesUsed=nModes; - - if(bBackgroundLow) - { - low_threshold = BACKGROUND; - } - else - { - low_threshold = FOREGROUND; - } - - if(bBackgroundHigh) - { - high_threshold = BACKGROUND; - } - else - { - high_threshold = FOREGROUND; - } + //calculate distances to the modes (+ sort???) + //here we need to go in descending order!!! + long pos; + bool bFitsPDF = 0; + bool bBackgroundLow = false; + bool bBackgroundHigh = false; + + float fOneMinAlpha = 1 - m_params.Alpha(); + + float prune = -m_params.Alpha()*m_complexity_prior; + + int nModes = *pModesUsed; + 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 < nModes; ++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 < nModes; 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].sigma; + 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; + + //check fit + if (dist < m_params.LowThreshold()*var) + { + ///// + //belongs to the mode + 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 + prune; + 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 update speed for cov matrice + //not needed + //k=k>20*m_m_params.Alpha()?20*m_m_params.Alpha():k; + //float sigmanew = var + k*((0.33*(dR*dR+dG*dG+dB*dB))-var); + //float sigmanew = var + k*((dR*dR+dG*dG+dB*dB)-var); + //float sigmanew = var + k*((0.33*dist)-var); + float sigmanew = var + k*(dist - var); + + //limit the variance + m_modes[pos].sigma = sigmanew < 4 ? 4 : sigmanew > 5 * m_variance ? 5 * m_variance : sigmanew; + + // Sort weights so they are in desending order. Note that only the weight for this + // mode will increase and that the weight for all modes that were previously larger than + // this one have already been modified and will not be modified again. Thus, we just need to + // the correct position of this mode in the already sorted list. + + // Zivkovic implementation has been modified for clarity, but the results are equivalent + /* + for (int iLocal = iModes;iLocal>0;iLocal--) + { + long posLocal=posPixel + iLocal; + if (weight < (m_modes[posLocal-1].weight)) + { + break; + } + else + { + //swap + GMM temp = m_modes[posLocal]; + m_modes[posLocal] = m_modes[posLocal-1]; + m_modes[posLocal-1] = temp; + } + } + */ + + for (int iLocal = iModes; iLocal > 0; iLocal--) + { + long posLocal = posPixel + iLocal; + if (m_modes[posLocal].weight > m_modes[posLocal - 1].weight) + { + //swap + GMM temp = m_modes[posLocal]; + m_modes[posLocal] = m_modes[posLocal - 1]; + m_modes[posLocal - 1] = temp; + } + else + { + break; + } + } + } + else + { + weight = fOneMinAlpha*weight + prune; + //check prune + if (weight < -prune) + { + weight = 0.0; + nModes--; + } + m_modes[pos].weight = weight; + } + //check if it fits the current mode (2.5 sigma) + /////// + } + //fit not found yet + ///// + else + { + weight = fOneMinAlpha*weight + prune; + //check prune + if (weight < -prune) + { + weight = 0.0; + nModes--; + } + m_modes[pos].weight = weight; + } + totalWeight += weight; + } + + //renormalize weights so they sum to 1 + for (int iLocal = 0; iLocal < nModes; iLocal++) + { + m_modes[posPixel + iLocal].weight = m_modes[posPixel + iLocal].weight / totalWeight; + } + + //make new mode if needed and exit + if (!bFitsPDF) + { + if (nModes == m_params.MaxModes()) + { + //replace the weakest + } + else + { + nModes++; + } + pos = posPixel + nModes - 1; + + if (nModes == 1) + m_modes[pos].weight = 1; + else + m_modes[pos].weight = m_params.Alpha(); + + // Zivkovic implementation changes as this will not result in the + // weights adding to 1 + /* + int iLocal; + for (iLocal = 0; iLocal < m_params.MaxModes()odes-1; iLocal++) + { + m_modes[posPixel+ iLocal].weight *= fOneMinAlpha; + } + */ + + // Revised implementation: + //renormalize weights + int iLocal; + float sum = 0.0; + for (iLocal = 0; iLocal < nModes; iLocal++) + { + sum += m_modes[posPixel + iLocal].weight; + } + + float invSum = 1.0f / sum; + for (iLocal = 0; iLocal < nModes; iLocal++) + { + m_modes[posPixel + iLocal].weight *= invSum; + } + + m_modes[pos].muR = pixel(0); + m_modes[pos].muG = pixel(1); + m_modes[pos].muB = pixel(2); + m_modes[pos].sigma = m_variance; + + // Zivkovic implementation to sort GMM so they are sorted in descending order according to their weight. + // It has been revised for clarity, but the results are equivalent + /* + for (iLocal = m_params.MaxModes()odes-1; iLocal > 0; iLocal--) + { + long posLocal = posPixel + iLocal; + if (m_params.Alpha() < (m_modes[posLocal-1].weight)) + { + break; + } + else + { + //swap + GMM temp = m_modes[posLocal]; + m_modes[posLocal] = m_modes[posLocal-1]; + m_modes[posLocal-1] = temp; + } + } + */ + + // sort GMM so they are sorted in descending order according to their weight + for (iLocal = nModes - 1; iLocal > 0; iLocal--) + { + long posLocal = posPixel + iLocal; + if (m_modes[posLocal].weight > m_modes[posLocal - 1].weight) + { + //swap + GMM temp = m_modes[posLocal]; + m_modes[posLocal] = m_modes[posLocal - 1]; + m_modes[posLocal - 1] = temp; + } + else + { + break; + } + } + } + + //set the number of modes + *pModesUsed = nModes; + + if (bBackgroundLow) + { + low_threshold = BACKGROUND; + } + else + { + low_threshold = FOREGROUND; + } + + if (bBackgroundHigh) + { + high_threshold = BACKGROUND; + } + else + { + high_threshold = FOREGROUND; + } } @@ -379,30 +379,30 @@ void ZivkovicAGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned // (the memory should already be reserved) // values: 255-foreground, 125-shadow, 0-background /////////////////////////////////////////////////////////////////////////////// -void ZivkovicAGMM::Subtract(int frame_num, const RgbImage& data, - BwImage& low_threshold_mask, BwImage& high_threshold_mask) +void ZivkovicAGMM::Subtract(int frame_num, const RgbImage& data, + BwImage& low_threshold_mask, BwImage& high_threshold_mask) { - unsigned char low_threshold, high_threshold; - - // update each pixel of the image - long posPixel; - unsigned char* pUsedModes=m_modes_per_pixel; - 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), pUsedModes, 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; - - pUsedModes++; - } - } + unsigned char low_threshold, high_threshold; + + // update each pixel of the image + long posPixel; + unsigned char* pUsedModes = m_modes_per_pixel; + 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), pUsedModes, 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; + + pUsedModes++; + } + } } diff --git a/package_bgs/dp/ZivkovicAGMM.h b/package_bgs/dp/ZivkovicAGMM.h index 1cd99b0211aa31056dc4df69cb3672138eedf3ae..07da9c340edc612e69ee7d6dc1ead7a7f4062b44 100644 --- a/package_bgs/dp/ZivkovicAGMM.h +++ b/package_bgs/dp/ZivkovicAGMM.h @@ -18,7 +18,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * * ZivkovicAGMM.hpp * -* Purpose: Implementation of the Gaussian mixture model (GMM) background +* Purpose: Implementation of the Gaussian mixture model (GMM) background * subtraction algorithm developed by Z. Zivkovic. * * Author: Donovan Parks, September 2007 @@ -28,13 +28,13 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. * following papers: * * "Improved adaptive Gausian mixture model for background subtraction" -* Z.Zivkovic +* Z.Zivkovic * International Conference Pattern Recognition, UK, August, 2004 * * -* "Efficient Adaptive Density Estimapion per Image Pixel for the +* "Efficient Adaptive Density Estimapion per Image Pixel for the * Task of Background Subtraction" -* Z.Zivkovic, F. van der Heijden +* 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 @@ -43,16 +43,14 @@ 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.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); ******************************************************************************/ - -#ifndef ZIVKOVIC_AGMM_H -#define ZIVKOVIC_AGMM_H +#pragma once #include "Bgs.h" @@ -71,18 +69,18 @@ namespace Algorithms int &MaxModes() { return m_max_modes; } 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 + // 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 (not standard deviations) + // It is usual easiest to think of these thresholds as being the number of variances (not standard deviations) // 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. + // set alpha=1/T. float m_alpha; // Maximum number of modes (Gaussian components) that will be used per pixel @@ -109,14 +107,14 @@ namespace Algorithms 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); + 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(long posPixel, const RgbPixel& pixel, unsigned char* pModesUsed, + void SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char* pModesUsed, unsigned char& lowThreshold, unsigned char& highThreshold); // User adjustable parameters @@ -128,13 +126,13 @@ namespace Algorithms // 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. + // 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; // This is related to the number of samples needed to accept that a component - // actually exists. + // actually exists. float m_complexity_prior; //data @@ -150,11 +148,3 @@ namespace Algorithms }; } } - -#endif - - - - - - diff --git a/package_bgs/jmo/BlobResult.cpp b/package_bgs/jmo/BlobResult.cpp deleted file mode 100644 index 1a047c7dc9035e017eab230f1e49e401d25780cc..0000000000000000000000000000000000000000 --- a/package_bgs/jmo/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/jmo/MultiLayerBGS.h b/package_bgs/jmo/MultiLayerBGS.h deleted file mode 100644 index 29db9466281f8c12eda1997552f1f5adff05378c..0000000000000000000000000000000000000000 --- a/package_bgs/jmo/MultiLayerBGS.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "CMultiLayerBGS.h" - -class MultiLayerBGS : public IBGS -{ -public: - enum Status - { - MLBGS_NONE = -1, - MLBGS_LEARN = 0, - MLBGS_DETECT = 1 - }; - -private: - bool firstTime; - long long frameNumber; - cv::Mat img_foreground; - cv::Mat img_merged; - cv::Mat img_background; - bool showOutput; - bool saveModel; - bool disableDetectMode; - bool disableLearning; - int detectAfter; - CMultiLayerBGS* BGS; - Status status; - IplImage* img; - IplImage* org_img; - IplImage* fg_img; - IplImage* bg_img; - IplImage* fg_prob_img; - IplImage* fg_mask_img; - IplImage* fg_prob_img3; - IplImage* merged_img; - std::string bg_model_preload; - - bool loadDefaultParams; - - int max_mode_num; - float weight_updating_constant; - float texture_weight; - float bg_mode_percent; - int pattern_neig_half_size; - float pattern_neig_gaus_sigma; - float bg_prob_threshold; - float bg_prob_updating_threshold; - int robust_LBP_constant; - float min_noised_angle; - float shadow_rate; - float highlight_rate; - float bilater_filter_sigma_s; - float bilater_filter_sigma_r; - - float frame_duration; - - float mode_learn_rate_per_second; - float weight_learn_rate_per_second; - float init_mode_weight; - - float learn_mode_learn_rate_per_second; - float learn_weight_learn_rate_per_second; - float learn_init_mode_weight; - - float detect_mode_learn_rate_per_second; - float detect_weight_learn_rate_per_second; - float detect_init_mode_weight; - -public: - MultiLayerBGS(); - ~MultiLayerBGS(); - - void setStatus(Status status); - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); - -private: - void finish(void); - void saveConfig(); - void loadConfig(); -}; \ No newline at end of file diff --git a/package_bgs/jmo/blob.cpp b/package_bgs/jmo/blob.cpp deleted file mode 100644 index 3629714ccf0b93e3b244f7c6070e5fe8396da44a..0000000000000000000000000000000000000000 --- a/package_bgs/jmo/blob.cpp +++ /dev/null @@ -1,1149 +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" -#include <opencv2/opencv.hpp> - -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/lb/BGModel.cpp b/package_bgs/lb/BGModel.cpp index c42bec73e34dfb1dd83dc319bbb8569281521a62..3c73b53ce3f3ae7e8e4cb66304279ffd046fb85a 100644 --- a/package_bgs/lb/BGModel.cpp +++ b/package_bgs/lb/BGModel.cpp @@ -14,9 +14,9 @@ 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 +/* 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 @@ -38,11 +38,11 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. namespace lb_library { - BGModel::BGModel(int width, int height): m_width(width), m_height(height) + 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); + 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); @@ -51,9 +51,9 @@ namespace lb_library BGModel::~BGModel() { - if (m_SrcImage!=NULL) cvReleaseImage(&m_SrcImage); - if (m_BGImage!=NULL) cvReleaseImage(&m_BGImage); - if (m_FGImage!=NULL) cvReleaseImage(&m_FGImage); + if (m_SrcImage != NULL) cvReleaseImage(&m_SrcImage); + if (m_BGImage != NULL) cvReleaseImage(&m_BGImage); + if (m_FGImage != NULL) cvReleaseImage(&m_FGImage); } IplImage* BGModel::GetSrc() @@ -73,15 +73,15 @@ namespace lb_library void BGModel::InitModel(IplImage* image) { - cvCopy(image,m_SrcImage); + cvCopy(image, m_SrcImage); Init(); return; } void BGModel::UpdateModel(IplImage* image) { - cvCopy(image,m_SrcImage); + cvCopy(image, m_SrcImage); Update(); return; } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModel.h b/package_bgs/lb/BGModel.h index 77f04902ca3dab6fce668d87490a77dfb3bd41b6..d47ad6242bd40995a94337b7bb511d8979851837 100644 --- a/package_bgs/lb/BGModel.h +++ b/package_bgs/lb/BGModel.h @@ -14,9 +14,9 @@ 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 +/* 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 @@ -33,9 +33,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifndef BGMODEL_H -#define BGMODEL_H +#pragma once #include <opencv2/opencv.hpp> #include <math.h> @@ -54,7 +52,7 @@ namespace lb_library void InitModel(IplImage* image); void UpdateModel(IplImage* image); - + virtual void setBGModelParameter(int id, int value) {}; virtual IplImage* GetSrc(); @@ -62,17 +60,15 @@ namespace lb_library 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; }; } - -#endif diff --git a/package_bgs/lb/BGModelFuzzyGauss.cpp b/package_bgs/lb/BGModelFuzzyGauss.cpp index 8706b1376e76f635eae77759b2ab59c63808d152..b249052bc4920a77bc49c1d7e0b9a0acb0fbcdfc 100644 --- a/package_bgs/lb/BGModelFuzzyGauss.cpp +++ b/package_bgs/lb/BGModelFuzzyGauss.cpp @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelFuzzyGauss.cpp Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -40,7 +40,7 @@ namespace lb_library { namespace FuzzyGaussian { - BGModelFuzzyGauss::BGModelFuzzyGauss(int width, int height) : BGModel(width,height) + BGModelFuzzyGauss::BGModelFuzzyGauss(int width, int height) : BGModel(width, height) { m_alphamax = ALPHAFUZZYGAUSS; m_threshold = THRESHOLDFUZZYGAUSS * THRESHOLDFUZZYGAUSS; @@ -53,7 +53,7 @@ namespace lb_library DBLRGB *pMu = m_pMu; DBLRGB *pVar = m_pVar; - for(int k = 0; k < (m_width * m_height); k++) + for (int k = 0; k < (m_width * m_height); k++) { pMu->Red = 0.0; pMu->Green = 0.0; @@ -70,15 +70,15 @@ namespace lb_library BGModelFuzzyGauss::~BGModelFuzzyGauss() { - delete [] m_pMu; - delete [] m_pVar; + delete[] m_pMu; + delete[] m_pVar; } void BGModelFuzzyGauss::setBGModelParameter(int id, int value) { - double dvalue = (double)value/255.0; + double dvalue = (double)value / 255.0; - switch(id) + switch (id) { case 0: m_threshold = 100.0*dvalue*dvalue; @@ -107,9 +107,9 @@ namespace lb_library Image<BYTERGB> prgbSrc(m_SrcImage); - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + for (int j = 0; j < m_width; j++) { pMu->Red = prgbSrc[i][j].Red; pMu->Green = prgbSrc[i][j].Green; @@ -136,13 +136,13 @@ namespace lb_library Image<BYTERGB> prgbBG(m_BGImage); Image<BYTERGB> prgbFG(m_FGImage); - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + 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; + 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) @@ -150,53 +150,53 @@ namespace lb_library 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 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; + if (d2 < m_threshold) + fuzzyBG = d2 / m_threshold; // Fuzzy running average double alpha = m_alphamax*exp(FUZZYEXP*fuzzyBG); - if(dr*dr > DBL_MIN) + if (dr*dr > DBL_MIN) pMu->Red += alpha*dr; - if(dg*dg > DBL_MIN) + if (dg*dg > DBL_MIN) pMu->Green += alpha*dg; - if(db*db > DBL_MIN) + 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) + if (d*d > DBL_MIN) pVar->Red += alpha*d; d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) pVar->Green += alpha*d; d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue; - if(d*d > DBL_MIN) + 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); + 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) + 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].Red = (unsigned char)pMu->Red; + prgbBG[i][j].Green = (unsigned char)pMu->Green; prgbBG[i][j].Blue = (unsigned char)pMu->Blue; pMu++; @@ -207,4 +207,4 @@ namespace lb_library return; } } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModelFuzzyGauss.h b/package_bgs/lb/BGModelFuzzyGauss.h index 98a92e594c4783eca28bb85aba22cb1c2f125bd7..a73b7165080675520c3d6995074acbd1954795be 100644 --- a/package_bgs/lb/BGModelFuzzyGauss.h +++ b/package_bgs/lb/BGModelFuzzyGauss.h @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelFuzzyGauss.h Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -33,9 +33,7 @@ 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 */ - -#ifndef BGMODELFUZZYGAUSS_H -#define BGMODELFUZZYGAUSS_H +#pragma once #include "BGModel.h" @@ -71,5 +69,3 @@ namespace lb_library }; } } - -#endif diff --git a/package_bgs/lb/BGModelFuzzySom.cpp b/package_bgs/lb/BGModelFuzzySom.cpp index 189cb1aa3cd0faa138e70a197dafe6283eda0656..e7e59dda3b5c6c93209668edc50155c6d6d147bc 100644 --- a/package_bgs/lb/BGModelFuzzySom.cpp +++ b/package_bgs/lb/BGModelFuzzySom.cpp @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelFuzzySom.cpp Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -40,27 +40,27 @@ namespace lb_library { namespace FuzzyAdaptiveSOM { - BGModelFuzzySom::BGModelFuzzySom(int width, int height) : BGModel(width,height) + BGModelFuzzySom::BGModelFuzzySom(int width, int height) : BGModel(width, height) { - m_offset = (KERNEL - 1)/2; + m_offset = (KERNEL - 1) / 2; - if(SPAN_NEIGHBORS) - m_pad = 0; + 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_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 = 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 j = 0; j < m_heightSOM; j++) { - for(int i = 0; i < m_widthSOM; i++) + for (int i = 0; i < m_widthSOM; i++) { m_ppSOM[j][i].Red = 0.0; m_ppSOM[j][i].Green = 0.0; @@ -71,7 +71,7 @@ namespace lb_library // Create weights m_ppW = new double*[KERNEL]; - for(int n = 0; n < KERNEL; n++) + for (int n = 0; n < KERNEL; n++) m_ppW[n] = new double[KERNEL]; // Construct Gaussian kernel using Pascal's triangle @@ -81,15 +81,15 @@ namespace lb_library m_Wmax = DBL_MIN; cN = 1; - for(int j = 0; j < KERNEL; j++) + for (int j = 0; j < KERNEL; j++) { - cM = 1; + cM = 1; - for(int i = 0; i < KERNEL; i++) + for (int i = 0; i < KERNEL; i++) { m_ppW[j][i] = cN*cM; - if(m_ppW[j][i] > m_Wmax) + if (m_ppW[j][i] > m_Wmax) m_Wmax = m_ppW[j][i]; cM = cM * (KERNEL - 1 - i) / (i + 1); @@ -103,8 +103,8 @@ namespace lb_library m_epsilon1 = EPS1*EPS1; m_epsilon2 = EPS2*EPS2; - m_alpha1 = C1/m_Wmax; - m_alpha2 = C2/m_Wmax; + m_alpha1 = C1 / m_Wmax; + m_alpha2 = C2 / m_Wmax; m_K = 0; m_TSteps = TRAINING_STEPS; @@ -112,22 +112,22 @@ namespace lb_library BGModelFuzzySom::~BGModelFuzzySom() { - for(int n = 0; n < m_heightSOM; n++) - delete [] m_ppSOM[n]; + for (int n = 0; n < m_heightSOM; n++) + delete[] m_ppSOM[n]; - delete [] m_ppSOM; + delete[] m_ppSOM; - for(int n = 0; n < KERNEL; n++) - delete [] m_ppW[n]; + for (int n = 0; n < KERNEL; n++) + delete[] m_ppW[n]; - delete [] m_ppW; + delete[] m_ppW; } void BGModelFuzzySom::setBGModelParameter(int id, int value) { - double dvalue = (double)value/255.0; + double dvalue = (double)value / 255.0; - switch(id) + switch (id) { case 0: m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue; @@ -138,11 +138,11 @@ namespace lb_library break; case 2: - m_alpha2 = dvalue*dvalue*dvalue/m_Wmax; + m_alpha2 = dvalue*dvalue*dvalue / m_Wmax; break; case 3: - m_alpha1 = dvalue*dvalue*dvalue/m_Wmax; + m_alpha1 = dvalue*dvalue*dvalue / m_Wmax; break; case 5: @@ -157,21 +157,21 @@ namespace lb_library { Image<BYTERGB> prgbSrc(m_SrcImage); - for(int j = 0; j < m_height; j++) + for (int j = 0; j < m_height; j++) { int jj = m_offset + j*(N + m_pad); - for(int i = 0; i < m_width; i++) + for (int i = 0; i < m_width; i++) { - int ii = m_offset + i*(M + m_pad); + int ii = m_offset + i*(M + m_pad); - for(int l = 0; l < N; l++) + for (int l = 0; l < N; l++) { - for(int k = 0; k < M; k++) + 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_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; } } } @@ -184,11 +184,11 @@ namespace lb_library void BGModelFuzzySom::Update() { - double alpha,a; + double alpha, a; double epsilon; // calibration phase - if(m_K <= m_TSteps) + if (m_K <= m_TSteps) { epsilon = m_epsilon1; alpha = (m_alpha1 - m_K * (m_alpha1 - m_alpha2) / m_TSteps); @@ -204,11 +204,11 @@ namespace lb_library Image<BYTERGB> prgbBG(m_BGImage); Image<BYTERGB> prgbFG(m_FGImage); - for(int j = 0; j < m_height; j++) + for (int j = 0; j < m_height; j++) { int jj = m_offset + j*(N + m_pad); - for(int i = 0; i < m_width; i++) + for (int i = 0; i < m_width; i++) { int ii = m_offset + i*(M + m_pad); @@ -222,17 +222,17 @@ namespace lb_library int iiHit = ii; int jjHit = jj; - for(int l = 0; l < N; l++) + for (int l = 0; l < N; l++) { - for(int k = 0; k < M; k++) + 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 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) + if (d2 < d2min) { d2min = d2; iiHit = ii + k; @@ -243,16 +243,16 @@ namespace lb_library double fuzzyBG = 1.0; - if(d2min < epsilon) - fuzzyBG = d2min/epsilon; + 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 l = (jjHit - m_offset); l <= (jjHit + m_offset); l++) { - for(int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++) + for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++) { a = alphamax * m_ppW[l - jjHit + m_offset][k - iiHit + m_offset]; @@ -261,20 +261,20 @@ namespace lb_library double d; d = srcR - m_ppSOM[l][k].Red; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) m_ppSOM[l][k].Red += a*d; d = srcG - m_ppSOM[l][k].Green; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) m_ppSOM[l][k].Green += a*d; d = srcB - m_ppSOM[l][k].Blue; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) m_ppSOM[l][k].Blue += a*d; } } - if(fuzzyBG >= FUZZYTHRESH) + if (fuzzyBG >= FUZZYTHRESH) { // Set foreground image prgbFG[j][i].Red = prgbFG[j][i].Green = prgbFG[j][i].Blue = 255; @@ -284,7 +284,7 @@ namespace lb_library // 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; + 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; @@ -295,4 +295,4 @@ namespace lb_library return; } } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModelFuzzySom.h b/package_bgs/lb/BGModelFuzzySom.h index 2f21d3e01368863f6fa2188117b7527a520f82c4..ed0bf210e236a8acf02685c1e802be698ed4814d 100644 --- a/package_bgs/lb/BGModelFuzzySom.h +++ b/package_bgs/lb/BGModelFuzzySom.h @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelFuzzySom.h Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -33,9 +33,7 @@ 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 */ - -#ifndef BGMODELFUZZYSOM_H -#define BGMODELFUZZYSOM_H +#pragma once #include "BGModel.h" @@ -47,9 +45,9 @@ namespace lb_library const int M = 3; // width SOM (per pixel) const int N = 3; // height SOM (per pixel) - const int KERNEL = 3; // size Gaussian kernel + const int KERNEL = 3; // size Gaussian kernel - const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels // + 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 @@ -84,12 +82,10 @@ namespace lb_library double m_alpha2; DBLRGB** m_ppSOM; // SOM grid - double** m_ppW; // Weights + double** m_ppW; // Weights void Init(); void Update(); }; } } - -#endif diff --git a/package_bgs/lb/BGModelGauss.cpp b/package_bgs/lb/BGModelGauss.cpp index 6892d13b9b9820f8f61734b2bde3d37ce8c74c5d..28a8b9379606f6a34600ec9d677e74343ad0a522 100644 --- a/package_bgs/lb/BGModelGauss.cpp +++ b/package_bgs/lb/BGModelGauss.cpp @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelGauss.cpp Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -40,7 +40,7 @@ namespace lb_library { namespace SimpleGaussian { - BGModelGauss::BGModelGauss(int width, int height) : BGModel(width,height) + BGModelGauss::BGModelGauss(int width, int height) : BGModel(width, height) { m_alpha = ALPHAGAUSS; m_threshold = THRESHGAUSS*THRESHGAUSS; @@ -52,7 +52,7 @@ namespace lb_library DBLRGB *pMu = m_pMu; DBLRGB *pVar = m_pVar; - for(int k = 0; k < (m_width * m_height); k++) + for (int k = 0; k < (m_width * m_height); k++) { pMu->Red = 0.0; pMu->Green = 0.0; @@ -69,15 +69,15 @@ namespace lb_library BGModelGauss::~BGModelGauss() { - delete [] m_pMu; - delete [] m_pVar; + delete[] m_pMu; + delete[] m_pVar; } void BGModelGauss::setBGModelParameter(int id, int value) { - double dvalue = (double)value/255.0; + double dvalue = (double)value / 255.0; - switch(id) + switch (id) { case 0: m_threshold = 100.0*dvalue*dvalue; @@ -87,7 +87,7 @@ namespace lb_library m_noise = 100.0*dvalue; break; - case 2: + case 2: m_alpha = dvalue*dvalue*dvalue; break; } @@ -102,9 +102,9 @@ namespace lb_library Image<BYTERGB> prgbSrc(m_SrcImage); - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + for (int j = 0; j < m_width; j++) { pMu->Red = prgbSrc[i][j].Red; pMu->Green = prgbSrc[i][j].Green; @@ -131,62 +131,62 @@ namespace lb_library Image<BYTERGB> prgbBG(m_BGImage); Image<BYTERGB> prgbFG(m_FGImage); - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + 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; + double srcR = (double)prgbSrc[i][j].Red; + double srcG = (double)prgbSrc[i][j].Green; + double srcB = (double)prgbSrc[i][j].Blue; - // Mahalanobis distance + // 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 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; + 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; + prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255; // Update parameters - if(dr*dr > DBL_MIN) + if (dr*dr > DBL_MIN) pMu->Red += m_alpha*dr; - if(dg*dg > DBL_MIN) + if (dg*dg > DBL_MIN) pMu->Green += m_alpha*dg; - if(db*db > DBL_MIN) + 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) + if (d*d > DBL_MIN) pVar->Red += m_alpha*d; d = (srcG - pMu->Green)*(srcG - pMu->Green) - pVar->Green; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) pVar->Green += m_alpha*d; d = (srcB - pMu->Blue)*(srcB - pMu->Blue) - pVar->Blue; - if(d*d > DBL_MIN) + 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); + 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].Red = (unsigned char)pMu->Red; + prgbBG[i][j].Green = (unsigned char)pMu->Green; prgbBG[i][j].Blue = (unsigned char)pMu->Blue; pMu++; @@ -197,4 +197,4 @@ namespace lb_library return; } } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModelGauss.h b/package_bgs/lb/BGModelGauss.h index d36a716ab4094acd9ea431b6c834dc563ecfacae..0af6efe7beb9207d185ff15fc1d18df8c3657f3f 100644 --- a/package_bgs/lb/BGModelGauss.h +++ b/package_bgs/lb/BGModelGauss.h @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelGauss.h Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -33,9 +33,7 @@ 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 */ - -#ifndef BGMODELGAUSS_H -#define BGMODELGAUSS_H +#pragma once #include "BGModel.h" @@ -69,5 +67,3 @@ namespace lb_library }; } } - -#endif diff --git a/package_bgs/lb/BGModelMog.cpp b/package_bgs/lb/BGModelMog.cpp index df6986c90327115f7fb56d5066f976b7e1f8b3f7..036feabf1aaa3a819d3f816f43b98d97772c0a1e 100644 --- a/package_bgs/lb/BGModelMog.cpp +++ b/package_bgs/lb/BGModelMog.cpp @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelMog.cpp Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -54,9 +54,9 @@ namespace lb_library MOGDATA *pMOG = m_pMOG; int *pK = m_pK; - for(int i = 0; i < (m_width * m_height); i++) + for (int i = 0; i < (m_width * m_height); i++) { - for(int k = 0; k < NUMBERGAUSSIANS; k++) + for (int k = 0; k < NUMBERGAUSSIANS; k++) { pMOG->mu.Red = 0.0; pMOG->mu.Green = 0.0; @@ -72,27 +72,27 @@ namespace lb_library pMOG++; } - pK[i] = 0; + pK[i] = 0; } } BGModelMog::~BGModelMog() { - delete [] m_pMOG; - delete [] m_pK; + delete[] m_pMOG; + delete[] m_pK; } void BGModelMog::setBGModelParameter(int id, int value) { - double dvalue = (double)value/255.0; + double dvalue = (double)value / 255.0; - switch(id) + switch (id) { case 0: m_threshold = 100.0*dvalue*dvalue; break; - case 1: + case 1: m_T = dvalue; break; @@ -100,7 +100,7 @@ namespace lb_library m_alpha = dvalue*dvalue*dvalue; break; - case 3: + case 3: m_noise = 100.0*dvalue;; break; } @@ -116,9 +116,9 @@ namespace lb_library Image<BYTERGB> prgbSrc(m_SrcImage); int n = 0; - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + for (int j = 0; j < m_width; j++) { pMOG[0].mu.Red = prgbSrc[i][j].Red; pMOG[0].mu.Green = prgbSrc[i][j].Green; @@ -129,7 +129,7 @@ namespace lb_library 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); + pMOG[0].sortKey = pMOG[0].w / sqrt(pMOG[0].var.Red + pMOG[0].var.Green + pMOG[0].var.Blue); pK[n] = 1; n++; @@ -153,27 +153,27 @@ namespace lb_library Image<BYTERGB> prgbFG(m_FGImage); int n = 0; - for(int i = 0; i < m_height; i++) + for (int i = 0; i < m_height; i++) { - for(int j = 0; j < m_width; j++) + 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; + 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++) + 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; + double d2 = dr*dr / pMOG[k].var.Red + dg*dg / pMOG[k].var.Green + db*db / pMOG[k].var.Blue; - if(d2 < m_threshold) + if (d2 < m_threshold) { kHit = k; break; @@ -183,43 +183,43 @@ namespace lb_library // Adjust parameters // matching distribution found - if(kHit != -1) + if (kHit != -1) { - for(int k = 0; k < pK[n]; k++) + for (int k = 0; k < pK[n]; k++) { - if(k == kHit) + 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) + if (d*d > DBL_MIN) pMOG[k].mu.Red += m_alpha*d; d = srcG - pMOG[k].mu.Green; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) pMOG[k].mu.Green += m_alpha*d; d = srcB - pMOG[k].mu.Blue; - if(d*d > DBL_MIN) + 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) + 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) + 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) + 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); + 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; @@ -228,12 +228,12 @@ namespace lb_library // no match found... create new one else { - if(pK[n] < NUMBERGAUSSIANS) + if (pK[n] < NUMBERGAUSSIANS) pK[n]++; kHit = pK[n] - 1; - if(pK[n] == 1) + if (pK[n] == 1) pMOG[kHit].w = 1.0; else pMOG[kHit].w = LEARNINGRATEMOG; @@ -251,24 +251,24 @@ namespace lb_library double wsum = 0.0; - for(int k = 0; k < pK[n]; k++) + for (int k = 0; k < pK[n]; k++) wsum += pMOG[k].w; - double wfactor = 1.0/wsum; + double wfactor = 1.0 / wsum; - for(int k = 0; k < pK[n]; k++) + 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); + 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) + if (pMOG[kHit].sortKey > pMOG[k].sortKey) { - std::swap(pMOG[kHit],pMOG[k]); + std::swap(pMOG[kHit], pMOG[k]); break; } } @@ -277,21 +277,21 @@ namespace lb_library wsum = 0.0; - for(int k = 0; k < pK[n]; k++) + for (int k = 0; k < pK[n]; k++) { wsum += pMOG[k].w; - if(wsum > m_T) + if (wsum > m_T) { kBG = k; break; } } - if(kHit > kBG) - prgbFG[i][j].Red = prgbFG[i][j].Green = prgbFG[i][j].Blue = 255; + 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; + 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; @@ -306,4 +306,4 @@ namespace lb_library return; } } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModelMog.h b/package_bgs/lb/BGModelMog.h index c4e51a4447722bb0d8719297e1bd2e6269a53968..c75d1fdee92df5ebba23358f3321fcd06114c661 100644 --- a/package_bgs/lb/BGModelMog.h +++ b/package_bgs/lb/BGModelMog.h @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelMog.h Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -33,9 +33,7 @@ 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 */ - -#ifndef BGMODELMOGRGB_H -#define BGMODELMOGRGB_H +#pragma once #include "BGModel.h" @@ -79,5 +77,3 @@ namespace lb_library }; } } - -#endif diff --git a/package_bgs/lb/BGModelSom.cpp b/package_bgs/lb/BGModelSom.cpp index 256d4855f62d71aab321be466098f754fa7597ed..735af6e014669e777f01dad8518ac63b6e66456e 100644 --- a/package_bgs/lb/BGModelSom.cpp +++ b/package_bgs/lb/BGModelSom.cpp @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelSom.cpp Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -40,28 +40,28 @@ namespace lb_library { namespace AdaptiveSOM { - BGModelSom::BGModelSom(int width, int height) : BGModel(width,height) + BGModelSom::BGModelSom(int width, int height) : BGModel(width, height) { - m_offset = (KERNEL - 1)/2; + m_offset = (KERNEL - 1) / 2; - if(SPAN_NEIGHBORS) - m_pad = 0; + 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_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 = 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 j = 0; j < m_heightSOM; j++) { - for(int i = 0; i < m_widthSOM; i++) - { + 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; @@ -71,7 +71,7 @@ namespace lb_library // Create weights m_ppW = new double*[KERNEL]; - for(int n = 0; n < KERNEL; n++) + for (int n = 0; n < KERNEL; n++) m_ppW[n] = new double[KERNEL]; // Construct Gaussian kernel using Pascal's triangle @@ -81,16 +81,16 @@ namespace lb_library m_Wmax = DBL_MIN; cN = 1; - for(int j = 0; j < KERNEL; j++) + for (int j = 0; j < KERNEL; j++) { - cM = 1; + cM = 1; - for(int i = 0; i < KERNEL; i++) + 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]; + if (m_ppW[j][i] > m_Wmax) + m_Wmax = m_ppW[j][i]; cM = cM * (KERNEL - 1 - i) / (i + 1); } @@ -103,8 +103,8 @@ namespace lb_library m_epsilon1 = EPS1*EPS1; m_epsilon2 = EPS2*EPS2; - m_alpha1 = C1/m_Wmax; - m_alpha2 = C2/m_Wmax; + m_alpha1 = C1 / m_Wmax; + m_alpha2 = C2 / m_Wmax; m_K = 0; m_TSteps = TRAINING_STEPS; @@ -112,22 +112,22 @@ namespace lb_library BGModelSom::~BGModelSom() { - for(int n = 0; n < m_heightSOM; n++) - delete [] m_ppSOM[n]; + for (int n = 0; n < m_heightSOM; n++) + delete[] m_ppSOM[n]; - delete [] m_ppSOM; + delete[] m_ppSOM; - for(int n = 0; n < KERNEL; n++) - delete [] m_ppW[n]; + for (int n = 0; n < KERNEL; n++) + delete[] m_ppW[n]; - delete [] m_ppW; + delete[] m_ppW; } void BGModelSom::setBGModelParameter(int id, int value) { - double dvalue = (double)value/255.0; + double dvalue = (double)value / 255.0; - switch(id) + switch (id) { case 0: m_epsilon2 = 255.0*255.0*dvalue*dvalue*dvalue*dvalue; @@ -138,11 +138,11 @@ namespace lb_library break; case 2: - m_alpha2 = dvalue*dvalue*dvalue/m_Wmax; + m_alpha2 = dvalue*dvalue*dvalue / m_Wmax; break; case 3: - m_alpha1 = dvalue*dvalue*dvalue/m_Wmax; + m_alpha1 = dvalue*dvalue*dvalue / m_Wmax; break; case 5: @@ -157,21 +157,21 @@ namespace lb_library { Image<BYTERGB> prgbSrc(m_SrcImage); - for(int j = 0; j < m_height; j++) + for (int j = 0; j < m_height; j++) { int jj = m_offset + j*(N + m_pad); - for(int i = 0; i < m_width; i++) + for (int i = 0; i < m_width; i++) { - int ii = m_offset + i*(M + m_pad); + int ii = m_offset + i*(M + m_pad); - for(int l = 0; l < N; l++) + for (int l = 0; l < N; l++) { - for(int k = 0; k < M; k++) + 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_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; } } } @@ -184,18 +184,18 @@ namespace lb_library void BGModelSom::Update() { - double alpha,a; + double alpha, a; double epsilon; // calibration phase - if(m_K <= m_TSteps) - { + if (m_K <= m_TSteps) + { epsilon = m_epsilon1; - alpha = (m_alpha1-m_K*(m_alpha1-m_alpha2)/m_TSteps); + alpha = (m_alpha1 - m_K*(m_alpha1 - m_alpha2) / m_TSteps); m_K++; } else // online phase - { + { epsilon = m_epsilon2; alpha = m_alpha2; } @@ -204,11 +204,11 @@ namespace lb_library Image<BYTERGB> prgbBG(m_BGImage); Image<BYTERGB> prgbFG(m_FGImage); - for(int j = 0; j < m_height; j++) + for (int j = 0; j < m_height; j++) { int jj = m_offset + j*(N + m_pad); - for(int i = 0; i < m_width; i++) + for (int i = 0; i < m_width; i++) { int ii = m_offset + i*(M + m_pad); @@ -222,17 +222,17 @@ namespace lb_library int iiHit = ii; int jjHit = jj; - for(int l = 0; l < N; l++) + for (int l = 0; l < N; l++) { - for(int k = 0; k < M; k++) + 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 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) + if (d2 < d2min) { d2min = d2; iiHit = ii + k; @@ -243,28 +243,28 @@ namespace lb_library // Update SOM - if(d2min <= epsilon) // matching model found + if (d2min <= epsilon) // matching model found { - for(int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++) + for (int l = (jjHit - m_offset); l <= (jjHit + m_offset); l++) { - for(int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++) + for (int k = (iiHit - m_offset); k <= (iiHit + m_offset); k++) { - a = alpha*m_ppW[l-jjHit+m_offset][k-iiHit+m_offset]; + 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) + if (d*d > DBL_MIN) m_ppSOM[l][k].Red += a*d; d = srcG - m_ppSOM[l][k].Green; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) m_ppSOM[l][k].Green += a*d; d = srcB - m_ppSOM[l][k].Blue; - if(d*d > DBL_MIN) + if (d*d > DBL_MIN) m_ppSOM[l][k].Blue += a*d; } } @@ -272,7 +272,7 @@ namespace lb_library // 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; + 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; @@ -288,4 +288,4 @@ namespace lb_library return; } } -} \ No newline at end of file +} diff --git a/package_bgs/lb/BGModelSom.h b/package_bgs/lb/BGModelSom.h index dcd715819927d69ef0a3831637dea7f57264ca4e..0975b0b3e38d89a3e2b2e734e9c1d3c5bb4686ab 100644 --- a/package_bgs/lb/BGModelSom.h +++ b/package_bgs/lb/BGModelSom.h @@ -14,7 +14,7 @@ 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 +/* Scene 1.0.1 -- Background subtraction and object tracking for complex environments BGModelSom.h Copyright (C) 2011 Laurence Bender <lbender@untref.edu.ar> @@ -33,9 +33,7 @@ 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 */ - -#ifndef BGMODELSOM_H -#define BGMODELSOM_H +#pragma once #include "BGModel.h" @@ -47,9 +45,9 @@ namespace lb_library const int M = 3; // width SOM (per pixel) const int N = 3; // height SOM (per pixel) - const int KERNEL = 3; // size Gaussian kernel + const int KERNEL = 3; // size Gaussian kernel - const bool SPAN_NEIGHBORS = false; // true if update neighborhood spans different pixels // + 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 @@ -81,12 +79,10 @@ namespace lb_library double m_alpha2; DBLRGB** m_ppSOM; // SOM grid - double** m_ppW; // Weights + double** m_ppW; // Weights void Init(); void Update(); }; } } - -#endif diff --git a/package_bgs/lb/Types.h b/package_bgs/lb/Types.h index cb318a238b7ba97f0c455fbab3b4732f177d1031..bd59c41eaba01dc5f8642a7bf40c365f5c61758f 100644 --- a/package_bgs/lb/Types.h +++ b/package_bgs/lb/Types.h @@ -33,57 +33,55 @@ 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 */ - -#ifndef TYPES_H -#define TYPES_H +#pragma once #include <opencv2/opencv.hpp> namespace lb_library { - template<class T> class Image - { - private: - IplImage* imgp; +template<class T> class Image +{ +private: + IplImage* imgp; - public: - Image(IplImage* img=0) {imgp=img;} - ~Image(){imgp=0;} +public: + Image(IplImage* img=0) {imgp=img;} + ~Image(){imgp=0;} - void operator=(IplImage* img) {imgp=img;} + 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; - - /* + 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++) @@ -93,7 +91,3 @@ namespace lb_library imgA[i][j].r = 111; */ } - -//--------------------------------------------- - -#endif diff --git a/package_bgs/my/MyBGS.cpp b/package_bgs/my/MyBGS.cpp deleted file mode 100644 index 07b51cde46b07c5da9e0ad19951d35aca191f771..0000000000000000000000000000000000000000 --- a/package_bgs/my/MyBGS.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "MyBGS.h" - -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/my/MyBGS.h b/package_bgs/my/MyBGS.h deleted file mode 100644 index fa27484aafd413343913720b7695695e916cd624..0000000000000000000000000000000000000000 --- a/package_bgs/my/MyBGS.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -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(){} -}; \ No newline at end of file diff --git a/package_bgs/pl/BackgroundSubtractorLBSP.cpp b/package_bgs/pl/BackgroundSubtractorLBSP.cpp deleted file mode 100644 index 6752f76fa6cf94194d256c42c02c46ef7a4392b6..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorLBSP.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#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/pl/BackgroundSubtractorLBSP.h b/package_bgs/pl/BackgroundSubtractorLBSP.h deleted file mode 100644 index 5602d349f039da4ebdd4f581d1c2ee4e6e19a9a9..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorLBSP.h +++ /dev/null @@ -1,85 +0,0 @@ -#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 operator()(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/pl/BackgroundSubtractorLOBSTER.cpp b/package_bgs/pl/BackgroundSubtractorLOBSTER.cpp deleted file mode 100644 index 78938ad347805703f1c9a975c886e32b0467eaed..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorLOBSTER.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#include "BackgroundSubtractorLOBSTER.h" -#include "DistanceUtils.h" -#include "RandUtils.h" -#include <iostream> -#include <opencv2/imgproc/imgproc.hpp> -#include <opencv2/highgui/highgui.hpp> -#include <iomanip> - -BackgroundSubtractorLOBSTER::BackgroundSubtractorLOBSTER( float fRelLBSPThreshold - ,size_t nLBSPThresholdOffset - ,size_t nDescDistThreshold - ,size_t nColorDistThreshold - ,size_t nBGSamples - ,size_t nRequiredBGSamples) - : BackgroundSubtractorLBSP(fRelLBSPThreshold,nLBSPThresholdOffset) - ,m_nColorDistThreshold(nColorDistThreshold) - ,m_nDescDistThreshold(nDescDistThreshold) - ,m_nBGSamples(nBGSamples) - ,m_nRequiredBGSamples(nRequiredBGSamples) { - CV_Assert(m_nRequiredBGSamples<=m_nBGSamples); - m_bAutoModelResetEnabled = false; // @@@@@@ not supported here for now -} - -BackgroundSubtractorLOBSTER::~BackgroundSubtractorLOBSTER() { - if(m_aPxIdxLUT) - delete[] m_aPxIdxLUT; - if(m_aPxInfoLUT) - delete[] m_aPxInfoLUT; -} - -void BackgroundSubtractorLOBSTER::initialize(const cv::Mat& oInitImg, const cv::Mat& oROI) { - CV_Assert(!oInitImg.empty() && oInitImg.cols>0 && oInitImg.rows>0); - CV_Assert(oInitImg.isContinuous()); - CV_Assert(oInitImg.type()==CV_8UC1 || oInitImg.type()==CV_8UC3); - 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 << "\tBackgroundSubtractorLOBSTER : 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(); - } - LBSP::validateROI(oNewBGROI); - const size_t nROIPxCount = (size_t)cv::countNonZero(oNewBGROI); - CV_Assert(nROIPxCount>0); - m_oROI = oNewBGROI; - m_oImgSize = oInitImg.size(); - m_nImgType = oInitImg.type(); - m_nImgChannels = oInitImg.channels(); - m_nTotPxCount = m_oImgSize.area(); - m_nTotRelevantPxCount = nROIPxCount; - m_nFrameIndex = 0; - m_nFramesSinceLastReset = 0; - m_nModelResetCooldown = 0; - m_oLastFGMask.create(m_oImgSize,CV_8UC1); - m_oLastFGMask = cv::Scalar_<uchar>(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_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>((t*m_fRelLBSPThreshold+m_nLBSPThresholdOffset)/2); - 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>(t*m_fRelLBSPThreshold+m_nLBSPThresholdOffset); - 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 BackgroundSubtractorLOBSTER::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 BackgroundSubtractorLOBSTER::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate) { - CV_Assert(m_bInitialized); - CV_Assert(learningRate>0); - 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(); - oCurrFGMask = cv::Scalar_<uchar>(0); - const size_t nLearningRate = (size_t)ceil(learningRate); - 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 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 nGoodSamplesCount=0, nModelIdx=0; - ushort nCurrInputDesc; - while(nGoodSamplesCount<m_nRequiredBGSamples && nModelIdx<m_nBGSamples) { - const uchar nBGColor = m_voBGColorSamples[nModelIdx].data[nPxIter]; - { - const size_t nColorDist = L1dist(nCurrColor,nBGColor); - if(nColorDist>m_nColorDistThreshold/2) - goto failedcheck1ch; - LBSP::computeGrayscaleDescriptor(oInputImg,nBGColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nBGColor],nCurrInputDesc); - const size_t nDescDist = hdist(nCurrInputDesc,*((ushort*)(m_voBGDescSamples[nModelIdx].data+nDescIter))); - if(nDescDist>m_nDescDistThreshold) - goto failedcheck1ch; - nGoodSamplesCount++; - } - failedcheck1ch: - nModelIdx++; - } - if(nGoodSamplesCount<m_nRequiredBGSamples) - oCurrFGMask.data[nPxIter] = UCHAR_MAX; - else { - if((rand()%nLearningRate)==0) { - const size_t nSampleModelIdx = rand()%m_nBGSamples; - ushort& nRandInputDesc = *((ushort*)(m_voBGDescSamples[nSampleModelIdx].data+nDescIter)); - LBSP::computeGrayscaleDescriptor(oInputImg,nCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nCurrColor],nRandInputDesc); - m_voBGColorSamples[nSampleModelIdx].data[nPxIter] = nCurrColor; - } - if((rand()%nLearningRate)==0) { - int nSampleImgCoord_Y, nSampleImgCoord_X; - getRandNeighborPosition_3x3(nSampleImgCoord_X,nSampleImgCoord_Y,nCurrImgCoord_X,nCurrImgCoord_Y,LBSP::PATCH_SIZE/2,m_oImgSize); - const size_t nSampleModelIdx = rand()%m_nBGSamples; - ushort& nRandInputDesc = m_voBGDescSamples[nSampleModelIdx].at<ushort>(nSampleImgCoord_Y,nSampleImgCoord_X); - LBSP::computeGrayscaleDescriptor(oInputImg,nCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nCurrColor],nRandInputDesc); - m_voBGColorSamples[nSampleModelIdx].at<uchar>(nSampleImgCoord_Y,nSampleImgCoord_X) = nCurrColor; - } - } - } - } - else { //m_nImgChannels==3 - const size_t nCurrDescDistThreshold = m_nDescDistThreshold*3; - const size_t nCurrColorDistThreshold = m_nColorDistThreshold*3; - const size_t nCurrSCDescDistThreshold = nCurrDescDistThreshold/2; - const size_t nCurrSCColorDistThreshold = nCurrColorDistThreshold/2; - const size_t desc_row_step = m_voBGDescSamples[0].step.p[0]; - const size_t img_row_step = m_voBGColorSamples[0].step.p[0]; - 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 uchar* const anCurrColor = oInputImg.data+nPxIterRGB; - size_t nGoodSamplesCount=0, nModelIdx=0; - ushort anCurrInputDesc[3]; - while(nGoodSamplesCount<m_nRequiredBGSamples && nModelIdx<m_nBGSamples) { - const ushort* const anBGDesc = (ushort*)(m_voBGDescSamples[nModelIdx].data+nDescIterRGB); - const uchar* const anBGColor = m_voBGColorSamples[nModelIdx].data+nPxIterRGB; - size_t nTotColorDist = 0; - size_t nTotDescDist = 0; - for(size_t c=0;c<3; ++c) { - const size_t nColorDist = L1dist(anCurrColor[c],anBGColor[c]); - if(nColorDist>nCurrSCColorDistThreshold) - goto failedcheck3ch; - LBSP::computeSingleRGBDescriptor(oInputImg,anBGColor[c],nCurrImgCoord_X,nCurrImgCoord_Y,c,m_anLBSPThreshold_8bitLUT[anBGColor[c]],anCurrInputDesc[c]); - const size_t nDescDist = hdist(anCurrInputDesc[c],anBGDesc[c]); - if(nDescDist>nCurrSCDescDistThreshold) - goto failedcheck3ch; - nTotColorDist += nColorDist; - nTotDescDist += nDescDist; - } - if(nTotDescDist<=nCurrDescDistThreshold && nTotColorDist<=nCurrColorDistThreshold) - nGoodSamplesCount++; - failedcheck3ch: - nModelIdx++; - } - if(nGoodSamplesCount<m_nRequiredBGSamples) - oCurrFGMask.data[nPxIter] = UCHAR_MAX; - else { - if((rand()%nLearningRate)==0) { - const size_t nSampleModelIdx = rand()%m_nBGSamples; - ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data+nDescIterRGB)); - 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,anRandInputDesc); - for(size_t c=0; c<3; ++c) - *(m_voBGColorSamples[nSampleModelIdx].data+nPxIterRGB+c) = anCurrColor[c]; - } - if((rand()%nLearningRate)==0) { - int nSampleImgCoord_Y, nSampleImgCoord_X; - getRandNeighborPosition_3x3(nSampleImgCoord_X,nSampleImgCoord_Y,nCurrImgCoord_X,nCurrImgCoord_Y,LBSP::PATCH_SIZE/2,m_oImgSize); - const size_t nSampleModelIdx = rand()%m_nBGSamples; - ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data + desc_row_step*nSampleImgCoord_Y + 6*nSampleImgCoord_X)); - 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,anRandInputDesc); - for(size_t c=0; c<3; ++c) - *(m_voBGColorSamples[nSampleModelIdx].data + img_row_step*nSampleImgCoord_Y + 3*nSampleImgCoord_X + c) = anCurrColor[c]; - } - } - } - } - cv::medianBlur(oCurrFGMask,m_oLastFGMask,m_nDefaultMedianBlurKernelSize); - m_oLastFGMask.copyTo(oCurrFGMask); -} - -void BackgroundSubtractorLOBSTER::getBackgroundImage(cv::OutputArray backgroundImage) const { - CV_DbgAssert(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 idx_flt32 = idx_nimg*4; - float* oAvgBgImgPtr = (float*)(oAvgBGImg.data+idx_flt32); - 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 BackgroundSubtractorLOBSTER::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 idx_flt32 = idx_ndesc*2; - float* oAvgBgDescPtr = (float*)(oAvgBGDesc.data+idx_flt32); - 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/pl/BackgroundSubtractorLOBSTER.h b/package_bgs/pl/BackgroundSubtractorLOBSTER.h deleted file mode 100644 index bedc55d1cedccba3a2993f40de48ac056b67a8d3..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorLOBSTER.h +++ /dev/null @@ -1,67 +0,0 @@ -#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 operator()(cv::InputArray image, cv::OutputArray fgmask, double learningRate=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/pl/BackgroundSubtractorSuBSENSE.cpp b/package_bgs/pl/BackgroundSubtractorSuBSENSE.cpp deleted file mode 100644 index c7d5daca785550f6290f59e19e3427892908520c..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorSuBSENSE.cpp +++ /dev/null @@ -1,737 +0,0 @@ -#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::operator()(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/pl/BackgroundSubtractorSuBSENSE.h b/package_bgs/pl/BackgroundSubtractorSuBSENSE.h deleted file mode 100644 index f8424ad1761219c8f833e598d6b2cf1e0051c57f..0000000000000000000000000000000000000000 --- a/package_bgs/pl/BackgroundSubtractorSuBSENSE.h +++ /dev/null @@ -1,113 +0,0 @@ -#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 operator()(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/pl/DistanceUtils.h b/package_bgs/pl/DistanceUtils.h deleted file mode 100644 index 54d1cecd933b45a036c8222bed594d0b2305ef89..0000000000000000000000000000000000000000 --- a/package_bgs/pl/DistanceUtils.h +++ /dev/null @@ -1,316 +0,0 @@ -#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/pl/LBSP.cpp b/package_bgs/pl/LBSP.cpp deleted file mode 100644 index de35f1a09bd8b4d0b762b390475c111916e0be11..0000000000000000000000000000000000000000 --- a/package_bgs/pl/LBSP.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#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/pl/LBSP.h b/package_bgs/pl/LBSP.h deleted file mode 100644 index 1ca17a0125baae1a18e00b0d31fa673c1c34a903..0000000000000000000000000000000000000000 --- a/package_bgs/pl/LBSP.h +++ /dev/null @@ -1,118 +0,0 @@ -#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/pl/LOBSTER.cpp b/package_bgs/pl/LOBSTER.cpp deleted file mode 100644 index f4e9bf62a7433f693f2309c712da197c7fd614b4..0000000000000000000000000000000000000000 --- a/package_bgs/pl/LOBSTER.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "LOBSTER.h" -#include "BackgroundSubtractorLOBSTER.h" - - -LOBSTERBGS::LOBSTERBGS() : -pLOBSTER(0), firstTime(true), showOutput(true), -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) -{ -} - -LOBSTERBGS::~LOBSTERBGS() { - if (pLOBSTER) - delete pLOBSTER; -} - -void LOBSTERBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) -{ - if(img_input.empty()) - return; - - loadConfig(); - - if (firstTime) { - saveConfig(); - 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)(img_input, img_output); - pLOBSTER->getBackgroundImage(img_bgmodel); - - if(showOutput) { - imshow("LOBSTER FG", img_output); - imshow("LOBSTER BG", img_bgmodel); - } -} - -void LOBSTERBGS::saveConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/LOBSTERBGS.xml", 0, 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 LOBSTERBGS::loadConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/LOBSTERBGS.xml", 0, CV_STORAGE_READ); - - fRelLBSPThreshold = cvReadRealByName(fs, 0, "fRelLBSPThreshold", BGSLOBSTER_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD); - nLBSPThresholdOffset = cvReadIntByName(fs, 0, "nLBSPThresholdOffset", BGSLOBSTER_DEFAULT_LBSP_OFFSET_SIMILARITY_THRESHOLD); - nDescDistThreshold = cvReadIntByName(fs, 0, "nDescDistThreshold", BGSLOBSTER_DEFAULT_DESC_DIST_THRESHOLD); - nColorDistThreshold = cvReadIntByName(fs, 0, "nColorDistThreshold", BGSLOBSTER_DEFAULT_COLOR_DIST_THRESHOLD); - nBGSamples = cvReadIntByName(fs, 0, "nBGSamples", BGSLOBSTER_DEFAULT_NB_BG_SAMPLES); - nRequiredBGSamples = cvReadIntByName(fs, 0, "nRequiredBGSamples", BGSLOBSTER_DEFAULT_REQUIRED_NB_BG_SAMPLES); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - cvReleaseFileStorage(&fs); -} diff --git a/package_bgs/pl/LOBSTER.h b/package_bgs/pl/LOBSTER.h deleted file mode 100644 index f5954ca2ebe814d176f47936e790668959e6089c..0000000000000000000000000000000000000000 --- a/package_bgs/pl/LOBSTER.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -class BackgroundSubtractorLOBSTER; - -class LOBSTERBGS : public IBGS -{ -private: - BackgroundSubtractorLOBSTER* pLOBSTER; - bool firstTime; - bool showOutput; - - float fRelLBSPThreshold; - size_t nLBSPThresholdOffset; - size_t nDescDistThreshold; - size_t nColorDistThreshold; - size_t nBGSamples; - size_t nRequiredBGSamples; - -public: - LOBSTERBGS(); - ~LOBSTERBGS(); - - 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/pl/RandUtils.h b/package_bgs/pl/RandUtils.h deleted file mode 100644 index 24ca5f683d86970c89d4822efdcae1ffce1ca4ae..0000000000000000000000000000000000000000 --- a/package_bgs/pl/RandUtils.h +++ /dev/null @@ -1,96 +0,0 @@ -#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/pl/SuBSENSE.cpp b/package_bgs/pl/SuBSENSE.cpp deleted file mode 100644 index a4aab0c1c5a3423ddfc793fd6577e0a4d49b07f2..0000000000000000000000000000000000000000 --- a/package_bgs/pl/SuBSENSE.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "SuBSENSE.h" -#include "BackgroundSubtractorSuBSENSE.h" - - -SuBSENSEBGS::SuBSENSEBGS() : -pSubsense(0), firstTime(true), showOutput(true), -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) -{ -} - -SuBSENSEBGS::~SuBSENSEBGS() { - if (pSubsense) - delete pSubsense; -} - -void SuBSENSEBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) -{ - if(img_input.empty()) - return; - - loadConfig(); - - if (firstTime) { - saveConfig(); - 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)(img_input, img_output); - pSubsense->getBackgroundImage(img_bgmodel); - - if(showOutput) { - imshow("SuBSENSE FG", img_output); - imshow("SuBSENSE BG", img_bgmodel); - } -} - -void SuBSENSEBGS::saveConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/SuBSENSEBGS.xml", 0, 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 SuBSENSEBGS::loadConfig() -{ - CvFileStorage* fs = cvOpenFileStorage("./config/SuBSENSEBGS.xml", 0, CV_STORAGE_READ); - - fRelLBSPThreshold = cvReadRealByName(fs, 0, "fRelLBSPThreshold", BGSSUBSENSE_DEFAULT_LBSP_REL_SIMILARITY_THRESHOLD); - nDescDistThresholdOffset = cvReadIntByName(fs, 0, "nDescDistThresholdOffset", BGSSUBSENSE_DEFAULT_DESC_DIST_THRESHOLD_OFFSET); - nMinColorDistThreshold = cvReadIntByName(fs, 0, "nMinColorDistThreshold", BGSSUBSENSE_DEFAULT_MIN_COLOR_DIST_THRESHOLD); - nBGSamples = cvReadIntByName(fs, 0, "nBGSamples", BGSSUBSENSE_DEFAULT_NB_BG_SAMPLES); - nRequiredBGSamples = cvReadIntByName(fs, 0, "nRequiredBGSamples", BGSSUBSENSE_DEFAULT_REQUIRED_NB_BG_SAMPLES); - nSamplesForMovingAvgs = cvReadIntByName(fs, 0, "nSamplesForMovingAvgs", BGSSUBSENSE_DEFAULT_N_SAMPLES_FOR_MV_AVGS); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); - - cvReleaseFileStorage(&fs); -} diff --git a/package_bgs/pl/SuBSENSE.h b/package_bgs/pl/SuBSENSE.h deleted file mode 100644 index b527c2711682814d0cac39681e6b841008c1195f..0000000000000000000000000000000000000000 --- a/package_bgs/pl/SuBSENSE.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include <opencv2/opencv.hpp> - -#include "../IBGS.h" - -class BackgroundSubtractorSuBSENSE; - -class SuBSENSEBGS: public IBGS { -private: - BackgroundSubtractorSuBSENSE* pSubsense; - bool firstTime; - bool showOutput; - - float fRelLBSPThreshold; - size_t nDescDistThresholdOffset; - size_t nMinColorDistThreshold; - size_t nBGSamples; - size_t nRequiredBGSamples; - size_t nSamplesForMovingAvgs; - -public: - SuBSENSEBGS(); - ~SuBSENSEBGS(); - - 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/sjn/SJN_MultiCueBGS.h b/package_bgs/sjn/SJN_MultiCueBGS.h deleted file mode 100644 index 0891c08c16d9d319a6f12290df3d5dd2d7884a29..0000000000000000000000000000000000000000 --- a/package_bgs/sjn/SJN_MultiCueBGS.h +++ /dev/null @@ -1,248 +0,0 @@ -/* -This file is part of BGSLibrary. - -BGSLibrary is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -BGSLibrary is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. -*/ -#pragma once - -#define 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 - -#if !defined(__APPLE__) -#include <malloc.h> -#endif -#include "math.h" - -#include <vector> -using std::vector; - -#include <algorithm> -using std::sort; - -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -//------------------------------------Structure Lists-------------------------------------// -struct point{ - short m_nX; - short m_nY; -}; - -struct neighbor_pos{ - short m_nX; - short m_nY; -}; -//1) Bounding Box Structure -struct BoundingBoxInfo{ - int m_iBoundBoxNum; //# of bounding boxes for all foreground and false-positive blobs - int m_iArraySize; //the size of the below arrays to store bounding box information - - short *m_aLeft, *m_aRight, *m_aUpper, *m_aBottom; //arrays to store bounding box information for (the original frame size) - short *m_aRLeft, *m_aRRight, *m_aRUpper, *m_aRBottom; //arrays to store bounding box information for (the reduced frame size) - BOOL* m_ValidBox; //If this value is true, the corresponding bounding box is for a foreground blob. - //Else, it is for a false-positive blob -}; - -//2) Texture Model Structure -struct TextureCodeword{ - int m_iMNRL; //the maximum negative run-length - int m_iT_first_time; //the first access time - int m_iT_last_time; //the last access time - - //��� MTLBP�� - float m_fLowThre; //a low threshold for the matching - float m_fHighThre; //a high threshold for the matching - float m_fMean; //mean of the codeword -}; - -struct TextureModel{ - TextureCodeword** m_Codewords; //the texture-codeword Array - - int m_iTotal; //# of learned samples after the last clear process - int m_iElementArraySize; //the array size of m_Codewords - int m_iNumEntries; //# of codewords - - BOOL m_bID; //id=1 --> background model, id=0 --> cachebook -}; - -//3) Color Model Structure -struct ColorCodeword{ - int m_iMNRL; //the maximum negative run-length - int m_iT_first_time; //the first access time - int m_iT_last_time; //the last access time - - double m_dMean[3]; //mean vector of the codeword - -}; - -struct ColorModel{ - ColorCodeword** m_Codewords; //the color-codeword Array - - int m_iTotal; //# of learned samples after the last clear process - int m_iElementArraySize; //the array size of m_Codewords - int m_iNumEntries; //# of codewords - - BOOL m_bID; //id=1 --> background model, id=0 --> cachebookk -}; - - -class SJN_MultiCueBGS : public IBGS -{ -private: - bool firstTime; - bool showOutput; - void saveConfig(); - void loadConfig(); - -public: - SJN_MultiCueBGS(); - ~SJN_MultiCueBGS(void); - -public: - //---------------------------------------------------- - // APIs and User-Adjustable Parameters - //---------------------------------------------------- - void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); //the main function to background modeling and subtraction - - void GetForegroundMap(IplImage* return_image, IplImage* input_frame=NULL); //the function returning a foreground binary-map - void Destroy(); //the function to release allocated memories - - int g_iTrainingPeriod; //the training period (The parameter t in the paper) - int g_iT_ModelThreshold; //the threshold for texture-model based BGS. (The parameter tau_T in the paper) - int g_iC_ModelThreshold; //the threshold for appearance based verification. (The parameter tau_A in the paper) - - float g_fLearningRate; //the learning rate for background models. (The parameter alpha in the paper) - - 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 - //---------------------------------------------------- - - //--1) General Functions - void Initialize(IplImage* frame); - - void PreProcessing(IplImage* frame); - void ReduceImageSize(IplImage* SrcImage, IplImage* DstImage); - void GaussianFiltering(IplImage* frame, uchar*** aFilteredFrame); - void BGR2HSVxyz_Par(uchar*** aBGR, uchar*** aXYZ); - - void BackgroundModeling_Par(IplImage* frame); - void ForegroundExtraction(IplImage* frame); - void CreateLandmarkArray_Par(float fConfThre, short nTrainVolRange, float**aConfMap, int iNehborNum, uchar*** aXYZ, - point*** aNeiDir, TextureModel**** TModel, ColorModel*** CModel, uchar**aLandmarkArr); - - void PostProcessing(IplImage* frame); - void MorphologicalOpearions(uchar** aInput, uchar** aOutput, double dThresholdRatio, int iMaskSize, int iWidth, int iHeight); - void Labeling(uchar** aBinaryArray, int* pLabelCount, int** aLabelTable); - void SetBoundingBox(int iLabelCount, int** aLabelTable); - void BoundBoxVerification(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); - void EvaluateBoxSize( BoundingBoxInfo* BoundBoxInfo); - void EvaluateOverlapRegionSize(BoundingBoxInfo* SrcBoxInfo); - void EvaluateGhostRegion(IplImage* frame, uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); - double CalculateHausdorffDist(IplImage* input_image, IplImage* model_image); - void RemovingInvalidForeRegions(uchar** aResForeMap, BoundingBoxInfo* BoundBoxInfo); - - void UpdateModel_Par(); - void GetEnlargedMap(float** aOriginMap, float** aEnlargedMap); - - //--2) Texture Model Related Functions - void T_AllocateTextureModelRelatedMemory(); - void T_ReleaseTextureModelRelatedMemory(); - void T_SetNeighborDirection(point*** aNeighborPos); - void T_ModelConstruction(short nTrainVolRange,float fLearningRate, uchar*** aXYZ,point center, point* aNei, TextureModel** aModel); - void T_ClearNonEssentialEntries(short nClearNum, TextureModel** aModel); - void T_ClearNonEssentialEntriesForCachebook(uchar bLandmark, short* nReferredIdxArr, short nClearNum, TextureModel** pCachebook); - void T_GetConfidenceMap_Par(uchar*** aXYZ, float** aTextureMap, point*** aNeiDirArr, TextureModel**** aModel); - void T_Absorption(int iAbsorbCnt, point pos, short*** aContinuCnt, short*** aRefferedIndex, TextureModel** pModel, TextureModel** pCache); - - //--3) Color Model Related Functions - void C_AllocateColorModelRelatedMemory(); - void C_ReleaseColorModelRelatedMemory(); - void C_CodebookConstruction(uchar* aP,int iPosX, int iPosY, short nTrainVolRange, float fLearningRate, ColorModel* pC); - 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 - //---------------------------------------------------- - - //--1) General Variables - int g_iFrameCount; //the counter of processed frames - - int g_iBackClearPeriod; //the period to clear background models - int g_iCacheClearPeriod; //the period to clear cache-book models - - int g_iAbsortionPeriod; //the period to absorb static ghost regions - BOOL g_bAbsorptionEnable; //If True, procedures for ghost region absorption are activated. - - BOOL g_bModelMemAllocated; //To handle memory.. - BOOL g_bNonModelMemAllocated; //To handle memory.. - - float g_fConfidenceThre; //the final decision threshold - - int g_iWidth, g_iHeight; //width and height of input frames - int g_iRWidth, g_iRHeight; //width and height of reduced frames (For efficiency, the reduced size of frames are processed) - int g_iForegroundNum; //# of detected foreground regions - BOOL g_bForegroundMapEnable; //TRUE only when BGS is successful - - IplImage* g_ResizedFrame; //reduced size of frame (For efficiency, the reduced size of frames are processed) - uchar*** g_aGaussFilteredFrame; - uchar*** g_aXYZFrame; - uchar** g_aLandmarkArray; //the landmark map - uchar** g_aResizedForeMap; //the resized foreground map - uchar** g_aForegroundMap; //the final foreground map - BOOL** g_aUpdateMap; //the location map of update candidate pixels - - BoundingBoxInfo* g_BoundBoxInfo; //the array of bounding boxes of each foreground blob - - //--2) Texture Model Related - TextureModel**** g_TextureModel; //the texture background model - TextureModel**** g_TCacheBook; //the texture cache-book - short*** g_aTReferredIndex; //To handle cache-book - short*** g_aTContinuousCnt; //To handle cache-book - point*** g_aNeighborDirection; - float**g_aTextureConfMap; //the texture confidence map - - short g_nNeighborNum; //# of neighborhoods - short g_nRadius; - short g_nBoundarySize; - - //--3) Texture Model Related - ColorModel*** g_ColorModel; //the color background model - ColorModel*** g_CCacheBook; //the color cache-book - short** g_aCReferredIndex; //To handle cache-book - short** g_aCContinuousCnt; //To handle cache-book -}; - - diff --git a/package_bgs/tb/FuzzyChoquetIntegral.h b/package_bgs/tb/FuzzyChoquetIntegral.h deleted file mode 100644 index 76ba15829bf493a19f75e5f7a77e87e3ca5dcdf7..0000000000000000000000000000000000000000 --- a/package_bgs/tb/FuzzyChoquetIntegral.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -#include "FuzzyUtils.h" - -class FuzzyChoquetIntegral : public IBGS -{ -private: - bool firstTime; - long frameNumber; - bool showOutput; - - 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/tb/FuzzySugenoIntegral.h b/package_bgs/tb/FuzzySugenoIntegral.h deleted file mode 100644 index cfa91b7bb07dd4eeb2feba10a0f7832ef590a6d1..0000000000000000000000000000000000000000 --- a/package_bgs/tb/FuzzySugenoIntegral.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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" - -#include "FuzzyUtils.h" - -class FuzzySugenoIntegral : public IBGS -{ -private: - bool firstTime; - long long frameNumber; - bool showOutput; - - 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/tb/FuzzyUtils.cpp b/package_bgs/tb/FuzzyUtils.cpp deleted file mode 100644 index fcb1972b3d21438c92333762b522c49a7e043800..0000000000000000000000000000000000000000 --- a/package_bgs/tb/FuzzyUtils.cpp +++ /dev/null @@ -1,512 +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 "FuzzyUtils.h" - -FuzzyUtils::FuzzyUtils(void){} - -FuzzyUtils::~FuzzyUtils(void){} - -void FuzzyUtils::LBP(IplImage* InputImage, IplImage* LBPimage) -{ - PixelUtils p; - - float* neighberPixel = (float*) malloc(9*sizeof(float)); - float* BinaryValue = (float*) malloc(9*sizeof(float)); - float* CarreExp = (float*) malloc(9*sizeof(float)); - float* valLBP = (float*) malloc(1*sizeof(float)); - - *valLBP = 0; - - int x = 0, y = 0; - - // on implemente les 8 valeurs puissance de 2 qui correspondent aux 8 elem. d'image voisins au elem. d'image central - *(CarreExp+0)=1.0; - *(CarreExp+1)=2.0; - *(CarreExp+2)=4.0; - *(CarreExp+3)=8.0; - *(CarreExp+4)=0.0; - *(CarreExp+5)=16.0; - *(CarreExp+6)=32.0; - *(CarreExp+7)=64.0; - *(CarreExp+8)=128.0; - - //le calcule de LBP - //pour les 4 coins - /* 1.*/ - if(x==0 && y==0) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,4,0); - *valLBP=*valLBP+((*(BinaryValue+1))*(*(CarreExp+1))+(*(BinaryValue+2))*(*(CarreExp+2))+(*(BinaryValue+3))*(*(CarreExp+3)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - - /* 2.*/ - if(x==0 && y==InputImage->width) - { - *valLBP=0; - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,4,1); - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+2))*(*(CarreExp+2))+(*(BinaryValue+3))*(*(CarreExp+3)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - - /* 3.*/ - if(x==InputImage->height && y==0) - { - *valLBP=0; - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,4,2); - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+1))*(*(CarreExp+1))+(*(BinaryValue+3))*(*(CarreExp+3)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - - /* 4.*/ - if(x==InputImage->height && y==InputImage->width) - { - *valLBP=0; - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,4,3); - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+1))*(*(CarreExp+1))+(*(BinaryValue+2))*(*(CarreExp+2)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - - //le calcul de LBP pour la premi�re ligne : L(0) - if(x==0 && (y!=0 && y!=InputImage->width)) - { - for(int y = 1; y < InputImage->width-1; y++) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,6,4); - *valLBP=0; - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+1))*(*(CarreExp+1))+(*(BinaryValue+2))*(*(CarreExp+2))+(*(BinaryValue+3))*(*(CarreExp+3))+(*(BinaryValue+5))*(*(CarreExp+5)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - } - - //le calcul de LBP pour la derni�re colonne : C(w) - if((x!=0 && x!=InputImage->height) && y==InputImage->width) - { - for(int x = 1; x < InputImage->height-1; x++) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,6,4); - *valLBP=0; - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+1))*(*(CarreExp+1))+(*(BinaryValue+2))*(*(CarreExp+2))+(*(BinaryValue+3))*(*(CarreExp+3))+(*(BinaryValue+5))*(*(CarreExp+5)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - } - - //le calcul de LBP pour la derni�re ligne : L(h) - if(x==InputImage->height && (y!=0 && y!=InputImage->width)) - { - for(int y = 1; y < InputImage->width-1; y++) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,6,1); - *valLBP=0; - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp))+(*(BinaryValue+2))*(*(CarreExp+2))+(*(BinaryValue+3))*(*(CarreExp+3))+(*(BinaryValue+4))*(*(CarreExp+4))+(*(BinaryValue+5))*(*(CarreExp+5)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - } - - //le calcul de LBP pour la premi�re colonne : C(0) - if((x!=0 && x!=InputImage->height) && y==0) - { - for(int x = 1; x <InputImage->height-1; x++) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,6,2); - *valLBP=0; - *valLBP=*valLBP+((*(BinaryValue))*(*(CarreExp+5))+(*(BinaryValue+1))*(*(CarreExp+6))+(*(BinaryValue+3))*(*(CarreExp+3))+(*(BinaryValue+4))*(*(CarreExp))+(*(BinaryValue+5))*(*(CarreExp+1)))/255.0; - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - } - - //pour le reste des elements d'image - for(int y = 1; y < InputImage->height-1; y++) - { - for(int x = 1; x < InputImage->width-1; x++) - { - p.getNeighberhoodGrayPixel(InputImage, x,y,neighberPixel); - getBinValue(neighberPixel,BinaryValue,9,4); - //le calcul de la valeur du LBP pour chaque elem. d'im. - *valLBP=0; - for(int l = 0; l < 9; l++) - *valLBP = *valLBP + ((*(BinaryValue+l)) * (*(CarreExp+l))) / 255.0; - //printf("\nvalLBP(%d,%d)=%f",x,y,*valLBP); - p.PutGrayPixel(LBPimage,x,y,*valLBP); - } - } - - free(neighberPixel); - free(BinaryValue); - free(CarreExp); - free(valLBP); -} - -void FuzzyUtils::getBinValue(float* neighberGrayPixel, float* BinaryValue, int m, int n) -{ - // la comparaison entre la valeur d'elem d'image central et les valeurs des elem. d'im. voisins - // m = le numero des elements (4, 6 ou 9); - // n = la position de l'element central; - - int h = 0; - for(int k = 0; k < m; k++) - { - if(*(neighberGrayPixel+k) >= *(neighberGrayPixel+n)) - { - *(BinaryValue+h)=1; - h++; - } - else - { - *(BinaryValue+h)=0; - h++; - } - } -} - -void FuzzyUtils::SimilarityDegreesImage(IplImage* CurrentImage, IplImage* BGImage, IplImage* DeltaImage, int n, int color_space) -{ - PixelUtils p; - int i, j; - - if(n == 1) - { - float* CurrentGrayPixel = (float*) malloc (1*(sizeof(float))); - float* BGGrayPixel = (float*) malloc (1*(sizeof(float))); - float* DeltaGrayPixel = (float*) malloc (1*(sizeof(float))); - - for(i = 0; i < CurrentImage->width; i++) - { - for(j = 0; j < CurrentImage->height; j++) - { - p.GetGrayPixel(CurrentImage,i,j,CurrentGrayPixel); - p.GetGrayPixel(BGImage,i,j,BGGrayPixel); - RatioPixels(CurrentGrayPixel,BGGrayPixel,DeltaGrayPixel,1); - p.PutGrayPixel(DeltaImage,i,j,*DeltaGrayPixel); - } - } - - free(CurrentGrayPixel); - free(BGGrayPixel); - free(DeltaGrayPixel); - } - - if(n != 1) - { - IplImage* ConvertedCurrentImage = cvCreateImage(cvSize(CurrentImage->width, CurrentImage->height), IPL_DEPTH_32F, 3); - IplImage* ConvertedBGImage = cvCreateImage(cvSize(CurrentImage->width, CurrentImage->height), IPL_DEPTH_32F, 3); - - float* ConvertedCurrentPixel = (float*) malloc(3*(sizeof(float))); - float* ConvertedBGPixel = (float*) malloc(3*(sizeof(float))); - float* DeltaConvertedPixel = (float*) malloc(3*(sizeof(float))); - - p.ColorConversion(CurrentImage,ConvertedCurrentImage,color_space); - p.ColorConversion(BGImage,ConvertedBGImage,color_space); - - for(i = 0; i < CurrentImage->width; i++) - { - for(j = 0; j < CurrentImage->height; j++) - { - p.GetPixel(ConvertedCurrentImage,i,j,ConvertedCurrentPixel); - p.GetPixel(ConvertedBGImage,i,j,ConvertedBGPixel); - RatioPixels(ConvertedCurrentPixel,ConvertedBGPixel,DeltaConvertedPixel,3); - p.PutPixel(DeltaImage,i,j,DeltaConvertedPixel); - } - } - - free(ConvertedCurrentPixel); - free(ConvertedBGPixel); - free(DeltaConvertedPixel); - - cvReleaseImage(&ConvertedCurrentImage); - cvReleaseImage(&ConvertedBGImage); - } -} - -void FuzzyUtils::RatioPixels(float* CurrentPixel, float* BGPixel, float* DeltaPixel, int n) -{ - if(n == 1) - { - if(*CurrentPixel < *BGPixel) - *DeltaPixel = *CurrentPixel / *BGPixel; - - if(*CurrentPixel > *BGPixel) - *DeltaPixel = *BGPixel / *CurrentPixel; - - if(*CurrentPixel == *BGPixel) - *DeltaPixel = 1.0; - } - - if(n == 3) - for(int i = 0; i < 3; i++) - { - if(*(CurrentPixel+i) < *(BGPixel+i)) - *(DeltaPixel+i) = *(CurrentPixel+i) / *(BGPixel+i); - - if(*(CurrentPixel+i) > *(BGPixel+i)) - *(DeltaPixel+i) = *(BGPixel+i) / *(CurrentPixel+i); - - if(*(CurrentPixel+i) == *(BGPixel+i)) - *(DeltaPixel+i) = 1.0; - } -} - -void FuzzyUtils::getFuzzyIntegralSugeno(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage) -{ - // MeasureG : est un vecteur contenant 3 mesure g (g1,g2,g3) tel que : g1+g2+g3=1 - // n : =2 cad aggreger les 2 images "H" et "Delta" - // =1 cad aggreger uniquement les valeurs des composantes couleurs de l'image "Delta" - - PixelUtils p; - - float* HTexturePixel = (float*) malloc(1*sizeof(float)); - float* DeltaOhtaPixel = (float*) malloc(3*(sizeof(float))); - int *Indice = (int*) malloc(3*(sizeof(int))); - float *HI = (float*) malloc(3*(sizeof(float))); - float *Integral = (float*) malloc(3*(sizeof(float))); - float* X = (float*) malloc(1*sizeof(float)); - float* XiXj = (float*) malloc(1*sizeof(float)); - float IntegralFlou; - - *Indice = 0; - *(Indice+1) = 1; - *(Indice+2) = 2; - *X = 1.0; - - for(int i = 0; i < H->width; i++) - { - for(int j = 0; j < H->height; j++) - { - p.GetGrayPixel(H,i,j,HTexturePixel); - p.GetPixel(Delta,i,j,DeltaOhtaPixel); - - *(HI+0) = *(HTexturePixel+0); - *(HI+1) = *(DeltaOhtaPixel+0); - *(HI+2) = *(DeltaOhtaPixel+1); - - Trier(HI,3,Indice); - - *XiXj = *(MeasureG + (*(Indice+1))) + (*(MeasureG + (*(Indice+2)))); - - *(Integral+0) = min((HI + (*(Indice+0))), X); - *(Integral+1) = min((HI + (*(Indice+1))), XiXj); - *(Integral+2) = min((HI + (*(Indice+2))), ((MeasureG+(*(Indice+2))))); - - IntegralFlou = max(Integral,3); - p.PutGrayPixel(OutputImage,i,j,IntegralFlou); - } - } - - free(HTexturePixel); - free(DeltaOhtaPixel); - free(Indice); - free(HI); - free(X); - free(XiXj); - free(Integral); -} - -void FuzzyUtils::getFuzzyIntegralChoquet(IplImage* H, IplImage* Delta, int n, float *MeasureG, IplImage* OutputImage) -{ - // MeasureG : est un vecteur contenant 3 mesure g (g1,g2,g3) tel que : g1+g2+g3=1 - // n : =2 cad aggreger les 2 images "H" et "Delta" - // =1 cad aggreger uniquement les valeurs des composantes couleurs de l'image "Delta" - - PixelUtils p; - - float* HTexturePixel = (float*) malloc(1*sizeof(float)); - float* DeltaOhtaPixel = (float*) malloc(3*(sizeof(float))); - int *Indice = (int*) malloc(3*(sizeof(int))); - float *HI = (float*) malloc(3*(sizeof(float))); - float *Integral = (float*) malloc(3*(sizeof(float))); - float* X = (float*) malloc(1*sizeof(float)); - float* XiXj = (float*) malloc(1*sizeof(float)); - float IntegralFlou; - - *Indice = 0; - *(Indice+1) = 1; - *(Indice+2) = 2; - *X = 1.0; - - for(int i = 0; i < Delta->width; i++) - { - for(int j = 0; j < Delta->height; j++) - { - if(n == 2) - { - p.GetGrayPixel(H,i,j,HTexturePixel); - p.GetPixel(Delta,i,j,DeltaOhtaPixel); - - *(HI+0) = *(HTexturePixel+0); - *(HI+1) = *(DeltaOhtaPixel+0); - *(HI+2) = *(DeltaOhtaPixel+1); - } - - if(n==1) - { - //remplir HI par les valeurs des 3 composantes couleurs uniquement - p.GetPixel(Delta,i,j,DeltaOhtaPixel); - - *(HI+0) = *(DeltaOhtaPixel+0); - //*(HI+0) = *(DeltaOhtaPixel+2); - *(HI+1) = *(DeltaOhtaPixel+1); - *(HI+2) = *(DeltaOhtaPixel+2); - } - - Trier(HI,3,Indice); - *XiXj = *(MeasureG + (*(Indice+1))) + (*(MeasureG + (*(Indice+2)))); - - *(Integral+0) = *(HI+(*(Indice+0)))* (*X-*XiXj); - *(Integral+1) = *(HI+(*(Indice+1)))* (*XiXj-*(MeasureG+(*(Indice+2)))); - *(Integral+2) = *(HI+(*(Indice+2)))* (*(MeasureG+(*(Indice+2)))); - - IntegralFlou = *(Integral+0) + *(Integral+1) + *(Integral+2); - p.PutGrayPixel(OutputImage,i,j,IntegralFlou); - } - } - - free(HTexturePixel); - free(DeltaOhtaPixel); - free(Indice); - free(HI); - free(X); - free(XiXj); - free(Integral); -} - -void FuzzyUtils::FuzzyMeasureG(float g1, float g2, float g3, float *G) -{ - *(G+0) = g1; - *(G+1) = g2; - *(G+2) = g3; -} - -void FuzzyUtils::Trier(float* g,int n,int* index) -{ - // Cette fonction trie un vecteur g par ordre croissant et - // sort egalement l'indice des elements selon le trie dans le vecteur "index" suppos� initialis� par des valeurs de 1 a n - - float t; - int r,a,b; - - for(a = 1; a <= n; a++) - { - for(b = n-1; b >= a; b--) - if(*(g + b-1) < (*(g + b))) - { - // ordre croissant des �lements - t = *(g + b-1); - *(g + b-1) = *(g + b); - *(g + b) = t; - - // ordre des indices des �lements du vecteur g - r = *(index + b-1); - *(index + b-1) = *(index + b); - *(index + b) = r; - } - } -} - -float FuzzyUtils::min(float *a,float *b) -{ - float min = 0; - - if(*a >= (*b)) - min = *b; - else - min = *a; - - return min; -} - -float FuzzyUtils::max(float* g , int n) -{ - float max = 0; - - for(int i = 0; i < n; i++) - { - if(*(g+i) >= max) - max = *(g+i); - } - - return max; -} - -void FuzzyUtils::gDeDeux(float* a, float* b, float* lambda) -{ - float* c = (float*) malloc(1*sizeof(float)); - *c = *a + (*b) + (*lambda) * (*a) * (*b); -} - -void FuzzyUtils::getLambda(float* g) -{ - float a,b; - float* lambda = (float*) malloc(1*sizeof(float)); - - a = (*(g+0) * (*(g+1)) + (*(g+1)) * (*(g+2)) + (*(g+0)) * (*(g+2))); - *lambda = -(*(g+0) * (*(g+1)) + (*(g+1)) * (*(g+2)) + (*(g+0)) * (*(g+2))) / (*(g+0) * (*(g+1)) * (*(g+2))); - b = (*(g+0) * (*(g+1)) * (*(g+2))); - - //printf("\na:%f",a); - //printf("\nb:%f",b); - //printf("\nlambda:%f", *lambda); - - free(lambda); -} - -void FuzzyUtils::AdaptativeSelectiveBackgroundModelUpdate(IplImage* CurrentImage, IplImage* BGImage, IplImage* OutputImage, IplImage* Integral, float seuil, float alpha) -{ - PixelUtils p; - - float beta = 0.0; - float* CurentImagePixel = (float*) malloc(3*sizeof(float)); - float* BGImagePixel = (float*) malloc(3*sizeof(float)); - float* OutputImagePixel = (float*) malloc(3*sizeof(float)); - float* IntegralImagePixel = (float*) malloc(1*sizeof(float)); - float *Maximum = (float*) malloc(1*sizeof(float)); - float *Minimum = (float*) malloc(1*sizeof(float)); - - p.ForegroundMaximum(Integral, Maximum, 1); - p.ForegroundMinimum(Integral, Minimum, 1); - - for(int i = 0; i < CurrentImage->width; i++) - { - for(int j = 0; j < CurrentImage->height; j++) - { - p.GetPixel(CurrentImage, i, j, CurentImagePixel); - p.GetPixel(BGImage, i, j, BGImagePixel); - p.GetGrayPixel(Integral, i, j, IntegralImagePixel); - - beta = 1 - ((*IntegralImagePixel) - ((*Minimum / (*Minimum - *Maximum)) * (*IntegralImagePixel) - (*Minimum * (*Maximum) / (*Minimum - *Maximum)))); - - for(int k = 0; k < 3; k++) - *(OutputImagePixel + k) = beta * (*(BGImagePixel + k)) + (1 - beta) * (alpha * (*(CurentImagePixel+k)) + (1-alpha) * (*(BGImagePixel+k))); - - p.PutPixel(OutputImage, i, j, OutputImagePixel); - } - } - - free(CurentImagePixel); - free(BGImagePixel); - free(OutputImagePixel); - free(IntegralImagePixel); - free(Maximum); - free(Minimum); -} diff --git a/package_bgs/tb/PixelUtils.cpp b/package_bgs/tb/PixelUtils.cpp deleted file mode 100644 index d647e05089369117ec38dcec215d532b72825715..0000000000000000000000000000000000000000 --- a/package_bgs/tb/PixelUtils.cpp +++ /dev/null @@ -1,351 +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 "PixelUtils.h" - -PixelUtils::PixelUtils(void){} -PixelUtils::~PixelUtils(void){} - -void PixelUtils::ColorConversion(IplImage* RGBImage, IplImage* ConvertedImage, int color_space) -{ - // Space Color RGB - Nothing to do! - if(color_space == 1) - cvCopy(RGBImage, ConvertedImage); - - // Space Color Ohta - if(color_space == 2) - cvttoOTHA(RGBImage, ConvertedImage); - - // Space Color HSV - V Intensity - (H,S) Chromaticity - if(color_space == 3) - cvCvtColor(RGBImage, ConvertedImage, CV_BGR2HSV); - - // Space Color YCrCb - Y Intensity - (Cr,Cb) Chromaticity - if(color_space == 4) - cvCvtColor(RGBImage,ConvertedImage,CV_BGR2YCrCb); -} - -void PixelUtils::cvttoOTHA(IplImage* RGBImage, IplImage* OthaImage) -{ - float* OhtaPixel = (float*) malloc(3*(sizeof(float))); - float* RGBPixel = (float*) malloc(3*(sizeof(float))); - - for(int i = 0; i < RGBImage->width; i++) - { - for(int j = 0;j < RGBImage->height; j++) - { - GetPixel(RGBImage, i, j, RGBPixel); - - // I1 = (R + G + B) / 3 - *OhtaPixel = (*(RGBPixel) + (*(RGBPixel + 1)) + (*(RGBPixel + 2))) / 3.0; - - // I2 = (R - B) / 2 - *(OhtaPixel+1) = (*RGBPixel - (*(RGBPixel + 2))) / 2.0; - - // I3 = (2G - R - B) / 4 - *(OhtaPixel+2) = (2 * (*(RGBPixel + 1)) - (*RGBPixel) - (*(RGBPixel + 2))) / 4.0; - - PutPixel(OthaImage, i, j, OhtaPixel); - } - } - - free(OhtaPixel); - free(RGBPixel); -} - -void PixelUtils::PostProcessing(IplImage *InputImage) -{ - IplImage *ResultImage = cvCreateImage(cvSize(InputImage->width, InputImage->height), IPL_DEPTH_32F, 3); - - cvErode(InputImage, ResultImage, NULL, 1); - cvDilate(ResultImage, InputImage, NULL, 0); - - cvReleaseImage(&ResultImage); -} - -void PixelUtils::GetPixel(IplImage *image, int m, int n, unsigned char *pixelcourant) -{ - for(int k = 0; k < 3; k++) - pixelcourant[k] = ((unsigned char*)(image->imageData + image->widthStep*n))[m*3 + k]; -} - -void PixelUtils::GetGrayPixel(IplImage *image, int m, int n, unsigned char *pixelcourant) -{ - *pixelcourant = ((unsigned char*)(image->imageData + image->widthStep*n))[m]; -} - -void PixelUtils::PutPixel(IplImage *image,int p,int q,unsigned char *pixelcourant) -{ - for(int r = 0; r < 3; r++) - ((unsigned char*)(image->imageData + image->widthStep*q))[p*3 + r] = pixelcourant[r]; -} - -void PixelUtils::PutGrayPixel(IplImage *image, int p, int q, unsigned char pixelcourant) -{ - ((unsigned char*)(image->imageData + image->widthStep*q))[p] = pixelcourant; -} - -void PixelUtils::GetPixel(IplImage *image, int m, int n, float *pixelcourant) -{ - for(int k = 0; k < 3; k++) - pixelcourant[k] = ((float*)(image->imageData + image->widthStep*n))[m*3 + k]; -} - -void PixelUtils::GetGrayPixel(IplImage *image, int m, int n, float *pixelcourant) -{ - *pixelcourant = ((float*)(image->imageData + image->widthStep*n))[m]; -} - -void PixelUtils::PutPixel(IplImage *image, int p, int q, float *pixelcourant) -{ - for(int r = 0; r < 3; r++) - ((float*)(image->imageData + image->widthStep*q))[p*3 + r] = pixelcourant[r]; -} - -void PixelUtils::PutGrayPixel(IplImage *image,int p,int q,float pixelcourant) -{ - ((float*)(image->imageData + image->widthStep*q))[p] = pixelcourant; -} - -void PixelUtils::getNeighberhoodGrayPixel(IplImage* InputImage, int x, int y, float* neighberPixel) -{ - int i,j,k; - - float* pixelCourant = (float*) malloc(1*(sizeof(float))); - - //le calcul de voisinage pour les 4 coins; - /* 1.*/ - if(x==0 && y==0) - { - k = 0; - for(i = x; i < x+2; i++) - for(j = y; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - /* 2.*/ - if(x==0 && y==InputImage->width) - { - k = 0; - for(i = x; i < x+2; i++) - for(j = y-1; j < y+1; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - /* 3.*/ - if(x==InputImage->height && y==0) - { - k = 0; - for(i = x-1; i < x+1; i++) - for(j = y; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - /* 4.*/ - if(x==InputImage->height && y==InputImage->width) - { - k = 0; - for(i = x-1; i <x+1; i++) - for(j = y-1; j < y+1; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - // Voisinage de la premiere ligne : L(0) - if(x==0 && (y!=0 && y!=InputImage->width)) - { - k = 0; - for(i = x+1; i >= x; i--) - for(j = y-1; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - // Voisinage de la derni�re colonne : C(w) - if((x!=0 && x!=InputImage->height) && y==InputImage->width) - { - k = 0; - for(i = x+1; i > x-2; i--) - for(j = y-1; j < y+1; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - // Voisinage de la derni�re ligne : L(h) - if(x==InputImage->height && (y!=0 && y!=InputImage->width)) - { - k = 0; - for(i = x; i > x-2; i--) - for(j = y-1; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - // Voisinage de la premiere colonne : C(0) - if((x!=0 && x!=InputImage->height) && y==0) - { - k = 0; - for(i = x-1; i < x+2; i++) - for(j = y; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - //le calcul du voisinage pour le reste des elementes d'image - if((x!=0 && x!=InputImage->height)&&(y!=0 && y!=InputImage->width)) - { - k = 0; - for(i = x+1;i > x-2; i--) - for(j = y-1; j < y+2; j++) - { - GetGrayPixel(InputImage,i,j,pixelCourant); - *(neighberPixel+k) = *pixelCourant; - k++; - } - } - - free(pixelCourant); -} - -void PixelUtils::ForegroundMinimum(IplImage *Foreground, float *Minimum, int n) -{ - int i,j,k; - float *pixelcourant; - - pixelcourant = (float *) malloc(n*sizeof(float)); - - for(k = 0; k < n; k++) - *(Minimum + k) = 255; - - for(i = 0; i < Foreground->width; i++) - for(j = 0; j < Foreground->height; j++) - { - if(n == 3) - { - GetPixel(Foreground,i,j,pixelcourant); - - for(k = 0; k < n; k++) - if(*(pixelcourant + k) < *(Minimum + k)) - *(Minimum + k) = *(pixelcourant + k); - } - - if(n==1) - { - GetGrayPixel(Foreground,i,j,pixelcourant); - - if(*pixelcourant < *Minimum) - *Minimum = *pixelcourant; - } - } - - free(pixelcourant); -} - -void PixelUtils::ForegroundMaximum(IplImage *Foreground, float *Maximum, int n) -{ - int i,j,k; - float *pixelcourant; - - pixelcourant = (float *) malloc(n*sizeof(float)); - - for(k = 0; k < n; k++) - *(Maximum + k) = 0; - - for(i = 0; i < Foreground->width; i++) - for(j = 0; j < Foreground->height; j++) - { - if(n == 3) - { - GetPixel(Foreground,i,j,pixelcourant); - - for(k = 0; k < n; k++) - if(*(pixelcourant + k) > *(Maximum + k)) - *(Maximum + k) = *(pixelcourant + k); - } - - if(n == 1) - { - GetGrayPixel(Foreground,i,j,pixelcourant); - - if(*pixelcourant > *Maximum) - *Maximum = *pixelcourant; - } - } - - free(pixelcourant); -} - -void PixelUtils::ComplementaryAlphaImageCreation(IplImage *AlphaImage, IplImage *ComplementaryAlphaImage, int n) -{ - int i,j,k; - float *pixelcourant, *pixelcourant1; - - pixelcourant = (float *) malloc(n * sizeof(float)); - pixelcourant1 = (float *) malloc(n * sizeof(float)); - - for(i = 0; i < AlphaImage->width; i++) - for(j = 0; j < AlphaImage->height; j++) - { - if(n == 1) - { - GetGrayPixel(AlphaImage,i,j,pixelcourant); - *pixelcourant1 = 1 - *(pixelcourant); - PutGrayPixel(ComplementaryAlphaImage,i,j,*pixelcourant1); - } - - if(n == 3) - { - GetPixel(AlphaImage,i,j,pixelcourant); - for(k = 0; k < 3; k++) - { - *pixelcourant1 = 1.0 - *(pixelcourant); - *(pixelcourant1+1) = 1.0 - *(pixelcourant+1); - *(pixelcourant1+2) = 1.0 - *(pixelcourant+2); - } - PutPixel(ComplementaryAlphaImage,i,j,pixelcourant1); - } - } - - free(pixelcourant); - free(pixelcourant1); -} diff --git a/package_bgs/tb/T2FMRF_UM.h b/package_bgs/tb/T2FMRF_UM.h deleted file mode 100644 index fd0da7b1c2b68850d6b624ca489d38abdba462cf..0000000000000000000000000000000000000000 --- a/package_bgs/tb/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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "MRF.h" - -using namespace Algorithms::BackgroundSubtraction; - -class T2FMRF_UM : public IBGS -{ -private: - bool firstTime; - 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; - bool showOutput; - - 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/tb/T2FMRF_UV.h b/package_bgs/tb/T2FMRF_UV.h deleted file mode 100644 index 28fcb679c9c698ce5bde59b54d4e8fb5577cc411..0000000000000000000000000000000000000000 --- a/package_bgs/tb/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 <iostream> -#include <opencv2/opencv.hpp> - - -#include "../IBGS.h" -#include "MRF.h" - -using namespace Algorithms::BackgroundSubtraction; - -class T2FMRF_UV : public IBGS -{ -private: - bool firstTime; - 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; - bool showOutput; - - 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/vs2010/.gitignore b/vs2010/.gitignore deleted file mode 100644 index affde9233a4b8ff7958593971e21d20c09b0cd72..0000000000000000000000000000000000000000 --- a/vs2010/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# Ignore everything in this directory -* -# Except these files -!.gitignore -!README.txt -!bgslibrary.sln -!bgslibrary.suo -!bgslibrary.vcxproj -!bgslibrary.vcxproj.filters -!bgslibrary.vcxproj.user -!bgslibrary_demo.vcxproj -!bgslibrary_demo.vcxproj.filters -!bgslibrary_demo.vcxproj.user -!bgslibrary_demo2.vcxproj -!bgslibrary_demo2.vcxproj.filters -!bgslibrary_demo2.vcxproj.user diff --git a/vs2010/README.txt b/vs2010/README.txt deleted file mode 100644 index 7b0a5cf1796fc0df235fa1b1f050ef6f4e4cfbf3..0000000000000000000000000000000000000000 --- a/vs2010/README.txt +++ /dev/null @@ -1,15 +0,0 @@ -VISUAL STUDIO 2010 TEMPLATE PROJECT ------------------------------------ -Change to [Release][Win32] - -Tested with: - VISUAL STUDIO 2010 - VISUAL STUDIO 2012 - VISUAL STUDIO 2013 - VISUAL STUDIO 2015 - -You need to install OpenCV at: - C:\OpenCV2.4.10 -or change the project settings. - -Build and run! ;) \ No newline at end of file diff --git a/vs2010/bgslibrary.sln b/vs2010/bgslibrary.sln deleted file mode 100644 index ab59be309d10a090953faf2a36022849609195b0..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary.sln +++ /dev/null @@ -1,27 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bgslibrary", "bgslibrary.vcxproj", "{3B6BF763-9CDE-4859-ADD9-8EB7B282659F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bgslibrary_demo", "bgslibrary_demo.vcxproj", "{EBE7FE0E-9FE6-41D2-B744-D43E7446D50C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bgslibrary_demo2", "bgslibrary_demo2.vcxproj", "{EAA15CCC-270A-460B-A61C-2DB864D67718}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|Win32.ActiveCfg = Release|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|Win32.Build.0 = Release|Win32 - {EBE7FE0E-9FE6-41D2-B744-D43E7446D50C}.Release|Win32.ActiveCfg = Release|Win32 - {EBE7FE0E-9FE6-41D2-B744-D43E7446D50C}.Release|Win32.Build.0 = Release|Win32 - {EAA15CCC-270A-460B-A61C-2DB864D67718}.Release|Win32.ActiveCfg = Release|Win32 - {EAA15CCC-270A-460B-A61C-2DB864D67718}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vs2010/bgslibrary.suo b/vs2010/bgslibrary.suo deleted file mode 100644 index 3dc8e43797f0d1ee8f60b5d84b6328c180a83479..0000000000000000000000000000000000000000 Binary files a/vs2010/bgslibrary.suo and /dev/null differ diff --git a/vs2010/bgslibrary.vcxproj b/vs2010/bgslibrary.vcxproj deleted file mode 100644 index 248586584484775df8bc7a2d1a7699e80d25c648..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary.vcxproj +++ /dev/null @@ -1,279 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{3B6BF763-9CDE-4859-ADD9-8EB7B282659F}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>bgslibrary</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\build</OutDir> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc10\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\Demo.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\Demo2.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\FrameProcessor.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\Main.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\package_analysis\ForegroundMaskAnalysis.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\ae\KDE.cpp" /> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackground.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp" /> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp" /> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp" /> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp" /> - <ClCompile Include="..\package_bgs\ck\graph.cpp" /> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp" /> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp" /> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp" /> - <ClCompile Include="..\package_bgs\db\imbs.cpp" /> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp" /> - <ClCompile Include="..\package_bgs\dp\Error.cpp" /> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp" /> - <ClCompile Include="..\package_bgs\dp\Image.cpp" /> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp" /> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp" /> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\GMG.cpp" /> - <ClCompile Include="..\package_bgs\jmo\blob.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp" /> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp" /> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp" /> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\MRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp" /> - <ClCompile Include="..\PreProcessor.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\VideoAnalysis.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\VideoCapture.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\Config.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\FrameProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\IFrameProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\package_analysis\ForegroundMaskAnalysis.h" /> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\ae\KDE.h" /> - <ClInclude Include="..\package_bgs\ae\KernelTable.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h" /> - <ClInclude Include="..\package_bgs\av\TBackground.h" /> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h" /> - <ClInclude Include="..\package_bgs\av\VuMeter.h" /> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h" /> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h" /> - <ClInclude Include="..\package_bgs\bl\stdbool.h" /> - <ClInclude Include="..\package_bgs\ck\block.h" /> - <ClInclude Include="..\package_bgs\ck\graph.h" /> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h" /> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp" /> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp" /> - <ClInclude Include="..\package_bgs\db\imbs.hpp" /> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h" /> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Bgs.h" /> - <ClInclude Include="..\package_bgs\dp\BgsParams.h" /> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h" /> - <ClInclude Include="..\package_bgs\dp\Error.h" /> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h" /> - <ClInclude Include="..\package_bgs\dp\Image.h" /> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\WrenGA.h" /> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h" /> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\GMG.h" /> - <ClInclude Include="..\package_bgs\IBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h" /> - <ClInclude Include="..\package_bgs\jmo\BGS.h" /> - <ClInclude Include="..\package_bgs\jmo\blob.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h" /> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h" /> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h" /> - <ClInclude Include="..\package_bgs\lb\BGModel.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h" /> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h" /> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\Types.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h" /> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h" /> - <ClInclude Include="..\package_bgs\pl\LBSP.h" /> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\RandUtils.h" /> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h" /> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h" /> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h" /> - <ClInclude Include="..\package_bgs\tb\MRF.h" /> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h" /> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h" /> - <ClInclude Include="..\PreProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\VideoAnalysis.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\VideoCapture.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary.vcxproj.filters b/vs2010/bgslibrary.vcxproj.filters deleted file mode 100644 index ab0fbf0265b52c559040cc089240d8247c1cae67..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary.vcxproj.filters +++ /dev/null @@ -1,644 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Header Files\package_bgs"> - <UniqueIdentifier>{8cb396e6-81b6-4db9-a1b0-5c2b7c122bd9}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ae"> - <UniqueIdentifier>{e1ab6d45-3486-42fa-8f51-69a300c0c173}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\av"> - <UniqueIdentifier>{7992fa8c-e616-4e72-b249-6ede4f4291b4}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\db"> - <UniqueIdentifier>{667f4048-d125-4453-9f0c-42f9abd4ed3a}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\dp"> - <UniqueIdentifier>{89c4b817-936b-483c-abed-3e7e7c1fc427}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\jmo"> - <UniqueIdentifier>{c5e0f44c-6120-4906-917d-c8c8af3eafec}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\lb"> - <UniqueIdentifier>{728fbe82-1489-4878-89ea-a62ba0932204}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pt"> - <UniqueIdentifier>{6b017402-c47a-49a4-8f57-b5db863e1bde}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\sjn"> - <UniqueIdentifier>{e25c1e03-530d-4c7a-b776-26bf17595213}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\tb"> - <UniqueIdentifier>{53f2c4fb-9468-44ce-b76e-e25ea018c084}</UniqueIdentifier> - </Filter> - <Filter Include="Source Files\demo"> - <UniqueIdentifier>{23f1cd4a-e9b2-4338-a5e7-128f451d3c89}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_analysis"> - <UniqueIdentifier>{52a9f254-d817-4577-96c2-0b3b0a9527b7}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\bl"> - <UniqueIdentifier>{0494c5d4-b4bb-421c-b032-176903ba8e1b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ck"> - <UniqueIdentifier>{87961eee-b843-45bd-b642-9dcd9d78b661}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pl"> - <UniqueIdentifier>{cd33a41f-6151-46a5-95b6-b79022786144}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\GMG.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KDE.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackground.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\imbs.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Error.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Image.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\blob.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\MRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\FrameProcessor.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\Main.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\PreProcessor.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\VideoAnalysis.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\VideoCapture.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\Demo.cpp"> - <Filter>Source Files\demo</Filter> - </ClCompile> - <ClCompile Include="..\package_analysis\ForegroundMaskAnalysis.cpp"> - <Filter>Header Files\package_analysis</Filter> - </ClCompile> - <ClCompile Include="..\Demo2.cpp"> - <Filter>Source Files\demo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\graph.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\GMG.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\IBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KDE.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KernelTable.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackground.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\VuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\imbs.hpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Bgs.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\BgsParams.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Error.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Image.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\WrenGA.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\blob.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModel.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\Types.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\MRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\Config.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\FrameProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\IFrameProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\PreProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\VideoAnalysis.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\VideoCapture.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\package_analysis\ForegroundMaskAnalysis.h"> - <Filter>Header Files\package_analysis</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\stdbool.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\block.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\graph.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\RandUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary.vcxproj.user b/vs2010/bgslibrary.vcxproj.user deleted file mode 100644 index ebebb3be3c8c323f20cee48d5f72f973ac3afb4d..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments>-uf -fn=dataset/video.avi</LocalDebuggerCommandArguments> - </PropertyGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo.vcxproj b/vs2010/bgslibrary_demo.vcxproj deleted file mode 100644 index 966d57be2f68c5f0fd0989367754731893850ff2..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo.vcxproj +++ /dev/null @@ -1,241 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{EBE7FE0E-9FE6-41D2-B744-D43E7446D50C}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>bgslibrary</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\build</OutDir> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc10\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\Demo.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\ae\KDE.cpp" /> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackground.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp" /> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp" /> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp" /> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp" /> - <ClCompile Include="..\package_bgs\ck\graph.cpp" /> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp" /> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp" /> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp" /> - <ClCompile Include="..\package_bgs\db\imbs.cpp" /> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp" /> - <ClCompile Include="..\package_bgs\dp\Error.cpp" /> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp" /> - <ClCompile Include="..\package_bgs\dp\Image.cpp" /> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp" /> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp" /> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\GMG.cpp" /> - <ClCompile Include="..\package_bgs\jmo\blob.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp" /> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp" /> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp" /> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\MRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\ae\KDE.h" /> - <ClInclude Include="..\package_bgs\ae\KernelTable.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h" /> - <ClInclude Include="..\package_bgs\av\TBackground.h" /> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h" /> - <ClInclude Include="..\package_bgs\av\VuMeter.h" /> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h" /> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h" /> - <ClInclude Include="..\package_bgs\bl\stdbool.h" /> - <ClInclude Include="..\package_bgs\ck\block.h" /> - <ClInclude Include="..\package_bgs\ck\graph.h" /> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h" /> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp" /> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp" /> - <ClInclude Include="..\package_bgs\db\imbs.hpp" /> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h" /> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Bgs.h" /> - <ClInclude Include="..\package_bgs\dp\BgsParams.h" /> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h" /> - <ClInclude Include="..\package_bgs\dp\Error.h" /> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h" /> - <ClInclude Include="..\package_bgs\dp\Image.h" /> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\WrenGA.h" /> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h" /> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\GMG.h" /> - <ClInclude Include="..\package_bgs\IBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h" /> - <ClInclude Include="..\package_bgs\jmo\BGS.h" /> - <ClInclude Include="..\package_bgs\jmo\blob.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h" /> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h" /> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h" /> - <ClInclude Include="..\package_bgs\lb\BGModel.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h" /> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h" /> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\Types.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h" /> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h" /> - <ClInclude Include="..\package_bgs\pl\LBSP.h" /> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\RandUtils.h" /> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h" /> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h" /> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h" /> - <ClInclude Include="..\package_bgs\tb\MRF.h" /> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h" /> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h" /> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo.vcxproj.filters b/vs2010/bgslibrary_demo.vcxproj.filters deleted file mode 100644 index d9f3aa8224c2cec49c0148d8ebcc7e55987957a4..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo.vcxproj.filters +++ /dev/null @@ -1,596 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Header Files\package_bgs"> - <UniqueIdentifier>{8cb396e6-81b6-4db9-a1b0-5c2b7c122bd9}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ae"> - <UniqueIdentifier>{e1ab6d45-3486-42fa-8f51-69a300c0c173}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\av"> - <UniqueIdentifier>{7992fa8c-e616-4e72-b249-6ede4f4291b4}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\db"> - <UniqueIdentifier>{667f4048-d125-4453-9f0c-42f9abd4ed3a}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\dp"> - <UniqueIdentifier>{89c4b817-936b-483c-abed-3e7e7c1fc427}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\jmo"> - <UniqueIdentifier>{c5e0f44c-6120-4906-917d-c8c8af3eafec}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\lb"> - <UniqueIdentifier>{728fbe82-1489-4878-89ea-a62ba0932204}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pt"> - <UniqueIdentifier>{6b017402-c47a-49a4-8f57-b5db863e1bde}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\sjn"> - <UniqueIdentifier>{e25c1e03-530d-4c7a-b776-26bf17595213}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\tb"> - <UniqueIdentifier>{53f2c4fb-9468-44ce-b76e-e25ea018c084}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\bl"> - <UniqueIdentifier>{0494c5d4-b4bb-421c-b032-176903ba8e1b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ck"> - <UniqueIdentifier>{87961eee-b843-45bd-b642-9dcd9d78b661}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pl"> - <UniqueIdentifier>{cd33a41f-6151-46a5-95b6-b79022786144}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\GMG.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KDE.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackground.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\imbs.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Error.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Image.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\blob.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\MRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\graph.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\Demo.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\GMG.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\IBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KDE.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KernelTable.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackground.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\VuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\imbs.hpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Bgs.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\BgsParams.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Error.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Image.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\WrenGA.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\blob.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModel.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\Types.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\MRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\stdbool.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\block.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\graph.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\RandUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo.vcxproj.user b/vs2010/bgslibrary_demo.vcxproj.user deleted file mode 100644 index abe8dd8961e3b66a88605bd7083dad32ef27bee9..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup /> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo2.vcxproj b/vs2010/bgslibrary_demo2.vcxproj deleted file mode 100644 index ad0f4c4885039f583f88c26a5176e25810b762a3..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo2.vcxproj +++ /dev/null @@ -1,241 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{EAA15CCC-270A-460B-A61C-2DB864D67718}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>bgslibrary</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\build</OutDir> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc10\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\Demo2.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\ae\KDE.cpp" /> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackground.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp" /> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp" /> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp" /> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp" /> - <ClCompile Include="..\package_bgs\ck\graph.cpp" /> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp" /> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp" /> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp" /> - <ClCompile Include="..\package_bgs\db\imbs.cpp" /> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp" /> - <ClCompile Include="..\package_bgs\dp\Error.cpp" /> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp" /> - <ClCompile Include="..\package_bgs\dp\Image.cpp" /> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp" /> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp" /> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\GMG.cpp" /> - <ClCompile Include="..\package_bgs\jmo\blob.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp" /> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp" /> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp" /> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\MRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\ae\KDE.h" /> - <ClInclude Include="..\package_bgs\ae\KernelTable.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h" /> - <ClInclude Include="..\package_bgs\av\TBackground.h" /> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h" /> - <ClInclude Include="..\package_bgs\av\VuMeter.h" /> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h" /> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h" /> - <ClInclude Include="..\package_bgs\bl\stdbool.h" /> - <ClInclude Include="..\package_bgs\ck\block.h" /> - <ClInclude Include="..\package_bgs\ck\graph.h" /> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h" /> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp" /> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp" /> - <ClInclude Include="..\package_bgs\db\imbs.hpp" /> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h" /> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Bgs.h" /> - <ClInclude Include="..\package_bgs\dp\BgsParams.h" /> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h" /> - <ClInclude Include="..\package_bgs\dp\Error.h" /> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h" /> - <ClInclude Include="..\package_bgs\dp\Image.h" /> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\WrenGA.h" /> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h" /> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\GMG.h" /> - <ClInclude Include="..\package_bgs\IBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h" /> - <ClInclude Include="..\package_bgs\jmo\BGS.h" /> - <ClInclude Include="..\package_bgs\jmo\blob.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h" /> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h" /> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h" /> - <ClInclude Include="..\package_bgs\lb\BGModel.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h" /> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h" /> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\Types.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h" /> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h" /> - <ClInclude Include="..\package_bgs\pl\LBSP.h" /> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\RandUtils.h" /> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h" /> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h" /> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h" /> - <ClInclude Include="..\package_bgs\tb\MRF.h" /> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h" /> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h" /> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo2.vcxproj.filters b/vs2010/bgslibrary_demo2.vcxproj.filters deleted file mode 100644 index 45de1b6de367d51a75864819fb19ca2483e28e1c..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo2.vcxproj.filters +++ /dev/null @@ -1,596 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Header Files\package_bgs"> - <UniqueIdentifier>{8cb396e6-81b6-4db9-a1b0-5c2b7c122bd9}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ae"> - <UniqueIdentifier>{e1ab6d45-3486-42fa-8f51-69a300c0c173}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\av"> - <UniqueIdentifier>{7992fa8c-e616-4e72-b249-6ede4f4291b4}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\db"> - <UniqueIdentifier>{667f4048-d125-4453-9f0c-42f9abd4ed3a}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\dp"> - <UniqueIdentifier>{89c4b817-936b-483c-abed-3e7e7c1fc427}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\jmo"> - <UniqueIdentifier>{c5e0f44c-6120-4906-917d-c8c8af3eafec}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\lb"> - <UniqueIdentifier>{728fbe82-1489-4878-89ea-a62ba0932204}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pt"> - <UniqueIdentifier>{6b017402-c47a-49a4-8f57-b5db863e1bde}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\sjn"> - <UniqueIdentifier>{e25c1e03-530d-4c7a-b776-26bf17595213}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\tb"> - <UniqueIdentifier>{53f2c4fb-9468-44ce-b76e-e25ea018c084}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\bl"> - <UniqueIdentifier>{0494c5d4-b4bb-421c-b032-176903ba8e1b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ck"> - <UniqueIdentifier>{87961eee-b843-45bd-b642-9dcd9d78b661}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pl"> - <UniqueIdentifier>{cd33a41f-6151-46a5-95b6-b79022786144}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\GMG.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KDE.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackground.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\imbs.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Error.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Image.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\blob.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\MRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\graph.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\Demo2.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\GMG.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\IBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KDE.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KernelTable.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackground.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\VuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\imbs.hpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Bgs.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\BgsParams.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Error.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Image.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\WrenGA.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\blob.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModel.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\Types.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\MRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\stdbool.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\block.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\graph.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\RandUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/vs2010/bgslibrary_demo2.vcxproj.user b/vs2010/bgslibrary_demo2.vcxproj.user deleted file mode 100644 index abe8dd8961e3b66a88605bd7083dad32ef27bee9..0000000000000000000000000000000000000000 --- a/vs2010/bgslibrary_demo2.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup /> -</Project> \ No newline at end of file diff --git a/vs2010mfc/outputs/background/KEEP_THIS_FOLDER b/vs2010mfc/outputs/background/KEEP_THIS_FOLDER deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vs2010mfc/outputs/foreground/KEEP_THIS_FOLDER b/vs2010mfc/outputs/foreground/KEEP_THIS_FOLDER deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vs2010mfc/outputs/input/KEEP_THIS_FOLDER b/vs2010mfc/outputs/input/KEEP_THIS_FOLDER deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vs2010mfc/src/ReadMe.txt b/vs2010mfc/src/ReadMe.txt deleted file mode 100644 index 6c7fde03e015240ce34101fd9d65e3e2fa76f3f6..0000000000000000000000000000000000000000 --- a/vs2010mfc/src/ReadMe.txt +++ /dev/null @@ -1,100 +0,0 @@ -================================================================================ - MICROSOFT FOUNDATION CLASS LIBRARY : bgslibrary_vs2010_mfc Project Overview -=============================================================================== - -The application wizard has created this bgslibrary_vs2010_mfc application for -you. This application not only demonstrates the basics of using the Microsoft -Foundation Classes but is also a starting point for writing your application. - -This file contains a summary of what you will find in each of the files that -make up your bgslibrary_vs2010_mfc application. - -bgslibrary_vs2010_mfc.vcxproj - This is the main project file for VC++ projects generated using an application wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - application wizard. - -bgslibrary_vs2010_mfc.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -bgslibrary_vs2010_mfc.h - This is the main header file for the application. It includes other - project specific headers (including Resource.h) and declares the - CApp application class. - -bgslibrary_vs2010_mfc.cpp - This is the main application source file that contains the application - class CApp. - -bgslibrary_vs2010_mfc.rc - This is a listing of all of the Microsoft Windows resources that the - program uses. It includes the icons, bitmaps, and cursors that are stored - in the RES subdirectory. This file can be directly edited in Microsoft - Visual C++. Your project resources are in 1033. - -res\bgslibrary_vs2010_mfc.ico - This is an icon file, which is used as the application's icon. This - icon is included by the main resource file bgslibrary_vs2010_mfc.rc. - -res\bgslibrary_vs2010_mfc.rc2 - This file contains resources that are not edited by Microsoft - Visual C++. You should place all resources not editable by - the resource editor in this file. - - -///////////////////////////////////////////////////////////////////////////// - -The application wizard creates one dialog class: - -Dlg.h, Dlg.cpp - the dialog - These files contain your CDlg class. This class defines - the behavior of your application's main dialog. The dialog's template is - in bgslibrary_vs2010_mfc.rc, which can be edited in Microsoft Visual C++. - - -///////////////////////////////////////////////////////////////////////////// - -Other Features: - -ActiveX Controls - The application includes support to use ActiveX controls. - -///////////////////////////////////////////////////////////////////////////// - -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named bgslibrary_vs2010_mfc.pch and a precompiled types file named StdAfx.obj. - -Resource.h - This is the standard header file, which defines new resource IDs. - Microsoft Visual C++ reads and updates this file. - -bgslibrary_vs2010_mfc.manifest - Application manifest files are used by Windows XP to describe an applications - dependency on specific versions of Side-by-Side assemblies. The loader uses this - information to load the appropriate assembly from the assembly cache or private - from the application. The Application manifest maybe included for redistribution - as an external .manifest file that is installed in the same folder as the application - executable or it may be included in the executable in the form of a resource. -///////////////////////////////////////////////////////////////////////////// - -Other notes: - -The application wizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -If your application uses MFC in a shared DLL, you will need -to redistribute the MFC DLLs. If your application is in a language -other than the operating system's locale, you will also have to -redistribute the corresponding localized resources MFC100XXX.DLL. -For more information on both of these topics, please see the section on -redistributing Visual C++ applications in MSDN documentation. - -///////////////////////////////////////////////////////////////////////////// diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.rc b/vs2010mfc/src/bgslibrary_vs2010_mfc.rc deleted file mode 100644 index 7251658acf1cfb47e9ec6c5f95ae0d54e0237ed3..0000000000000000000000000000000000000000 Binary files a/vs2010mfc/src/bgslibrary_vs2010_mfc.rc and /dev/null differ diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.sln b/vs2010mfc/src/bgslibrary_vs2010_mfc.sln deleted file mode 100644 index f082581f1fd0405b195a65ebb6f6c52e847782c3..0000000000000000000000000000000000000000 --- a/vs2010mfc/src/bgslibrary_vs2010_mfc.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bgslibrary_vs2010_mfc", "bgslibrary_vs2010_mfc.vcxproj", "{236E77EE-00D6-4B4E-80C7-C38847B1B60E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {236E77EE-00D6-4B4E-80C7-C38847B1B60E}.Debug|Win32.ActiveCfg = Debug|Win32 - {236E77EE-00D6-4B4E-80C7-C38847B1B60E}.Debug|Win32.Build.0 = Debug|Win32 - {236E77EE-00D6-4B4E-80C7-C38847B1B60E}.Release|Win32.ActiveCfg = Release|Win32 - {236E77EE-00D6-4B4E-80C7-C38847B1B60E}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.v12.suo b/vs2010mfc/src/bgslibrary_vs2010_mfc.v12.suo deleted file mode 100644 index dde25911dbe9553c86ec3483e9f01294bcef873b..0000000000000000000000000000000000000000 Binary files a/vs2010mfc/src/bgslibrary_vs2010_mfc.v12.suo and /dev/null differ diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj b/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj deleted file mode 100644 index 1ed007d81a93f2a9df418151d5ca8fa2aeea5ab6..0000000000000000000000000000000000000000 --- a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj +++ /dev/null @@ -1,296 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{236E77EE-00D6-4B4E-80C7-C38847B1B60E}</ProjectGuid> - <RootNamespace>bgslibrary_vs2010_mfc</RootNamespace> - <Keyword>MFCProj</Keyword> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>Unicode</CharacterSet> - <UseOfMfc>Static</UseOfMfc> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <UseOfMfc>Static</UseOfMfc> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <OutDir>../</OutDir> - <TargetName>mfc_bgslibrary</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <PrecompiledHeader>Use</PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <SubSystem>Windows</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - <Midl> - <MkTypLibCompatible>false</MkTypLibCompatible> - <ValidateAllParameters>true</ValidateAllParameters> - <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </Midl> - <ResourceCompile> - <Culture>0x0409</Culture> - <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader>NotUsing</PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;C:\boost_1_55_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Windows</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc10\staticlib\*.lib;C:\boost_1_55_0\stage32\lib\vc10\*.lib;comctl32.lib;VFW32.lib;uafxcw.lib;LIBCMT.lib;%(AdditionalDependencies)</AdditionalDependencies> - <ShowProgress>NotSet</ShowProgress> - <IgnoreSpecificDefaultLibraries>uafxcw.lib;LIBCMT.lib</IgnoreSpecificDefaultLibraries> - </Link> - <Midl> - <MkTypLibCompatible>false</MkTypLibCompatible> - <ValidateAllParameters>true</ValidateAllParameters> - <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </Midl> - <ResourceCompile> - <Culture>0x0409</Culture> - <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> - <ItemGroup> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i" /> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i" /> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i" /> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i" /> - <None Include="ReadMe.txt" /> - <None Include="res\bgslibrary_vs2010_mfc.ico" /> - <None Include="res\bgslibrary_vs2010_mfc.rc2" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorLBSP.h" /> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorLOBSTER.h" /> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h" /> - <ClInclude Include="..\..\package_bgs\pl\DistanceUtils.h" /> - <ClInclude Include="..\..\package_bgs\pl\LBSP.h" /> - <ClInclude Include="..\..\package_bgs\pl\LOBSTER.h" /> - <ClInclude Include="..\..\package_bgs\pl\RandUtils.h" /> - <ClInclude Include="..\..\package_bgs\pl\SuBSENSE.h" /> - <ClInclude Include="App.h" /> - <ClInclude Include="Dlg.h" /> - <ClInclude Include="..\..\package_bgs\AdaptiveBackgroundLearning.h" /> - <ClInclude Include="..\..\package_bgs\AdaptiveSelectiveBackgroundLearning.h" /> - <ClInclude Include="..\..\package_bgs\ae\KDE.h" /> - <ClInclude Include="..\..\package_bgs\ae\KernelTable.h" /> - <ClInclude Include="..\..\package_bgs\ae\NPBGmodel.h" /> - <ClInclude Include="..\..\package_bgs\ae\NPBGSubtractor.h" /> - <ClInclude Include="..\..\package_bgs\av\TBackground.h" /> - <ClInclude Include="..\..\package_bgs\av\TBackgroundVuMeter.h" /> - <ClInclude Include="..\..\package_bgs\av\VuMeter.h" /> - <ClInclude Include="..\..\package_bgs\bl\sdLaMa091.h" /> - <ClInclude Include="..\..\package_bgs\bl\SigmaDeltaBGS.h" /> - <ClInclude Include="..\..\package_bgs\bl\stdbool.h" /> - <ClInclude Include="..\..\package_bgs\db\imbs.hpp" /> - <ClInclude Include="..\..\package_bgs\db\IndependentMultimodalBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\AdaptiveMedianBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\Bgs.h" /> - <ClInclude Include="..\..\package_bgs\dp\BgsParams.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPAdaptiveMedianBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPEigenbackgroundBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPGrimsonGMMBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPMeanBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPPratiMediodBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPTextureBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPWrenGABGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\DPZivkovicAGMMBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\Eigenbackground.h" /> - <ClInclude Include="..\..\package_bgs\dp\Error.h" /> - <ClInclude Include="..\..\package_bgs\dp\GrimsonGMM.h" /> - <ClInclude Include="..\..\package_bgs\dp\Image.h" /> - <ClInclude Include="..\..\package_bgs\dp\MeanBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\PratiMediodBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\TextureBGS.h" /> - <ClInclude Include="..\..\package_bgs\dp\WrenGA.h" /> - <ClInclude Include="..\..\package_bgs\dp\ZivkovicAGMM.h" /> - <ClInclude Include="..\..\package_bgs\FrameDifferenceBGS.h" /> - <ClInclude Include="..\..\package_bgs\GMG.h" /> - <ClInclude Include="..\..\package_bgs\IBGS.h" /> - <ClInclude Include="..\..\package_bgs\jmo\BackgroundSubtractionAPI.h" /> - <ClInclude Include="..\..\package_bgs\jmo\BGS.h" /> - <ClInclude Include="..\..\package_bgs\jmo\blob.h" /> - <ClInclude Include="..\..\package_bgs\jmo\BlobExtraction.h" /> - <ClInclude Include="..\..\package_bgs\jmo\BlobLibraryConfiguration.h" /> - <ClInclude Include="..\..\package_bgs\jmo\BlobResult.h" /> - <ClInclude Include="..\..\package_bgs\jmo\CMultiLayerBGS.h" /> - <ClInclude Include="..\..\package_bgs\jmo\LocalBinaryPattern.h" /> - <ClInclude Include="..\..\package_bgs\jmo\MultiLayerBGS.h" /> - <ClInclude Include="..\..\package_bgs\jmo\OpenCvDataConversion.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModel.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModelFuzzyGauss.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModelFuzzySom.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModelGauss.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModelMog.h" /> - <ClInclude Include="..\..\package_bgs\lb\BGModelSom.h" /> - <ClInclude Include="..\..\package_bgs\lb\LBAdaptiveSOM.h" /> - <ClInclude Include="..\..\package_bgs\lb\LBFuzzyAdaptiveSOM.h" /> - <ClInclude Include="..\..\package_bgs\lb\LBFuzzyGaussian.h" /> - <ClInclude Include="..\..\package_bgs\lb\LBMixtureOfGaussians.h" /> - <ClInclude Include="..\..\package_bgs\lb\LBSimpleGaussian.h" /> - <ClInclude Include="..\..\package_bgs\lb\Types.h" /> - <ClInclude Include="..\..\package_bgs\MixtureOfGaussianV1BGS.h" /> - <ClInclude Include="..\..\package_bgs\MixtureOfGaussianV2BGS.h" /> - <ClInclude Include="..\..\package_bgs\sjn\SJN_MultiCueBGS.h" /> - <ClInclude Include="..\..\package_bgs\StaticFrameDifferenceBGS.h" /> - <ClInclude Include="..\..\package_bgs\tb\FuzzyChoquetIntegral.h" /> - <ClInclude Include="..\..\package_bgs\tb\FuzzySugenoIntegral.h" /> - <ClInclude Include="..\..\package_bgs\tb\FuzzyUtils.h" /> - <ClInclude Include="..\..\package_bgs\tb\MRF.h" /> - <ClInclude Include="..\..\package_bgs\tb\PerformanceUtils.h" /> - <ClInclude Include="..\..\package_bgs\tb\PixelUtils.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM_UM.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM_UV.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF_UM.h" /> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF_UV.h" /> - <ClInclude Include="..\..\package_bgs\WeightedMovingMeanBGS.h" /> - <ClInclude Include="..\..\package_bgs\WeightedMovingVarianceBGS.h" /> - <ClInclude Include="Resource.h" /> - <ClInclude Include="stdafx.h" /> - <ClInclude Include="targetver.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorLBSP.cpp" /> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp" /> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp" /> - <ClCompile Include="..\..\package_bgs\pl\LBSP.cpp" /> - <ClCompile Include="..\..\package_bgs\pl\LOBSTER.cpp" /> - <ClCompile Include="..\..\package_bgs\pl\SuBSENSE.cpp" /> - <ClCompile Include="App.cpp" /> - <ClCompile Include="Dlg.cpp" /> - <ClCompile Include="..\..\package_bgs\AdaptiveBackgroundLearning.cpp" /> - <ClCompile Include="..\..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" /> - <ClCompile Include="..\..\package_bgs\ae\KDE.cpp" /> - <ClCompile Include="..\..\package_bgs\ae\KernelTable.cpp" /> - <ClCompile Include="..\..\package_bgs\ae\NPBGmodel.cpp" /> - <ClCompile Include="..\..\package_bgs\ae\NPBGSubtractor.cpp" /> - <ClCompile Include="..\..\package_bgs\av\TBackground.cpp" /> - <ClCompile Include="..\..\package_bgs\av\TBackgroundVuMeter.cpp" /> - <ClCompile Include="..\..\package_bgs\av\VuMeter.cpp" /> - <ClCompile Include="..\..\package_bgs\bl\sdLaMa091.cpp" /> - <ClCompile Include="..\..\package_bgs\bl\SigmaDeltaBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\db\imbs.cpp" /> - <ClCompile Include="..\..\package_bgs\db\IndependentMultimodalBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\AdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPAdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPEigenbackgroundBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPGrimsonGMMBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPMeanBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPPratiMediodBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPTextureBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPWrenGABGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\DPZivkovicAGMMBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\Eigenbackground.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\Error.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\GrimsonGMM.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\Image.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\MeanBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\PratiMediodBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\TextureBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\WrenGA.cpp" /> - <ClCompile Include="..\..\package_bgs\dp\ZivkovicAGMM.cpp" /> - <ClCompile Include="..\..\package_bgs\FrameDifferenceBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\GMG.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\blob.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\BlobExtraction.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\BlobResult.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\CMultiLayerBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\LocalBinaryPattern.cpp" /> - <ClCompile Include="..\..\package_bgs\jmo\MultiLayerBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModel.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModelFuzzyGauss.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModelFuzzySom.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModelGauss.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModelMog.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\BGModelSom.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\LBAdaptiveSOM.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\LBFuzzyGaussian.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\LBMixtureOfGaussians.cpp" /> - <ClCompile Include="..\..\package_bgs\lb\LBSimpleGaussian.cpp" /> - <ClCompile Include="..\..\package_bgs\MixtureOfGaussianV1BGS.cpp" /> - <ClCompile Include="..\..\package_bgs\MixtureOfGaussianV2BGS.cpp" /> - <ClCompile Include="..\..\package_bgs\sjn\SJN_MultiCueBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\StaticFrameDifferenceBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\FuzzyChoquetIntegral.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\FuzzySugenoIntegral.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\FuzzyUtils.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\MRF.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\PerformanceUtils.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\PixelUtils.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM_UM.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM_UV.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF_UM.cpp" /> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF_UV.cpp" /> - <ClCompile Include="..\..\package_bgs\WeightedMovingMeanBGS.cpp" /> - <ClCompile Include="..\..\package_bgs\WeightedMovingVarianceBGS.cpp" /> - <ClCompile Include="stdafx.cpp"> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="bgslibrary_vs2010_mfc.rc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> - <ProjectExtensions> - <VisualStudio> - <UserProperties RESOURCE_FILE="bgslibrary_vs2010_mfc.rc" /> - </VisualStudio> - </ProjectExtensions> -</Project> \ No newline at end of file diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.filters b/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.filters deleted file mode 100644 index 28d979dd3d0204fa3d2b913eb231e03c20dc1944..0000000000000000000000000000000000000000 --- a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.filters +++ /dev/null @@ -1,581 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Header Files\package_bgs"> - <UniqueIdentifier>{be6b45b0-e96c-4347-a65e-a72506b4195f}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\av"> - <UniqueIdentifier>{c4756493-26d9-46f4-93d6-024b4d1ca61a}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\dp"> - <UniqueIdentifier>{a3dff805-136a-4fc5-a8e9-a7eadebcd6f2}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\jmo"> - <UniqueIdentifier>{d9c40f02-d18f-46bb-a956-522e83a8a2e7}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\lb"> - <UniqueIdentifier>{77576fcd-de50-4205-8072-cb25a1aab145}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\tb"> - <UniqueIdentifier>{50f16e47-ef1d-46b0-a0cb-f7c07599cd21}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ae"> - <UniqueIdentifier>{704bbcb4-9bbe-4fe1-8a80-78ee8d7f49c5}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\sjn"> - <UniqueIdentifier>{d365878b-8639-4bfd-8008-adb158c9cd8b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\db"> - <UniqueIdentifier>{f7961eef-2755-4712-a9b7-1b840b7936b1}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\bl"> - <UniqueIdentifier>{e23418b4-562b-41ae-bd15-e9ad45ece1d1}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pl"> - <UniqueIdentifier>{2a0f8129-33e2-4829-a112-edba4c8f5ef6}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <None Include="ReadMe.txt" /> - <None Include="res\bgslibrary_vs2010_mfc.rc2"> - <Filter>Resource Files</Filter> - </None> - <None Include="res\bgslibrary_vs2010_mfc.ico"> - <Filter>Resource Files</Filter> - </None> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - </ItemGroup> - <ItemGroup> - <ClInclude Include="Dlg.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="stdafx.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="targetver.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="Resource.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="App.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\AdaptiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\FrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\GMG.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\IBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\MixtureOfGaussianV1BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\MixtureOfGaussianV2BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\StaticFrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\WeightedMovingMeanBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\WeightedMovingVarianceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\av\TBackground.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\av\TBackgroundVuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\av\VuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\BackgroundSubtractionAPI.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\BGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\blob.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\BlobExtraction.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\BlobLibraryConfiguration.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\BlobResult.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\CMultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\LocalBinaryPattern.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\MultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\jmo\OpenCvDataConversion.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModel.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModelFuzzyGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModelFuzzySom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModelGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModelMog.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\BGModelSom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\LBAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\LBFuzzyAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\LBFuzzyGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\LBMixtureOfGaussians.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\LBSimpleGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\lb\Types.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\FuzzyChoquetIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\FuzzySugenoIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\FuzzyUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\MRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\PerformanceUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\PixelUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FGMM_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\tb\T2FMRF_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\ae\KDE.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\ae\KernelTable.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\ae\NPBGmodel.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\ae\NPBGSubtractor.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\AdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\Bgs.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\BgsParams.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPAdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPEigenbackgroundBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPGrimsonGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPMeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPPratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPTextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPWrenGABGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\DPZivkovicAGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\Eigenbackground.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\Error.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\GrimsonGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\Image.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\MeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\PratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\TextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\WrenGA.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\dp\ZivkovicAGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\sjn\SJN_MultiCueBGS.h"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\db\imbs.hpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\db\IndependentMultimodalBGS.h"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\AdaptiveSelectiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\bl\sdLaMa091.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\bl\SigmaDeltaBGS.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\bl\stdbool.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorLBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorLOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\DistanceUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\LBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\LOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\RandUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\..\package_bgs\pl\SuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <ClCompile Include="Dlg.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="stdafx.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="App.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\AdaptiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\FrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\GMG.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\MixtureOfGaussianV1BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\MixtureOfGaussianV2BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\StaticFrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\WeightedMovingMeanBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\WeightedMovingVarianceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\av\TBackground.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\av\TBackgroundVuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\av\VuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\blob.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\BlobExtraction.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\BlobResult.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\CMultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\LocalBinaryPattern.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\jmo\MultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModel.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModelFuzzyGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModelFuzzySom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModelGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModelMog.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\BGModelSom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\LBAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\LBFuzzyGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\LBMixtureOfGaussians.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\lb\LBSimpleGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\FuzzyChoquetIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\FuzzySugenoIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\FuzzyUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\MRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\PerformanceUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\PixelUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FGMM_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\tb\T2FMRF_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\ae\KDE.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\ae\KernelTable.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\ae\NPBGmodel.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\ae\NPBGSubtractor.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\AdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPAdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPEigenbackgroundBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPGrimsonGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPMeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPPratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPTextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPWrenGABGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\DPZivkovicAGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\Eigenbackground.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\Error.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\GrimsonGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\Image.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\MeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\PratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\TextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\WrenGA.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\dp\ZivkovicAGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\sjn\SJN_MultiCueBGS.cpp"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\db\imbs.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\db\IndependentMultimodalBGS.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\bl\sdLaMa091.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\bl\SigmaDeltaBGS.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorLBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\LBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\LOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\..\package_bgs\pl\SuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="bgslibrary_vs2010_mfc.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.user b/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.user deleted file mode 100644 index 882b48c8d7ec68d8f657f496796212ce80d27ea7..0000000000000000000000000000000000000000 --- a/vs2010mfc/src/bgslibrary_vs2010_mfc.vcxproj.user +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - </PropertyGroup> -</Project> \ No newline at end of file diff --git a/vs2010mfc/src/res/bgslibrary_vs2010_mfc.ico b/vs2010mfc/src/res/bgslibrary_vs2010_mfc.ico deleted file mode 100644 index d56fbcdfdf6eac0f4727c34770c26689271d96af..0000000000000000000000000000000000000000 Binary files a/vs2010mfc/src/res/bgslibrary_vs2010_mfc.ico and /dev/null differ diff --git a/vs2010mfc/src/res/bgslibrary_vs2010_mfc.rc2 b/vs2010mfc/src/res/bgslibrary_vs2010_mfc.rc2 deleted file mode 100644 index e327fa85913f2210efffc3a01eb0194aadda29e2..0000000000000000000000000000000000000000 Binary files a/vs2010mfc/src/res/bgslibrary_vs2010_mfc.rc2 and /dev/null differ diff --git a/vs2013/.gitignore b/vs2013/.gitignore deleted file mode 100644 index e289c9527e1cc7770a2991e1087affd94f960243..0000000000000000000000000000000000000000 --- a/vs2013/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Ignore everything in this directory -* -# Except these files -!.gitignore -!bgslibrary.sln -!bgslibrary.suo -!bgslibrary.vcxproj -!bgslibrary.vcxproj.filters -!bgslibrary.vcxproj.user -!README.txt \ No newline at end of file diff --git a/vs2013/README.txt b/vs2013/README.txt deleted file mode 100644 index e090e339c1145cffcfd5efb5ff8076bd36febd6f..0000000000000000000000000000000000000000 --- a/vs2013/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -VISUAL STUDIO 2013 TEMPLATE PROJECT ------------------------------------ -Select [Release][Win32] or [Release][x64] - -YOU NEEDS TO INSTALL OPENCV AT: - C:\OpenCV2.4.10 - -BUILD AND RUN! \ No newline at end of file diff --git a/vs2013/bgslibrary.sln b/vs2013/bgslibrary.sln deleted file mode 100644 index 8013b8e1af2ed99ead4d54d55b9f1efb336b6393..0000000000000000000000000000000000000000 --- a/vs2013/bgslibrary.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bgslibrary", "bgslibrary.vcxproj", "{3B6BF763-9CDE-4859-ADD9-8EB7B282659F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseDemo|Win32 = ReleaseDemo|Win32 - ReleaseDemo|x64 = ReleaseDemo|x64 - ReleaseDemo2|Win32 = ReleaseDemo2|Win32 - ReleaseDemo2|x64 = ReleaseDemo2|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Debug|Win32.ActiveCfg = Debug|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Debug|Win32.Build.0 = Debug|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Debug|x64.ActiveCfg = Debug|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Debug|x64.Build.0 = Debug|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|Win32.ActiveCfg = Release|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|Win32.Build.0 = Release|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|x64.ActiveCfg = Release|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.Release|x64.Build.0 = Release|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo|Win32.ActiveCfg = ReleaseDemo|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo|Win32.Build.0 = ReleaseDemo|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo|x64.ActiveCfg = ReleaseDemo|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo|x64.Build.0 = ReleaseDemo|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo2|Win32.ActiveCfg = ReleaseDemo2|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo2|Win32.Build.0 = ReleaseDemo2|Win32 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo2|x64.ActiveCfg = ReleaseDemo2|x64 - {3B6BF763-9CDE-4859-ADD9-8EB7B282659F}.ReleaseDemo2|x64.Build.0 = ReleaseDemo2|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vs2013/bgslibrary.suo b/vs2013/bgslibrary.suo deleted file mode 100644 index 3dc8e43797f0d1ee8f60b5d84b6328c180a83479..0000000000000000000000000000000000000000 Binary files a/vs2013/bgslibrary.suo and /dev/null differ diff --git a/vs2013/bgslibrary.vcxproj b/vs2013/bgslibrary.vcxproj deleted file mode 100644 index de8e328ef22c18303faf5140fea7ae68a0481ec6..0000000000000000000000000000000000000000 --- a/vs2013/bgslibrary.vcxproj +++ /dev/null @@ -1,600 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="ReleaseDemo2|Win32"> - <Configuration>ReleaseDemo2</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="ReleaseDemo2|x64"> - <Configuration>ReleaseDemo2</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="ReleaseDemo|Win32"> - <Configuration>ReleaseDemo</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="ReleaseDemo|x64"> - <Configuration>ReleaseDemo</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{3B6BF763-9CDE-4859-ADD9-8EB7B282659F}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>bgslibrary</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120</PlatformToolset> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\</OutDir> - <IntDir>$(Platform)\$(Configuration)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>../</OutDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\</OutDir> - <TargetName>Demo</TargetName> - <IntDir>$(Platform)\$(Configuration)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'"> - <TargetName>Demo</TargetName> - <LinkIncremental>false</LinkIncremental> - <OutDir>../</OutDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>..\</OutDir> - <TargetName>Demo2</TargetName> - <IntDir>$(Platform)\$(Configuration)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'"> - <TargetName>Demo2</TargetName> - <LinkIncremental>false</LinkIncremental> - <OutDir>../</OutDir> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x64\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x64\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x86\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader> - </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>C:\OpenCV2.4.10\build\include;C:\OpenCV2.4.10\build\include\opencv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <AdditionalDependencies>C:\OpenCV2.4.10\build\x64\vc12\staticlib\*.lib;comctl32.lib;VFW32.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\Demo.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\Demo2.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\FrameProcessor.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\Main.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">true</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\package_analysis\ForegroundMaskAnalysis.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp" /> - <ClCompile Include="..\package_bgs\ae\KDE.cpp" /> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp" /> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackground.cpp" /> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp" /> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp" /> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp" /> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp" /> - <ClCompile Include="..\package_bgs\ck\graph.cpp" /> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp" /> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp" /> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp" /> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp" /> - <ClCompile Include="..\package_bgs\db\imbs.cpp" /> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp" /> - <ClCompile Include="..\package_bgs\dp\Error.cpp" /> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp" /> - <ClCompile Include="..\package_bgs\dp\Image.cpp" /> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp" /> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp" /> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp" /> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\GMG.cpp" /> - <ClCompile Include="..\package_bgs\jmo\blob.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp" /> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp" /> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp" /> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp" /> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp" /> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp" /> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp" /> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp" /> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp" /> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp" /> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp" /> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\MRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp" /> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp" /> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp" /> - <ClCompile Include="..\PreProcessor.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\VideoAnalysis.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClCompile> - <ClCompile Include="..\VideoCapture.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\Config.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\FrameProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\IFrameProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\package_analysis\ForegroundMaskAnalysis.h" /> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h" /> - <ClInclude Include="..\package_bgs\ae\KDE.h" /> - <ClInclude Include="..\package_bgs\ae\KernelTable.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h" /> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h" /> - <ClInclude Include="..\package_bgs\av\TBackground.h" /> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h" /> - <ClInclude Include="..\package_bgs\av\VuMeter.h" /> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h" /> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h" /> - <ClInclude Include="..\package_bgs\bl\stdbool.h" /> - <ClInclude Include="..\package_bgs\ck\block.h" /> - <ClInclude Include="..\package_bgs\ck\graph.h" /> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h" /> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp" /> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp" /> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp" /> - <ClInclude Include="..\package_bgs\db\imbs.hpp" /> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h" /> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Bgs.h" /> - <ClInclude Include="..\package_bgs\dp\BgsParams.h" /> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h" /> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h" /> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h" /> - <ClInclude Include="..\package_bgs\dp\Error.h" /> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h" /> - <ClInclude Include="..\package_bgs\dp\Image.h" /> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h" /> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h" /> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h" /> - <ClInclude Include="..\package_bgs\dp\WrenGA.h" /> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h" /> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\GMG.h" /> - <ClInclude Include="..\package_bgs\IBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h" /> - <ClInclude Include="..\package_bgs\jmo\BGS.h" /> - <ClInclude Include="..\package_bgs\jmo\blob.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h" /> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h" /> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h" /> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h" /> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h" /> - <ClInclude Include="..\package_bgs\lb\BGModel.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h" /> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h" /> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h" /> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h" /> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h" /> - <ClInclude Include="..\package_bgs\lb\Types.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h" /> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h" /> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h" /> - <ClInclude Include="..\package_bgs\pl\LBSP.h" /> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h" /> - <ClInclude Include="..\package_bgs\pl\RandUtils.h" /> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h" /> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h" /> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h" /> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h" /> - <ClInclude Include="..\package_bgs\tb\MRF.h" /> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h" /> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h" /> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h" /> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h" /> - <ClInclude Include="..\PreProcessor.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\VideoAnalysis.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - <ClInclude Include="..\VideoCapture.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'">false</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'">false</ExcludedFromBuild> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i" /> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/vs2013/bgslibrary.vcxproj.filters b/vs2013/bgslibrary.vcxproj.filters deleted file mode 100644 index ab0fbf0265b52c559040cc089240d8247c1cae67..0000000000000000000000000000000000000000 --- a/vs2013/bgslibrary.vcxproj.filters +++ /dev/null @@ -1,644 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Header Files\package_bgs"> - <UniqueIdentifier>{8cb396e6-81b6-4db9-a1b0-5c2b7c122bd9}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ae"> - <UniqueIdentifier>{e1ab6d45-3486-42fa-8f51-69a300c0c173}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\av"> - <UniqueIdentifier>{7992fa8c-e616-4e72-b249-6ede4f4291b4}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\db"> - <UniqueIdentifier>{667f4048-d125-4453-9f0c-42f9abd4ed3a}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\dp"> - <UniqueIdentifier>{89c4b817-936b-483c-abed-3e7e7c1fc427}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\jmo"> - <UniqueIdentifier>{c5e0f44c-6120-4906-917d-c8c8af3eafec}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\lb"> - <UniqueIdentifier>{728fbe82-1489-4878-89ea-a62ba0932204}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pt"> - <UniqueIdentifier>{6b017402-c47a-49a4-8f57-b5db863e1bde}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\sjn"> - <UniqueIdentifier>{e25c1e03-530d-4c7a-b776-26bf17595213}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\tb"> - <UniqueIdentifier>{53f2c4fb-9468-44ce-b76e-e25ea018c084}</UniqueIdentifier> - </Filter> - <Filter Include="Source Files\demo"> - <UniqueIdentifier>{23f1cd4a-e9b2-4338-a5e7-128f451d3c89}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_analysis"> - <UniqueIdentifier>{52a9f254-d817-4577-96c2-0b3b0a9527b7}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\bl"> - <UniqueIdentifier>{0494c5d4-b4bb-421c-b032-176903ba8e1b}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\ck"> - <UniqueIdentifier>{87961eee-b843-45bd-b642-9dcd9d78b661}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files\package_bgs\pl"> - <UniqueIdentifier>{cd33a41f-6151-46a5-95b6-b79022786144}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\package_bgs\AdaptiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\FrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\GMG.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV1BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\MixtureOfGaussianV2BGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\StaticFrameDifferenceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingMeanBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\WeightedMovingVarianceBGS.cpp"> - <Filter>Header Files\package_bgs</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KDE.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\KernelTable.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGmodel.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ae\NPBGSubtractor.cpp"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackground.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\TBackgroundVuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\av\VuMeter.cpp"> - <Filter>Header Files\package_bgs\av</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\imbs.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\db\IndependentMultimodalBGS.cpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\AdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPAdaptiveMedianBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPEigenbackgroundBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPGrimsonGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPMeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPPratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPTextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPWrenGABGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\DPZivkovicAGMMBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Eigenbackground.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Error.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\GrimsonGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\Image.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\MeanBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\PratiMediodBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\TextureBGS.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\WrenGA.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\dp\ZivkovicAGMM.cpp"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\blob.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobExtraction.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\BlobResult.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\CMultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\LocalBinaryPattern.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\jmo\MultiLayerBGS.cpp"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModel.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzyGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelFuzzySom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelGauss.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelMog.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\BGModelSom.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBFuzzyGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBMixtureOfGaussians.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\lb\LBSimpleGaussian.cpp"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\sjn\SJN_MultiCueBGS.cpp"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyChoquetIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzySugenoIntegral.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\FuzzyUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\MRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PerformanceUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\PixelUtils.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FGMM_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UM.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\tb\T2FMRF_UV.cpp"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClCompile> - <ClCompile Include="..\FrameProcessor.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\Main.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\PreProcessor.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\VideoAnalysis.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\VideoCapture.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\Demo.cpp"> - <Filter>Source Files\demo</Filter> - </ClCompile> - <ClCompile Include="..\package_analysis\ForegroundMaskAnalysis.cpp"> - <Filter>Header Files\package_analysis</Filter> - </ClCompile> - <ClCompile Include="..\Demo2.cpp"> - <Filter>Source Files\demo</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\SigmaDeltaBGS.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\bl\sdLaMa091.cpp"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\graph.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\LbpMrf.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\maxflow.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEDefs.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEHistogram.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MEImage.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\ck\MotionDetection.cpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LBSP.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\LOBSTER.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - <ClCompile Include="..\package_bgs\pl\SuBSENSE.cpp"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\package_bgs\AdaptiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\AdaptiveSelectiveBackgroundLearning.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\FrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\GMG.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\IBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV1BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\MixtureOfGaussianV2BGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\StaticFrameDifferenceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingMeanBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\WeightedMovingVarianceBGS.h"> - <Filter>Header Files\package_bgs</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KDE.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\KernelTable.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGmodel.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ae\NPBGSubtractor.h"> - <Filter>Header Files\package_bgs\ae</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackground.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\TBackgroundVuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\av\VuMeter.h"> - <Filter>Header Files\package_bgs\av</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\imbs.hpp"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\db\IndependentMultimodalBGS.h"> - <Filter>Header Files\package_bgs\db</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\AdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Bgs.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\BgsParams.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPAdaptiveMedianBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPEigenbackgroundBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPGrimsonGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPMeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPPratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPTextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPWrenGABGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\DPZivkovicAGMMBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Eigenbackground.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Error.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\GrimsonGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\Image.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\MeanBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\PratiMediodBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\TextureBGS.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\WrenGA.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\dp\ZivkovicAGMM.h"> - <Filter>Header Files\package_bgs\dp</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BackgroundSubtractionAPI.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\blob.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobExtraction.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobLibraryConfiguration.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\BlobResult.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\CMultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\LocalBinaryPattern.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\MultiLayerBGS.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\jmo\OpenCvDataConversion.h"> - <Filter>Header Files\package_bgs\jmo</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModel.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzyGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelFuzzySom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelGauss.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelMog.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\BGModelSom.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyAdaptiveSOM.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBFuzzyGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBMixtureOfGaussians.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\LBSimpleGaussian.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\lb\Types.h"> - <Filter>Header Files\package_bgs\lb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\sjn\SJN_MultiCueBGS.h"> - <Filter>Header Files\package_bgs\sjn</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyChoquetIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzySugenoIntegral.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\FuzzyUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\MRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PerformanceUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\PixelUtils.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FGMM_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UM.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\tb\T2FMRF_UV.h"> - <Filter>Header Files\package_bgs\tb</Filter> - </ClInclude> - <ClInclude Include="..\Config.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\FrameProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\IFrameProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\PreProcessor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\VideoAnalysis.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\VideoCapture.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\package_analysis\ForegroundMaskAnalysis.h"> - <Filter>Header Files\package_analysis</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\sdLaMa091.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\SigmaDeltaBGS.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\bl\stdbool.h"> - <Filter>Header Files\package_bgs\bl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\block.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\graph.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\LbpMrf.h"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEDefs.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEHistogram.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MEImage.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\ck\MotionDetection.hpp"> - <Filter>Header Files\package_bgs\ck</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorLOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\BackgroundSubtractorSuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\DistanceUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LBSP.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\LOBSTER.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\RandUtils.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - <ClInclude Include="..\package_bgs\pl\SuBSENSE.h"> - <Filter>Header Files\package_bgs\pl</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_1ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch1t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_3ch3t.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - <None Include="..\package_bgs\pl\LBSP_16bits_dbcross_s3ch.i"> - <Filter>Header Files\package_bgs\pl</Filter> - </None> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/vs2013/bgslibrary.vcxproj.user b/vs2013/bgslibrary.vcxproj.user deleted file mode 100644 index 02146ba90de0d9e1d260428f869f3a15a1ae1909..0000000000000000000000000000000000000000 --- a/vs2013/bgslibrary.vcxproj.user +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments>-uf=true -fn=dataset/video.avi</LocalDebuggerCommandArguments> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments>-uf=true -fn=dataset/video.avi</LocalDebuggerCommandArguments> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|Win32'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments> - </LocalDebuggerCommandArguments> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo|x64'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments /> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|Win32'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments /> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDemo2|x64'"> - <LocalDebuggerWorkingDirectory>../</LocalDebuggerWorkingDirectory> - <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> - <LocalDebuggerCommandArguments /> - </PropertyGroup> -</Project> \ No newline at end of file diff --git a/vs2013mfc/.gitignore b/vs2013mfc/.gitignore deleted file mode 100644 index fc99052718c029dc8927b7fb705ddc2ad093f0c7..0000000000000000000000000000000000000000 --- a/vs2013mfc/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.exe -*.pdb -*.dll \ No newline at end of file diff --git a/vs2013mfc/config/AdaptiveBackgroundLearning.xml b/vs2013mfc/config/AdaptiveBackgroundLearning.xml deleted file mode 100644 index 313e1d4ed8e2e952599137b18753bf15811d2ec9..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/AdaptiveBackgroundLearning.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<alpha>5.0000000000000003e-002</alpha> -<limit>-1</limit> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showForeground>0</showForeground> -<showBackground>0</showBackground> -</opencv_storage> diff --git a/vs2013mfc/config/AdaptiveSelectiveBackgroundLearning.xml b/vs2013mfc/config/AdaptiveSelectiveBackgroundLearning.xml deleted file mode 100644 index f175558a53932aac23393b3dd71588289a0f8ee4..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/AdaptiveSelectiveBackgroundLearning.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<learningFrames>90</learningFrames> -<alphaLearn>5.0000000000000003e-002</alphaLearn> -<alphaDetection>5.0000000000000003e-002</alphaDetection> -<threshold>25</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPAdaptiveMedianBGS.xml b/vs2013mfc/config/DPAdaptiveMedianBGS.xml deleted file mode 100644 index 8d09e859cf6b75c2a5432515ad56c2d87b558c8f..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPAdaptiveMedianBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>40</threshold> -<samplingRate>7</samplingRate> -<learningFrames>30</learningFrames> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPEigenbackgroundBGS.xml b/vs2013mfc/config/DPEigenbackgroundBGS.xml deleted file mode 100644 index d610426deba5bf4cc874695b1498b63390e0edf8..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPEigenbackgroundBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>225</threshold> -<historySize>20</historySize> -<embeddedDim>10</embeddedDim> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPGrimsonGMMBGS.xml b/vs2013mfc/config/DPGrimsonGMMBGS.xml deleted file mode 100644 index 8ade44f22824afdef676e1a7e80c93ffba82ac98..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPGrimsonGMMBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>9.</threshold> -<alpha>1.0000000000000000e-002</alpha> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPMeanBGS.xml b/vs2013mfc/config/DPMeanBGS.xml deleted file mode 100644 index 9bd59a84a2fc903366207bea2023eb0af22e30bb..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPMeanBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>2700</threshold> -<alpha>9.9999999747524271e-007</alpha> -<learningFrames>30</learningFrames> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPPratiMediodBGS.xml b/vs2013mfc/config/DPPratiMediodBGS.xml deleted file mode 100644 index fdf20b4efdecf362ef6de51abb5246ac60d59166..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPPratiMediodBGS.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>30</threshold> -<samplingRate>5</samplingRate> -<historySize>16</historySize> -<weight>5</weight> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPTextureBGS.xml b/vs2013mfc/config/DPTextureBGS.xml deleted file mode 100644 index 0d63e78ca0ddbea78b29206d4e652e0f3398b3c0..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPTextureBGS.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPWrenGABGS.xml b/vs2013mfc/config/DPWrenGABGS.xml deleted file mode 100644 index 7eaa78ba47d02d4547ca1d3af118417e857f8048..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPWrenGABGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>1.2250000000000000e+001</threshold> -<alpha>4.9999998882412910e-003</alpha> -<learningFrames>30</learningFrames> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/DPZivkovicAGMMBGS.xml b/vs2013mfc/config/DPZivkovicAGMMBGS.xml deleted file mode 100644 index 98ee82aaf9cd25da3cc38e2747da86db4822d9f2..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/DPZivkovicAGMMBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>25.</threshold> -<alpha>1.0000000474974513e-003</alpha> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/FrameDifferenceBGS.xml b/vs2013mfc/config/FrameDifferenceBGS.xml deleted file mode 100644 index 943a6c91f4eb5c48a786cd59ee1b73456090d365..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/FrameDifferenceBGS.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/FuzzyChoquetIntegral.xml b/vs2013mfc/config/FuzzyChoquetIntegral.xml deleted file mode 100644 index 22074aa90bffddb80527f40cbf4406b41ff47a48..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/FuzzyChoquetIntegral.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<showOutput>0</showOutput> -<framesToLearn>10</framesToLearn> -<alphaLearn>1.0000000000000001e-001</alphaLearn> -<alphaUpdate>1.0000000000000000e-002</alphaUpdate> -<colorSpace>1</colorSpace> -<option>2</option> -<smooth>1</smooth> -<threshold>6.7000000000000004e-001</threshold> -</opencv_storage> diff --git a/vs2013mfc/config/FuzzySugenoIntegral.xml b/vs2013mfc/config/FuzzySugenoIntegral.xml deleted file mode 100644 index 22074aa90bffddb80527f40cbf4406b41ff47a48..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/FuzzySugenoIntegral.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<showOutput>0</showOutput> -<framesToLearn>10</framesToLearn> -<alphaLearn>1.0000000000000001e-001</alphaLearn> -<alphaUpdate>1.0000000000000000e-002</alphaUpdate> -<colorSpace>1</colorSpace> -<option>2</option> -<smooth>1</smooth> -<threshold>6.7000000000000004e-001</threshold> -</opencv_storage> diff --git a/vs2013mfc/config/GMG.xml b/vs2013mfc/config/GMG.xml deleted file mode 100644 index e3ebdc736e92d8f096ffaacb9b491b111e353ebf..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/GMG.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<initializationFrames>20</initializationFrames> -<decisionThreshold>6.9999999999999996e-001</decisionThreshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/IndependentMultimodalBGS.xml b/vs2013mfc/config/IndependentMultimodalBGS.xml deleted file mode 100644 index 0d63e78ca0ddbea78b29206d4e652e0f3398b3c0..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/IndependentMultimodalBGS.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/KDE.xml b/vs2013mfc/config/KDE.xml deleted file mode 100644 index c9b74025011e4f19d1752e8955c3b6ae0cf0f30a..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/KDE.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<framesToLearn>10</framesToLearn> -<SequenceLength>50</SequenceLength> -<TimeWindowSize>100</TimeWindowSize> -<SDEstimationFlag>1</SDEstimationFlag> -<lUseColorRatiosFlag>1</lUseColorRatiosFlag> -<th>9.9999999999999995e-008</th> -<alpha>2.9999999999999999e-001</alpha> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LBAdaptiveSOM.xml b/vs2013mfc/config/LBAdaptiveSOM.xml deleted file mode 100644 index 94b257021cfcf7c730ed2af03281086623339fb2..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LBAdaptiveSOM.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<sensitivity>75</sensitivity> -<trainingSensitivity>245</trainingSensitivity> -<learningRate>62</learningRate> -<trainingLearningRate>255</trainingLearningRate> -<trainingSteps>55</trainingSteps> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LBFuzzyAdaptiveSOM.xml b/vs2013mfc/config/LBFuzzyAdaptiveSOM.xml deleted file mode 100644 index 7168563f6a032ac019e3facff2bf5b34bda5a779..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LBFuzzyAdaptiveSOM.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<sensitivity>90</sensitivity> -<trainingSensitivity>240</trainingSensitivity> -<learningRate>38</learningRate> -<trainingLearningRate>255</trainingLearningRate> -<trainingSteps>81</trainingSteps> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LBFuzzyGaussian.xml b/vs2013mfc/config/LBFuzzyGaussian.xml deleted file mode 100644 index 18635a1248e632d25f4d623c7e011a71d18ac74d..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LBFuzzyGaussian.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<sensitivity>72</sensitivity> -<bgThreshold>162</bgThreshold> -<learningRate>49</learningRate> -<noiseVariance>195</noiseVariance> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LBMixtureOfGaussians.xml b/vs2013mfc/config/LBMixtureOfGaussians.xml deleted file mode 100644 index 22737201df64764ae51248cfb40eef752bb36500..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LBMixtureOfGaussians.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<sensitivity>81</sensitivity> -<bgThreshold>83</bgThreshold> -<learningRate>59</learningRate> -<noiseVariance>206</noiseVariance> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LBSimpleGaussian.xml b/vs2013mfc/config/LBSimpleGaussian.xml deleted file mode 100644 index a803f3f120523af3bbe4fa721bff4a645148ef73..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LBSimpleGaussian.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<sensitivity>66</sensitivity> -<noiseVariance>162</noiseVariance> -<learningRate>18</learningRate> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/LOBSTERBGS.xml b/vs2013mfc/config/LOBSTERBGS.xml deleted file mode 100644 index c17b5510fc48a0142fe8bf2c4afad7024d78625f..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/LOBSTERBGS.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<fRelLBSPThreshold>3.6500000953674316e-001</fRelLBSPThreshold> -<nLBSPThresholdOffset>0</nLBSPThresholdOffset> -<nDescDistThreshold>4</nDescDistThreshold> -<nColorDistThreshold>30</nColorDistThreshold> -<nBGSamples>35</nBGSamples> -<nRequiredBGSamples>2</nRequiredBGSamples> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/MixtureOfGaussianV1BGS.xml b/vs2013mfc/config/MixtureOfGaussianV1BGS.xml deleted file mode 100644 index 1e09ceb40082f60946afc3cb09e7ad6189af2e09..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/MixtureOfGaussianV1BGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<alpha>5.0000000000000003e-002</alpha> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/MixtureOfGaussianV2BGS.xml b/vs2013mfc/config/MixtureOfGaussianV2BGS.xml deleted file mode 100644 index 1e09ceb40082f60946afc3cb09e7ad6189af2e09..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/MixtureOfGaussianV2BGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<alpha>5.0000000000000003e-002</alpha> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/MultiCueBGS.xml b/vs2013mfc/config/MultiCueBGS.xml deleted file mode 100644 index 0d63e78ca0ddbea78b29206d4e652e0f3398b3c0..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/MultiCueBGS.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/MultiLayerBGS.xml b/vs2013mfc/config/MultiLayerBGS.xml deleted file mode 100644 index 9b803db7ec73435625fb1fc3f0f5458f77b71a11..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/MultiLayerBGS.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<preloadModel>"./models/MultiLayerBGSModel.yml"</preloadModel> -<saveModel>0</saveModel> -<detectAfter>0</detectAfter> -<disableDetectMode>1</disableDetectMode> -<disableLearningInDetecMode>0</disableLearningInDetecMode> -<loadDefaultParams>1</loadDefaultParams> -<max_mode_num>5</max_mode_num> -<weight_updating_constant>5.</weight_updating_constant> -<texture_weight>5.0000000000000000e-001</texture_weight> -<bg_mode_percent>6.0000002384185791e-001</bg_mode_percent> -<pattern_neig_half_size>4</pattern_neig_half_size> -<pattern_neig_gaus_sigma>3.</pattern_neig_gaus_sigma> -<bg_prob_threshold>2.0000000298023224e-001</bg_prob_threshold> -<bg_prob_updating_threshold>2.0000000298023224e-001</bg_prob_updating_threshold> -<robust_LBP_constant>3</robust_LBP_constant> -<min_noised_angle>1.7453293502330780e-001</min_noised_angle> -<shadow_rate>6.0000002384185791e-001</shadow_rate> -<highlight_rate>1.2000000476837158e+000</highlight_rate> -<bilater_filter_sigma_s>3.</bilater_filter_sigma_s> -<bilater_filter_sigma_r>1.0000000149011612e-001</bilater_filter_sigma_r> -<frame_duration>1.0000000149011612e-001</frame_duration> -<learn_mode_learn_rate_per_second>5.0000000000000000e-001</learn_mode_learn_rate_per_second> -<learn_weight_learn_rate_per_second>5.0000000000000000e-001</learn_weight_learn_rate_per_second> -<learn_init_mode_weight>5.0000000745058060e-002</learn_init_mode_weight> -<detect_mode_learn_rate_per_second>9.9999997764825821e-003</detect_mode_learn_rate_per_second> -<detect_weight_learn_rate_per_second>9.9999997764825821e-003</detect_weight_learn_rate_per_second> -<detect_init_mode_weight>1.0000000474974513e-003</detect_init_mode_weight> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/SigmaDeltaBGS.xml b/vs2013mfc/config/SigmaDeltaBGS.xml deleted file mode 100644 index f1b2b2f54d8a9dd555297315cbb96217efb2d533..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/SigmaDeltaBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<ampFactor>1</ampFactor> -<minVar>15</minVar> -<maxVar>255</maxVar> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/StaticFrameDifferenceBGS.xml b/vs2013mfc/config/StaticFrameDifferenceBGS.xml deleted file mode 100644 index 943a6c91f4eb5c48a786cd59ee1b73456090d365..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/StaticFrameDifferenceBGS.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/SuBSENSEBGS.xml b/vs2013mfc/config/SuBSENSEBGS.xml deleted file mode 100644 index 05509c15a8c0cf70db253d9ad5a90f3bfe819942..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/SuBSENSEBGS.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<fRelLBSPThreshold>3.3300000429153442e-001</fRelLBSPThreshold> -<nDescDistThresholdOffset>3</nDescDistThresholdOffset> -<nMinColorDistThreshold>30</nMinColorDistThreshold> -<nBGSamples>50</nBGSamples> -<nRequiredBGSamples>2</nRequiredBGSamples> -<nSamplesForMovingAvgs>100</nSamplesForMovingAvgs> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/T2FGMM_UM.xml b/vs2013mfc/config/T2FGMM_UM.xml deleted file mode 100644 index d2f1054e0517b8df10af55e715c94e9add632edc..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/T2FGMM_UM.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>9.</threshold> -<alpha>1.0000000000000000e-002</alpha> -<km>1.5000000000000000e+000</km> -<kv>6.0000002384185791e-001</kv> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/T2FGMM_UV.xml b/vs2013mfc/config/T2FGMM_UV.xml deleted file mode 100644 index d2f1054e0517b8df10af55e715c94e9add632edc..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/T2FGMM_UV.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>9.</threshold> -<alpha>1.0000000000000000e-002</alpha> -<km>1.5000000000000000e+000</km> -<kv>6.0000002384185791e-001</kv> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/T2FMRF_UM.xml b/vs2013mfc/config/T2FMRF_UM.xml deleted file mode 100644 index 9a65c57ca90f63d5223752d84191c7e439ff8882..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/T2FMRF_UM.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>9.</threshold> -<alpha>1.0000000000000000e-002</alpha> -<km>2.</km> -<kv>8.9999997615814209e-001</kv> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/T2FMRF_UV.xml b/vs2013mfc/config/T2FMRF_UV.xml deleted file mode 100644 index 9a65c57ca90f63d5223752d84191c7e439ff8882..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/T2FMRF_UV.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<threshold>9.</threshold> -<alpha>1.0000000000000000e-002</alpha> -<km>2.</km> -<kv>8.9999997615814209e-001</kv> -<gaussians>3</gaussians> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/VuMeter.xml b/vs2013mfc/config/VuMeter.xml deleted file mode 100644 index d28fda7ae34e3840df1b0695eea314fd7078756b..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/VuMeter.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<enableFilter>1</enableFilter> -<binSize>8</binSize> -<alpha>9.9500000000000000e-001</alpha> -<threshold>2.9999999999999999e-002</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/config/WeightedMovingMeanBGS.xml b/vs2013mfc/config/WeightedMovingMeanBGS.xml deleted file mode 100644 index 008ad741b9f0d140beac4eea74daf2c397b70a3c..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/WeightedMovingMeanBGS.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<enableWeight>1</enableWeight> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -<showBackground>0</showBackground> -</opencv_storage> diff --git a/vs2013mfc/config/WeightedMovingVarianceBGS.xml b/vs2013mfc/config/WeightedMovingVarianceBGS.xml deleted file mode 100644 index d9de1d4f8cd0978018e56d86f536a85ed8e98435..0000000000000000000000000000000000000000 --- a/vs2013mfc/config/WeightedMovingVarianceBGS.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<opencv_storage> -<enableWeight>1</enableWeight> -<enableThreshold>1</enableThreshold> -<threshold>15</threshold> -<showOutput>0</showOutput> -</opencv_storage> diff --git a/vs2013mfc/dataset/video.avi b/vs2013mfc/dataset/video.avi deleted file mode 100644 index a29f00658be7d05b10344859e6bee9a501a7a2b1..0000000000000000000000000000000000000000 Binary files a/vs2013mfc/dataset/video.avi and /dev/null differ diff --git a/vs2013mfc/src/.gitignore b/vs2013mfc/src/.gitignore deleted file mode 100644 index 4ad092eb1e2981311d46fee0774589cf43dcb17a..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -Release/ -ipch/ -*.exe -*.pdb -*.sdf -*.opensdf \ No newline at end of file diff --git a/vs2013mfc/src/App.cpp b/vs2013mfc/src/App.cpp deleted file mode 100644 index a6f45c78da8e675b92213074239b23c9907a1738..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/App.cpp +++ /dev/null @@ -1,94 +0,0 @@ - -// App.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "App.h" -#include "Dlg.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CApp - -BEGIN_MESSAGE_MAP(CApp, CWinApp) - ON_COMMAND(ID_HELP, &CWinApp::OnHelp) -END_MESSAGE_MAP() - - -// CApp construction - -CApp::CApp() -{ - // support Restart Manager - m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; - - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - - -// The one and only CApp object - -CApp theApp; - - -// CApp initialization - -BOOL CApp::InitInstance() -{ - // InitCommonControlsEx() is required on Windows XP if an application - // manifest specifies use of ComCtl32.dll version 6 or later to enable - // visual styles. Otherwise, any window creation will fail. - INITCOMMONCONTROLSEX InitCtrls; - InitCtrls.dwSize = sizeof(InitCtrls); - // Set this to include all the common control classes you want to use - // in your application. - InitCtrls.dwICC = ICC_WIN95_CLASSES; - InitCommonControlsEx(&InitCtrls); - - CWinApp::InitInstance(); - - - AfxEnableControlContainer(); - - // Create the shell manager, in case the dialog contains - // any shell tree view or shell list view controls. - CShellManager *pShellManager = new CShellManager; - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need - // Change the registry key under which our settings are stored - // TODO: You should modify this string to be something appropriate - // such as the name of your company or organization - SetRegistryKey(_T("Local AppWizard-Generated Applications")); - - CDlg dlg; - m_pMainWnd = &dlg; - INT_PTR nResponse = dlg.DoModal(); - if (nResponse == IDOK) - { - // TODO: Place code here to handle when the dialog is - // dismissed with OK - } - else if (nResponse == IDCANCEL) - { - // TODO: Place code here to handle when the dialog is - // dismissed with Cancel - } - - // Delete the shell manager created above. - if (pShellManager != NULL) - { - delete pShellManager; - } - - // Since the dialog has been closed, return FALSE so that we exit the - // application, rather than start the application's message pump. - return FALSE; -} - diff --git a/vs2013mfc/src/App.h b/vs2013mfc/src/App.h deleted file mode 100644 index 5ef9764a331791f71d688154f7af484024a9ca7f..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/App.h +++ /dev/null @@ -1,32 +0,0 @@ - -// App.h : main header file for the application -// - -#pragma once - -#ifndef __AFXWIN_H__ - #error "include 'stdafx.h' before including this file for PCH" -#endif - -#include "resource.h" // main symbols - - -// CApp: -// See App.cpp for the implementation of this class -// - -class CApp : public CWinApp -{ -public: - CApp(); - -// Overrides -public: - virtual BOOL InitInstance(); - -// Implementation - - DECLARE_MESSAGE_MAP() -}; - -extern CApp theApp; \ No newline at end of file diff --git a/vs2013mfc/src/Dlg.cpp b/vs2013mfc/src/Dlg.cpp deleted file mode 100644 index f39249eb3c7c450e55cb335666b94e7f910928e2..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/Dlg.cpp +++ /dev/null @@ -1,709 +0,0 @@ - -// Dlg.cpp : implementation file -// - -#include "stdafx.h" -#include "App.h" -#include "Dlg.h" -#include "afxdialogex.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialogEx -{ -public: - CAboutDlg(); - -// Dialog Data - enum { IDD = IDD_ABOUTBOX }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - -// Implementation -protected: - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) -{ -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialogEx::DoDataExchange(pDX); -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) -END_MESSAGE_MAP() - - -// CDlg dialog - - - - -CDlg::CDlg(CWnd* pParent /*=NULL*/) - : CDialogEx(CDlg::IDD, pParent) -{ - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); -} - -void CDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialogEx::DoDataExchange(pDX); - DDX_Control(pDX, IDC_COMBO_BGSLIST, m_bgslist); - DDX_Control(pDX, IDC_LOG, m_log); - DDX_Control(pDX, IDC_INPUT_VIDEO, m_inputVideo); - DDX_Control(pDX, IDC_USE_WEBCAM, m_useWebCam); - DDX_Control(pDX, IDC_SPIN_WEBCAM_INDEX, m_spinWebCamIndex); - DDX_Control(pDX, IDC_EDIT_WEBCAM_INDEX, m_webCamIndex); - DDX_Control(pDX, IDC_FRAME_NUMBER, m_frameNumber); - DDX_Control(pDX, IDC_SAVE_FRAME, m_saveFrame); - DDX_Control(pDX, IDC_SAVE_MASK, m_saveMask); - DDX_Control(pDX, IDC_SAVE_BKG, m_saveBkg); - DDX_Control(pDX, IDC_IMG_SEQ, m_isImgSeq); - DDX_Control(pDX, IDC_EDIT_START_IDX, m_startIdx); - DDX_Control(pDX, IDC_EDIT_STOP_IDX, m_stopIdx); - DDX_Control(pDX, IDC_COMBO_FILE_TYPE, m_fileTypeList); - DDX_Control(pDX, IDC_SPIN_START_IDX, m_spinStartIdx); - DDX_Control(pDX, IDC_SPIN_STOP_IDX, m_spinStopIdx); - DDX_Control(pDX, IDC_EDIT_DELAY, m_delay); - DDX_Control(pDX, IDC_EXEC_TIME, m_execTime); - DDX_Control(pDX, IDC_MEDIAN_FILTER, m_medianFilter); -} - -BEGIN_MESSAGE_MAP(CDlg, CDialogEx) - ON_WM_SYSCOMMAND() - ON_WM_PAINT() - ON_WM_QUERYDRAGICON() - ON_BN_CLICKED(IDSTART, &CDlg::OnBnClickedStart) - ON_BN_CLICKED(IDSTOP, &CDlg::OnBnClickedStop) - ON_BN_CLICKED(IDC_USE_WEBCAM, &CDlg::OnBnClickedUseWebcam) - ON_BN_CLICKED(IDC_IMG_SEQ, &CDlg::OnBnClickedImgSeq) - ON_BN_CLICKED(IDSAVE, &CDlg::OnBnClickedSave) -END_MESSAGE_MAP() - - -// CDlg message handlers - -BOOL CDlg::OnInitDialog() -{ - CDialogEx::OnInitDialog(); - - // Add "About..." menu item to system menu. - - // IDM_ABOUTBOX must be in the system command range. - ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); - ASSERT(IDM_ABOUTBOX < 0xF000); - - CMenu* pSysMenu = GetSystemMenu(FALSE); - if (pSysMenu != NULL) - { - BOOL bNameValid; - CString strAboutMenu; - bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); - ASSERT(bNameValid); - if (!strAboutMenu.IsEmpty()) - { - pSysMenu->AppendMenu(MF_SEPARATOR); - pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); - } - } - - // Set the icon for this dialog. The framework does this automatically - // when the application's main window is not a dialog - SetIcon(m_hIcon, TRUE); // Set big icon - SetIcon(m_hIcon, FALSE); // Set small icon - - // TODO: Add extra initialization here - methodName = L""; - useWebCam = false; - useImgSeq = false; - filePath = L""; - bgs = NULL; - webCamIndex = 0; - m_spinWebCamIndex.SetRange(0, 9); - m_spinStartIdx.SetRange(0, 999999); - m_spinStopIdx.SetRange(0, 999999); - m_frameNumber.SetWindowTextW(L"0"); - - addBgsList(); - m_fileTypeList.AddString(L"PNG"); - m_fileTypeList.AddString(L"JPG"); - m_fileTypeList.AddString(L"JPEG"); - m_fileTypeList.AddString(L"JPE"); - m_fileTypeList.AddString(L"JP2"); - m_fileTypeList.AddString(L"BMP"); - m_fileTypeList.AddString(L"DIB"); - m_fileTypeList.AddString(L"PBM"); - m_fileTypeList.AddString(L"PGM"); - m_fileTypeList.AddString(L"PPM"); - m_fileTypeList.AddString(L"SR"); - m_fileTypeList.AddString(L"RAS"); - m_fileTypeList.AddString(L"TIFF"); - m_fileTypeList.AddString(L"TIF"); - m_fileTypeList.SelectString(0,L"PNG"); - m_inputVideo.SetWindowTextW(L"dataset/video.avi"); - m_delay.SetWindowTextW(L"1"); - m_execTime.SetWindowTextW(L"0"); - - started = false; - if(started == false) - { - cv::namedWindow("INPUT", 1); - HWND hWnd = (HWND) cvGetWindowHandle("INPUT"); - HWND hParent = ::GetParent(hWnd); - ::SetParent(hWnd, GetDlgItem(IDC_FRAME_INPUT)->m_hWnd); - ::ShowWindow(hParent, SW_HIDE); - } - - if(started == false) - { - cv::namedWindow("MASK", 1); - HWND hWnd = (HWND) cvGetWindowHandle("MASK"); - HWND hParent = ::GetParent(hWnd); - ::SetParent(hWnd, GetDlgItem(IDC_FRAME_MASK)->m_hWnd); - ::ShowWindow(hParent, SW_HIDE); - } - - if(started == false) - { - cv::namedWindow("BKG", 1); - HWND hWnd = (HWND) cvGetWindowHandle("BKG"); - HWND hParent = ::GetParent(hWnd); - ::SetParent(hWnd, GetDlgItem(IDC_FRAME_BKG)->m_hWnd); - ::ShowWindow(hParent, SW_HIDE); - } - - return TRUE; // return TRUE unless you set the focus to a control -} - -void CDlg::OnSysCommand(UINT nID, LPARAM lParam) -{ - if ((nID & 0xFFF0) == IDM_ABOUTBOX) - { - CAboutDlg dlgAbout; - dlgAbout.DoModal(); - } - else - { - CDialogEx::OnSysCommand(nID, lParam); - } -} - -// If you add a minimize button to your dialog, you will need the code below -// to draw the icon. For MFC applications using the document/view model, -// this is automatically done for you by the framework. - -void CDlg::OnPaint() -{ - if (IsIconic()) - { - CPaintDC dc(this); // device context for painting - - SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); - - // Center icon in client rectangle - int cxIcon = GetSystemMetrics(SM_CXICON); - int cyIcon = GetSystemMetrics(SM_CYICON); - CRect rect; - GetClientRect(&rect); - int x = (rect.Width() - cxIcon + 1) / 2; - int y = (rect.Height() - cyIcon + 1) / 2; - - // Draw the icon - dc.DrawIcon(x, y, m_hIcon); - } - else - { - CDialogEx::OnPaint(); - } -} - -// The system calls this function to obtain the cursor to display while the user drags -// the minimized window. -HCURSOR CDlg::OnQueryDragIcon() -{ - return static_cast<HCURSOR>(m_hIcon); -} - -void CDlg::addBgsList() -{ - // 37 algorithms - m_bgslist.AddString(L"FrameDifferenceBGS"); - m_bgslist.AddString(L"StaticFrameDifferenceBGS"); - m_bgslist.AddString(L"WeightedMovingMeanBGS"); - m_bgslist.AddString(L"WeightedMovingVarianceBGS"); - m_bgslist.AddString(L"MixtureOfGaussianV1BGS"); - m_bgslist.AddString(L"MixtureOfGaussianV2BGS"); - m_bgslist.AddString(L"AdaptiveBackgroundLearning"); - m_bgslist.AddString(L"AdaptiveSelectiveBackgroundLearning"); - m_bgslist.AddString(L"GMG"); - m_bgslist.AddString(L"DPAdaptiveMedianBGS"); - m_bgslist.AddString(L"DPGrimsonGMMBGS"); - m_bgslist.AddString(L"DPZivkovicAGMMBGS"); - m_bgslist.AddString(L"DPMeanBGS"); - m_bgslist.AddString(L"DPWrenGABGS"); - m_bgslist.AddString(L"DPPratiMediodBGS"); - m_bgslist.AddString(L"DPEigenbackgroundBGS"); - m_bgslist.AddString(L"DPTextureBGS"); - m_bgslist.AddString(L"T2FGMM_UM"); - m_bgslist.AddString(L"T2FGMM_UV"); - m_bgslist.AddString(L"T2FMRF_UM"); - m_bgslist.AddString(L"T2FMRF_UV"); - m_bgslist.AddString(L"FuzzySugenoIntegral"); - m_bgslist.AddString(L"FuzzyChoquetIntegral"); - m_bgslist.AddString(L"LBSimpleGaussian"); - m_bgslist.AddString(L"LBFuzzyGaussian"); - m_bgslist.AddString(L"LBMixtureOfGaussians"); - m_bgslist.AddString(L"LBAdaptiveSOM"); - m_bgslist.AddString(L"LBFuzzyAdaptiveSOM"); - m_bgslist.AddString(L"MultiLayerBGS"); - //m_bgslist.AddString(L"PBAS"); - m_bgslist.AddString(L"VuMeter"); - m_bgslist.AddString(L"KDE"); - m_bgslist.AddString(L"IndependentMultimodalBGS"); - m_bgslist.AddString(L"SJN_MultiCueBGS"); - m_bgslist.AddString(L"SigmaDeltaBGS"); - m_bgslist.AddString(L"SuBSENSEBGS"); - m_bgslist.AddString(L"LOBSTERBGS"); -} - -bool CDlg::getBgsMethodName() -{ - int nIndex = m_bgslist.GetCurSel(); - if(nIndex != CB_ERR) - { - m_bgslist.GetLBText(nIndex, methodName); - return true; - } - else - { - AfxMessageBox(L"Please, select one background subtraction method!"); - return false; - } -} - -bool CDlg::getFileType() -{ - int nIndex = m_fileTypeList.GetCurSel(); - if(nIndex != CB_ERR) - { - m_fileTypeList.GetLBText(nIndex, fileType); - return true; - } - else - { - AfxMessageBox(L"Please, select one file type or extension!"); - return false; - } -} - -bool CDlg::getInputVideoFilePath() -{ - m_inputVideo.GetWindowTextW(filePath); - - if(filePath.GetLength() > 0) - return true; - else - { - AfxMessageBox(L"Please, select one video file or image sequence folder!"); - return false; - } -} - -void CDlg::OnBnClickedStart() -{ - if(started == false) - { - m_log.SetWindowTextW(L"Checking..."); - - if(!getBgsMethodName()) - { - m_log.SetWindowTextW(L"Stopped..."); - return; - } - - useWebCam = false; - if(m_useWebCam.GetCheck() == BST_CHECKED) - useWebCam = true; - - useImgSeq = false; - if(m_isImgSeq.GetCheck() == BST_CHECKED) - { - useImgSeq = true; - - if(!getFileType()) - { - m_log.SetWindowTextW(L"Stopped..."); - return; - } - } - - if(useWebCam == false) - if(!getInputVideoFilePath()) - { - m_log.SetWindowTextW(L"Stopped..."); - return; - } - - m_log.SetWindowTextW(L"Starting..."); - thread = AfxBeginThread((AFX_THREADPROC) CDlg::Thread, (LPVOID) this); - } - else - { - AfxMessageBox(L"Thread is already initialized!"); - return; - } -} - -DWORD CDlg::Thread(LPVOID *lpvParam) -{ - CDlg *thr = (CDlg*) lpvParam; - thr->ThreadProcess(); - return NULL; -} - -void CDlg::ThreadProcess() -{ - CString csStartIdx; - m_startIdx.GetWindowTextW(csStartIdx); - startIdx = _tstoi(csStartIdx); - - CString csStopIdx; - m_stopIdx.GetWindowTextW(csStopIdx); - stopIdx = _tstoi(csStopIdx); - - if(useImgSeq == false) - { - if(useWebCam) - { - CString strIndex; - m_webCamIndex.GetWindowTextW(strIndex); - webCamIndex = _tstoi(strIndex); - capture = cvCaptureFromCAM(webCamIndex); - } - else - { - CStringA file_path_aux(filePath); - capture = cvCaptureFromFile((const char *) file_path_aux); - } - - if(!capture) - { - AfxMessageBox(L"ERROR: Cannot initialize video!"); - m_log.SetWindowTextW(L"Stopped..."); - return; - } - } - else - { - if(stopIdx == 0) - { - AfxMessageBox(L"Stop index not defined!"); - return; - } - - if(startIdx > stopIdx) - { - AfxMessageBox(L"Start index is higher than stop index!"); - return; - } - } - - /* Background Subtraction Methods */ - - if(methodName == "FrameDifferenceBGS") - bgs = new FrameDifferenceBGS; - if(methodName == "StaticFrameDifferenceBGS") - bgs = new StaticFrameDifferenceBGS; - if(methodName == "WeightedMovingMeanBGS") - bgs = new WeightedMovingMeanBGS; - if(methodName == "WeightedMovingVarianceBGS") - bgs = new WeightedMovingVarianceBGS; - if(methodName == "MixtureOfGaussianV1BGS") - bgs = new MixtureOfGaussianV1BGS; - if(methodName == "MixtureOfGaussianV2BGS") - bgs = new MixtureOfGaussianV2BGS; - if(methodName == "AdaptiveBackgroundLearning") - bgs = new AdaptiveBackgroundLearning; - if(methodName == "AdaptiveSelectiveBackgroundLearning") - bgs = new AdaptiveSelectiveBackgroundLearning; - if(methodName == "GMG") - bgs = new GMG; - - if(methodName == "DPAdaptiveMedianBGS") - bgs = new DPAdaptiveMedianBGS; - if(methodName == "DPGrimsonGMMBGS") - bgs = new DPGrimsonGMMBGS; - if(methodName == "DPZivkovicAGMMBGS") - bgs = new DPZivkovicAGMMBGS; - if(methodName == "DPMeanBGS") - bgs = new DPMeanBGS; - if(methodName == "DPWrenGABGS") - bgs = new DPWrenGABGS; - if(methodName == "DPPratiMediodBGS") - bgs = new DPPratiMediodBGS; - if(methodName == "DPEigenbackgroundBGS") - bgs = new DPEigenbackgroundBGS; - if(methodName == "DPTextureBGS") - bgs = new DPTextureBGS; - - if(methodName == "T2FGMM_UM") - bgs = new T2FGMM_UM; - if(methodName == "T2FGMM_UV") - bgs = new T2FGMM_UV; - if(methodName == "T2FMRF_UM") - bgs = new T2FMRF_UM; - if(methodName == "T2FMRF_UV") - bgs = new T2FMRF_UV; - if(methodName == "FuzzySugenoIntegral") - bgs = new FuzzySugenoIntegral; - if(methodName == "FuzzyChoquetIntegral") - bgs = new FuzzyChoquetIntegral; - - if(methodName == "LBSimpleGaussian") - bgs = new LBSimpleGaussian; - if(methodName == "LBFuzzyGaussian") - bgs = new LBFuzzyGaussian; - if(methodName == "LBMixtureOfGaussians") - bgs = new LBMixtureOfGaussians; - if(methodName == "LBAdaptiveSOM") - bgs = new LBAdaptiveSOM; - if(methodName == "LBFuzzyAdaptiveSOM") - bgs = new LBFuzzyAdaptiveSOM; - if(methodName == "MultiLayerBGS") - bgs = new MultiLayerBGS; - //if(methodName == "PBAS") - //bgs = new PixelBasedAdaptiveSegmenter; - if(methodName == "VuMeter") - bgs = new VuMeter; - if(methodName == "KDE") - bgs = new KDE; - if(methodName == "IndependentMultimodalBGS") - bgs = new IndependentMultimodalBGS; - if(methodName == "SJN_MultiCueBGS") - bgs = new SJN_MultiCueBGS; - if (methodName == "SigmaDeltaBGS") - bgs = new SigmaDeltaBGS; - if (methodName == "SuBSENSEBGS") - bgs = new SuBSENSEBGS; - if (methodName == "LOBSTERBGS") - bgs = new LOBSTERBGS; - - if(bgs == NULL) - { - AfxMessageBox(L"BGS object not defined!"); - return; - } - - started = true; - int i = 0; - if(useImgSeq == true && startIdx > 0) - i = startIdx - 1; - CString strFrameNumber; - CString strExecTime; - cv::Size default_size; - default_size.width = 235; - default_size.height = 189; - IplImage* frame; - std::string input_filename; - cv::Mat img_input; - // Convert a TCHAR string to a LPCSTR - CT2CA fileType2(fileType); - CT2CA filePath2(filePath); - // construct a std::string using the LPCSTR input - std::string str_fileType(fileType2); - std::string str_filePath(filePath2); - // delay - CString csDelay; - m_delay.GetWindowTextW(csDelay); - int delay = _tstoi(csDelay); - - do - { - m_log.SetWindowTextW(L"Running..."); - - i++; - //::Sleep(1); - - if(useImgSeq == true && i == (stopIdx + 1)) - break; - - if(useImgSeq) - { - input_filename = str_filePath + "\\" + boost::lexical_cast<std::string>(i) + "." + str_fileType; - img_input = cv::imread(input_filename); - - CString input_filename2(input_filename.c_str()); - m_log.SetWindowTextW(input_filename2); - - strFrameNumber.Format(L"%d",i); - m_frameNumber.SetWindowTextW(strFrameNumber); - - if(img_input.data == NULL) - { - AfxMessageBox(L"File can not be read!"); - break; - } - } - else - { - if(useWebCam == false && stopIdx >= 2 && i > stopIdx) - break; - - frame = cvQueryFrame(capture); - if(!frame) - break; - - if(useWebCam == false && startIdx >= 2 && i < startIdx) - continue; - - img_input = cv::Mat(frame,true); - } - - cv::Mat img_mask; - cv::Mat img_bkg; - Clock::time_point t0 = Clock::now(); - bgs->process(img_input, img_mask, img_bkg); - Clock::time_point t1 = Clock::now(); - auto d = boost::chrono::duration_cast<milliseconds>(t1 - t0); - //std::cout << "\nElapsed time: " << d.count() << "ms" << std::endl; - - cv::Mat img_input_aux; - cv::resize(img_input, img_input_aux, default_size); - - cv::Mat img_mask_aux; - if(img_mask.empty()) - img_mask = cv::Mat::zeros(cv::Size(img_input.size().width, img_input.size().height), img_input.type()); - if(m_medianFilter.GetCheck() == BST_CHECKED) - cv::medianBlur(img_mask, img_mask, 5); - cv::resize(img_mask, img_mask_aux, default_size); - - cv::Mat img_bgk_aux; - if(img_bkg.empty()) - img_bkg = cv::Mat::zeros(cv::Size(img_input.size().width, img_input.size().height), img_input.type()); - cv::resize(img_bkg, img_bgk_aux, default_size); - - cv::imshow("INPUT", img_input_aux); - cv::imshow("MASK", img_mask_aux); - cv::imshow("BKG", img_bgk_aux); - - extern_input_filename = "outputs/input/" + boost::lexical_cast<std::string>(i)+".png"; - img_input.copyTo(extern_input_img); - if(m_saveFrame.GetCheck() == BST_CHECKED) - cv::imwrite(extern_input_filename, img_input); - - extern_fg_filename = "outputs/foreground/" + boost::lexical_cast<std::string>(i)+".png"; - img_mask.copyTo(extern_fg_img); - if(m_saveMask.GetCheck() == BST_CHECKED) - cv::imwrite(extern_fg_filename, img_mask); - - extern_bg_filename = "outputs/background/" + boost::lexical_cast<std::string>(i)+".png"; - img_bkg.copyTo(extern_bg_img); - if(m_saveBkg.GetCheck() == BST_CHECKED) - cv::imwrite(extern_bg_filename, img_bkg); - - strFrameNumber.Format(L"%d",i); - m_frameNumber.SetWindowTextW(strFrameNumber); - - //strExecTime.Format(_T("%.2f"), d.count()); - strExecTime.Format(_T("%d"), d.count()); - m_execTime.SetWindowTextW(strExecTime); - - ::Sleep(delay); - - }while(1); - - delete bgs; - - if(!useImgSeq) - cvReleaseCapture(&capture); - - //AfxMessageBox(L"Thread is finished!"); - m_log.SetWindowTextW(L"Finished!"); - started = false; -} - - -void CDlg::OnBnClickedStop() -{ - if(started) - { - m_log.SetWindowTextW(L"Stopping..."); - - StopThread(); - - if(!useImgSeq) - if(capture) - cvReleaseCapture(&capture); - - delete bgs; - bgs = NULL; - - m_log.SetWindowTextW(L"Stopped!"); - started = false; - } -} - -void CDlg::StopThread() -{ - DWORD exit_code = NULL; - - if(thread != NULL) - { - GetExitCodeThread(thread->m_hThread, &exit_code); - - if(exit_code == STILL_ACTIVE) - { - ::TerminateThread(thread->m_hThread, 0); - CloseHandle(thread->m_hThread); - } - - thread->m_hThread = NULL; - thread = NULL; - } -} - -void CDlg::OnBnClickedUseWebcam() -{ - if(m_useWebCam.GetCheck() == BST_CHECKED) - m_isImgSeq.SetCheck(BST_UNCHECKED); - - m_inputVideo.EnableFileBrowseButton(); -} - -void CDlg::OnBnClickedImgSeq() -{ - if(m_isImgSeq.GetCheck() == BST_CHECKED) - { - m_inputVideo.EnableFolderBrowseButton(); - m_useWebCam.SetCheck(BST_UNCHECKED); - } - else - { - m_startIdx.SetWindowTextW(L"0"); - m_stopIdx.SetWindowTextW(L"0"); - m_inputVideo.EnableFileBrowseButton(); - } -} - -void CDlg::OnBnClickedSave() -{ - if(m_saveFrame.GetCheck() == BST_CHECKED) - cv::imwrite(extern_input_filename, extern_input_img); - - if(m_saveMask.GetCheck() == BST_CHECKED) - cv::imwrite(extern_fg_filename, extern_fg_img); - - if(m_saveBkg.GetCheck() == BST_CHECKED) - cv::imwrite(extern_bg_filename, extern_bg_img); - - m_log.SetWindowTextW(L"OK! Saved!"); -} diff --git a/vs2013mfc/src/Dlg.h b/vs2013mfc/src/Dlg.h deleted file mode 100644 index 479d7271be837a490bf17915279e371f41461e85..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/Dlg.h +++ /dev/null @@ -1,92 +0,0 @@ - -// Dlg.h : header file -// - -#pragma once -#include "stdafx.h" -#include "afxwin.h" -#include "afxcmn.h" - -// CDlg dialog -class CDlg : public CDialogEx -{ -// Construction -public: - CDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - enum { IDD = IDD_APP }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - -// Implementation -protected: - HICON m_hIcon; - - // Generated message map functions - virtual BOOL OnInitDialog(); - afx_msg void OnSysCommand(UINT nID, LPARAM lParam); - afx_msg void OnPaint(); - afx_msg HCURSOR OnQueryDragIcon(); - DECLARE_MESSAGE_MAP() - -private: - bool started; - CWinThread* thread; - CvCapture* capture; - IBGS* bgs; - CString methodName; - CString fileType; - bool useWebCam; - bool useImgSeq; - int webCamIndex; - int startIdx; - int stopIdx; - int extern_i; - std::string extern_input_filename; - cv::Mat extern_input_img; - std::string extern_fg_filename; - cv::Mat extern_fg_img; - std::string extern_bg_filename; - cv::Mat extern_bg_img; - - CString filePath; - -public: - afx_msg void ThreadProcess(); - static DWORD Thread(LPVOID *x); - afx_msg void StopThread(); - afx_msg bool ipDraw(HDC hdc, IplImage* img, int xoffset=0, int yoffset=0); - -public: - void addBgsList(); - bool getBgsMethodName(); - CComboBox m_bgslist; - afx_msg void OnBnClickedStart(); - CStatic m_log; - CMFCEditBrowseCtrl m_inputVideo; - bool getInputVideoFilePath(); - CButton m_useWebCam; - afx_msg void OnBnClickedStop(); - CSpinButtonCtrl m_spinWebCamIndex; - CEdit m_webCamIndex; - CStatic m_frameNumber; - CButton m_saveFrame; - CButton m_saveMask; - CButton m_saveBkg; - CButton m_isImgSeq; - CEdit m_startIdx; - CEdit m_stopIdx; - CComboBox m_fileTypeList; - bool getFileType(); - CSpinButtonCtrl m_spinStartIdx; - CSpinButtonCtrl m_spinStopIdx; - afx_msg void OnBnClickedUseWebcam(); - afx_msg void OnBnClickedImgSeq(); - CEdit m_delay; - CStatic m_execTime; - CButton m_medianFilter; - afx_msg void OnBnClickedSave(); -}; diff --git a/vs2013mfc/src/resource.h b/vs2013mfc/src/resource.h deleted file mode 100644 index 606dd8c2eebd167158db80652c82fc50419d8ec6..0000000000000000000000000000000000000000 Binary files a/vs2013mfc/src/resource.h and /dev/null differ diff --git a/vs2013mfc/src/stdafx.cpp b/vs2013mfc/src/stdafx.cpp deleted file mode 100644 index 9e260e7224cab759fbfae5b285437dcdec4e40db..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -// stdafx.cpp : source file that includes just the standard includes -// bgslibrary_vs2010_mfc.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - diff --git a/vs2013mfc/src/stdafx.h b/vs2013mfc/src/stdafx.h deleted file mode 100644 index 4d734a9e557b27d0ff404d1ae85769b66c6e890e..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/stdafx.h +++ /dev/null @@ -1,104 +0,0 @@ - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#ifndef _SECURE_ATL -#define _SECURE_ATL 1 -#endif - -#ifndef VC_EXTRALEAN -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#endif - -#include "targetver.h" - -#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit - -// turns off MFC's hiding of some common and often safely ignored warning messages -#define _AFX_ALL_WARNINGS - -#include <afxwin.h> // MFC core and standard components -#include <afxext.h> // MFC extensions - - -#include <afxdisp.h> // MFC Automation classes - - - -#ifndef _AFX_NO_OLE_SUPPORT -#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls -#endif -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include <afxcmn.h> // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include <afxcontrolbars.h> // MFC support for ribbons and control bars - -#ifdef _UNICODE -#if defined _M_IX86 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_X64 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#else -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -#endif -#endif - -#include <boost/lexical_cast.hpp> -#include <boost/chrono.hpp> -typedef boost::chrono::high_resolution_clock Clock; -typedef boost::chrono::milliseconds milliseconds; -typedef boost::chrono::microseconds microseconds; - -#include <iostream> - -#include <cv.h> -#include <highgui.h> - -// BGSLibrary algorithms - -#include "../../package_bgs/FrameDifferenceBGS.h" -#include "../../package_bgs/StaticFrameDifferenceBGS.h" -#include "../../package_bgs/WeightedMovingMeanBGS.h" -#include "../../package_bgs/WeightedMovingVarianceBGS.h" -#include "../../package_bgs/MixtureOfGaussianV1BGS.h" -#include "../../package_bgs/MixtureOfGaussianV2BGS.h" -#include "../../package_bgs/AdaptiveBackgroundLearning.h" -#include "../../package_bgs/AdaptiveSelectiveBackgroundLearning.h" -#include "../../package_bgs/GMG.h" - -#include "../../package_bgs/dp/DPAdaptiveMedianBGS.h" -#include "../../package_bgs/dp/DPGrimsonGMMBGS.h" -#include "../../package_bgs/dp/DPZivkovicAGMMBGS.h" -#include "../../package_bgs/dp/DPMeanBGS.h" -#include "../../package_bgs/dp/DPWrenGABGS.h" -#include "../../package_bgs/dp/DPPratiMediodBGS.h" -#include "../../package_bgs/dp/DPEigenbackgroundBGS.h" -#include "../../package_bgs/dp/DPTextureBGS.h" - -#include "../../package_bgs/tb/T2FGMM_UM.h" -#include "../../package_bgs/tb/T2FGMM_UV.h" -#include "../../package_bgs/tb/T2FMRF_UM.h" -#include "../../package_bgs/tb/T2FMRF_UV.h" -#include "../../package_bgs/tb/FuzzySugenoIntegral.h" -#include "../../package_bgs/tb/FuzzyChoquetIntegral.h" - -#include "../../package_bgs/lb/LBSimpleGaussian.h" -#include "../../package_bgs/lb/LBFuzzyGaussian.h" -#include "../../package_bgs/lb/LBMixtureOfGaussians.h" -#include "../../package_bgs/lb/LBAdaptiveSOM.h" -#include "../../package_bgs/lb/LBFuzzyAdaptiveSOM.h" - -#include "../../package_bgs/jmo/MultiLayerBGS.h" -//#include "../../package_bgs/pt/PixelBasedAdaptiveSegmenter.h" -#include "../../package_bgs/av/VuMeter.h" -#include "../../package_bgs/ae/KDE.h" -#include "../../package_bgs/db/IndependentMultimodalBGS.h" -#include "../../package_bgs/sjn/SJN_MultiCueBGS.h" -#include "../../package_bgs/bl/SigmaDeltaBGS.h" - -#include "../../package_bgs/pl/SuBSENSE.h" -#include "../../package_bgs/pl/LOBSTER.h" diff --git a/vs2013mfc/src/targetver.h b/vs2013mfc/src/targetver.h deleted file mode 100644 index 87c0086de751bac3d47208b77d76b82d78f26702..0000000000000000000000000000000000000000 --- a/vs2013mfc/src/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include <SDKDDKVer.h> diff --git a/wrapper_matlab/.gitignore b/wrapper_matlab/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..1c363bf8e10adc1abae7940599fcf0292c8ec151 --- /dev/null +++ b/wrapper_matlab/.gitignore @@ -0,0 +1 @@ +*.mex* diff --git a/wrapper_matlab/backgroundSubtractor.m b/wrapper_matlab/backgroundSubtractor.m new file mode 100644 index 0000000000000000000000000000000000000000..e4317664f7d8580f8ce4740dc4b6c51b8835b268 --- /dev/null +++ b/wrapper_matlab/backgroundSubtractor.m @@ -0,0 +1,81 @@ +%{ +/* + * 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) + % creates an object with properties + % + % Properties: + % algorithm - Algorithm name (e.g. "FrameDifference"). + % + % fgMask = getForegroundMask(obj, img) computes foreground mask on + % input image, img, for the object defined by obj. + % + % reset(obj) resets object. + % + % release(obj) releases object memory. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Properties + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + properties + % See the full list of available algorithms in the BGSLibrary website. + algorithm = 'FrameDifference'; + end + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Public methods + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + methods + % Constructor + function obj = backgroundSubtractor(algorithm) + if(nargin > 0) + obj.algorithm = algorithm; + else + obj.algorithm = 'FrameDifference'; + end + disp(['Selected algorithm: ' obj.algorithm]); + params = struct('algorithm', obj.algorithm); + backgroundSubtractor_wrapper('construct', params); + end + + % Get foreground mask and background model + function [fgMask, bgModel] = getForegroundMask(~, img) + [fgMask, bgModel] = backgroundSubtractor_wrapper('compute', img); + end + + % Reset object states + function reset(obj) + % Reset the background model with default parameters + % This is done in two steps. First free the persistent + % memory and then reconstruct the model with original + % parameters + backgroundSubtractor_wrapper('destroy'); + params = struct('algorithm', obj.algorithm); + backgroundSubtractor_wrapper('construct', params); + end + + % Release object memory + function release(~) + % free persistent memory for model + backgroundSubtractor_wrapper('destroy'); + end + + end +end \ No newline at end of file diff --git a/wrapper_matlab/backgroundSubtractor_wrapper.cpp b/wrapper_matlab/backgroundSubtractor_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..547012070adb5a3318282452faa650bf5aa3f6a7 --- /dev/null +++ b/wrapper_matlab/backgroundSubtractor_wrapper.cpp @@ -0,0 +1,395 @@ +/* + * 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> +#include "mxarray.h" + +#include "IBGS.h" +#include "FrameDifference.h" +#include "StaticFrameDifference.h" +#include "WeightedMovingMean.h" +#include "WeightedMovingVariance.h" +#include "MixtureOfGaussianV1.h" +#include "MixtureOfGaussianV2.h" +#include "AdaptiveBackgroundLearning.h" +#include "AdaptiveSelectiveBackgroundLearning.h" +#include "GMG.h" +#include "KNN.h" +#include "DPAdaptiveMedian.h" +#include "DPGrimsonGMM.h" +#include "DPZivkovicAGMM.h" +#include "DPMean.h" +#include "DPWrenGA.h" +#include "DPPratiMediod.h" +#include "DPEigenbackground.h" +#include "DPTexture.h" +#include "T2FGMM_UM.h" +#include "T2FGMM_UV.h" +#include "T2FMRF_UM.h" +#include "T2FMRF_UV.h" +#include "FuzzySugenoIntegral.h" +#include "FuzzyChoquetIntegral.h" +#include "LBSimpleGaussian.h" +#include "LBFuzzyGaussian.h" +#include "LBMixtureOfGaussians.h" +#include "LBAdaptiveSOM.h" +#include "LBFuzzyAdaptiveSOM.h" +#include "LBP_MRF.h" +#include "MultiLayer.h" +#include "PixelBasedAdaptiveSegmenter.h" +#include "VuMeter.h" +#include "KDE.h" +#include "IndependentMultimodal.h" +#include "MultiCue.h" +#include "SigmaDelta.h" +#include "SuBSENSE.h" +#include "LOBSTER.h" +#include "PAWCS.h" +#include "TwoPoints.h" +#include "ViBe.h" + +using namespace bgslibrary::algorithms; + +static IBGS *ptrBGS = NULL; + +namespace bgslibrary +{ + IBGS* init_alg(std::string alg_name) + { + if (alg_name.compare("FrameDifference") == 0) + return (IBGS *)mxCalloc(1, sizeof(FrameDifference)); + if (alg_name.compare("StaticFrameDifference") == 0) + return (IBGS *)mxCalloc(1, sizeof(StaticFrameDifference)); + if (alg_name.compare("WeightedMovingMean") == 0) + return (IBGS *)mxCalloc(1, sizeof(WeightedMovingMean)); + if (alg_name.compare("WeightedMovingVariance") == 0) + return (IBGS *)mxCalloc(1, sizeof(WeightedMovingVariance)); +#if CV_MAJOR_VERSION == 2 + if (alg_name.compare("MixtureOfGaussianV1") == 0) + return (IBGS *)mxCalloc(1, sizeof(MixtureOfGaussianV1)); // only for OpenCV 2.x +#endif + if (alg_name.compare("MixtureOfGaussianV2") == 0) + return (IBGS *)mxCalloc(1, sizeof(MixtureOfGaussianV2)); + if (alg_name.compare("AdaptiveBackgroundLearning") == 0) + return (IBGS *)mxCalloc(1, sizeof(AdaptiveBackgroundLearning)); + if (alg_name.compare("AdaptiveSelectiveBackgroundLearning") == 0) + return (IBGS *)mxCalloc(1, sizeof(AdaptiveSelectiveBackgroundLearning)); +#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 + 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 (alg_name.compare("KNN") == 0) + return (IBGS *)mxCalloc(1, sizeof(KNN)); // only for OpenCV 3.x +#endif + if (alg_name.compare("DPAdaptiveMedian") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPAdaptiveMedian)); + if (alg_name.compare("DPGrimsonGMM") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPGrimsonGMM)); + if (alg_name.compare("DPZivkovicAGMM") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPZivkovicAGMM)); + if (alg_name.compare("DPMean") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPMean)); + if (alg_name.compare("DPWrenGA") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPWrenGA)); + if (alg_name.compare("DPPratiMediod") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPPratiMediod)); + if (alg_name.compare("DPEigenbackground") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPEigenbackground)); + if (alg_name.compare("DPTexture") == 0) + return (IBGS *)mxCalloc(1, sizeof(DPTexture)); + if (alg_name.compare("T2FGMM_UM") == 0) + return (IBGS *)mxCalloc(1, sizeof(T2FGMM_UM)); + if (alg_name.compare("T2FGMM_UV") == 0) + return (IBGS *)mxCalloc(1, sizeof(T2FGMM_UV)); + if (alg_name.compare("T2FMRF_UM") == 0) + return (IBGS *)mxCalloc(1, sizeof(T2FMRF_UM)); + if (alg_name.compare("T2FMRF_UV") == 0) + return (IBGS *)mxCalloc(1, sizeof(T2FMRF_UV)); + if (alg_name.compare("FuzzySugenoIntegral") == 0) + return (IBGS *)mxCalloc(1, sizeof(FuzzySugenoIntegral)); + if (alg_name.compare("FuzzyChoquetIntegral") == 0) + return (IBGS *)mxCalloc(1, sizeof(FuzzyChoquetIntegral)); + if (alg_name.compare("LBSimpleGaussian") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBSimpleGaussian)); + if (alg_name.compare("LBFuzzyGaussian") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBFuzzyGaussian)); + if (alg_name.compare("LBMixtureOfGaussians") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBMixtureOfGaussians)); + if (alg_name.compare("LBAdaptiveSOM") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBAdaptiveSOM)); + if (alg_name.compare("LBFuzzyAdaptiveSOM") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBFuzzyAdaptiveSOM)); + if (alg_name.compare("LBP_MRF") == 0) + return (IBGS *)mxCalloc(1, sizeof(LBP_MRF)); + if (alg_name.compare("MultiLayer") == 0) + return (IBGS *)mxCalloc(1, sizeof(MultiLayer)); + if (alg_name.compare("PixelBasedAdaptiveSegmenter") == 0) + return (IBGS *)mxCalloc(1, sizeof(PixelBasedAdaptiveSegmenter)); + if (alg_name.compare("VuMeter") == 0) + return (IBGS *)mxCalloc(1, sizeof(VuMeter)); + if (alg_name.compare("KDE") == 0) + return (IBGS *)mxCalloc(1, sizeof(KDE)); + if (alg_name.compare("IndependentMultimodal") == 0) + return (IBGS *)mxCalloc(1, sizeof(IndependentMultimodal)); + if (alg_name.compare("MultiCue") == 0) + return (IBGS *)mxCalloc(1, sizeof(MultiCue)); + if (alg_name.compare("SigmaDelta") == 0) + return (IBGS *)mxCalloc(1, sizeof(SigmaDelta)); + if (alg_name.compare("SuBSENSE") == 0) + return (IBGS *)mxCalloc(1, sizeof(SuBSENSE)); + if (alg_name.compare("LOBSTER") == 0) + return (IBGS *)mxCalloc(1, sizeof(LOBSTER)); + if (alg_name.compare("PAWCS") == 0) + return (IBGS *)mxCalloc(1, sizeof(PAWCS)); + if (alg_name.compare("TwoPoints") == 0) + return (IBGS *)mxCalloc(1, sizeof(TwoPoints)); + if (alg_name.compare("ViBe") == 0) + return (IBGS *)mxCalloc(1, sizeof(ViBe)); + 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(); + return NULL; + } +} + +////////////////////////////////////////////////////////////////////////////// +// Check inputs +////////////////////////////////////////////////////////////////////////////// +void checkInputs(int nrhs, const mxArray *prhs[]) +{ + //mexPrintf("checkInputs()\n"); + if ((nrhs < 1) || (nrhs > 2)) + mexErrMsgTxt("Incorrect number of inputs. Function expects 1 or 2 inputs."); +} + +////////////////////////////////////////////////////////////////////////////// +// Get MEX function inputs +////////////////////////////////////////////////////////////////////////////// +void getParams(std::string &algorithm, const mxArray* mxParams) +{ + //mexPrintf("getParams()\n"); + const mxArray* mxfield; + mxfield = mxGetField(mxParams, 0, "algorithm"); + algorithm = mexplus::MxArray::to<std::string>(mxfield); + //mexPrintf(algorithm.c_str()); + //mexPrintf("\n"); +} + +////////////////////////////////////////////////////////////////////////////// +// Exit function for freeing persistent memory +////////////////////////////////////////////////////////////////////////////// +void exitFcn() +{ + //mexPrintf("exitFcn()\n"); + if (ptrBGS != NULL) + { + // explicitly call destructor for "placement new" + ptrBGS->~IBGS(); + mxFree(ptrBGS); + ptrBGS = NULL; + } +} + +////////////////////////////////////////////////////////////////////////////// +// Construct object +////////////////////////////////////////////////////////////////////////////// +void constructObject(const mxArray *prhs[]) +{ + //mexPrintf("constructObject()\n"); + std::string algorithm; + + // second input must be struct + if (mxIsStruct(prhs[1])) + getParams(algorithm, prhs[1]); + + if (ptrBGS != NULL) exitFcn(); + + // Allocate memory for background subtractor model + //ptrBGS = (IBGS *)mxCalloc(1, sizeof(IBGS)); + ptrBGS = bgslibrary::init_alg(algorithm); + if (ptrBGS != NULL) + { + // Make memory allocated by MATLAB software persist after MEX-function completes. + // This lets us use the updated background subtractor model for the next frame. + mexMakeMemoryPersistent(ptrBGS); + + // Use "placement new" to construct an object on memory that was + // already allocated using mxCalloc + ptrBGS = bgslibrary::get_alg(algorithm); + if (ptrBGS == NULL) + mexErrMsgTxt("Failed to construct an object on memory. Algorithm not initialized."); + } + else + mexErrMsgTxt("Failed to allocate memory. Algorithm not found?"); + + // Register a function that gets called when the MEX-function is cleared. + // This function is responsible for freeing persistent memory + mexAtExit(exitFcn); +} + +////////////////////////////////////////////////////////////////////////////// +// Compute foreground mask +////////////////////////////////////////////////////////////////////////////// +void computeForegroundMask(mxArray *plhs[], const mxArray *prhs[]) +{ + //mexPrintf("computeForegroundMask()\n"); + if (ptrBGS != NULL) + { + cv::Ptr<cv::Mat> img = ocvMxArrayToImage_uint8(prhs[1], true); + cv::Mat fgmask, bgmodel; + + ptrBGS->process(*img, fgmask, bgmodel); + + if (fgmask.empty()) + fgmask = cv::Mat::zeros((*img).size(), CV_8UC1); + if (bgmodel.empty()) + bgmodel = cv::Mat::zeros((*img).size(), CV_8UC3); // (*img).type() + + // https://fr.mathworks.com/help/vision/ref/ocvmxarrayfromimage_datatype.html + plhs[0] = ocvMxArrayFromImage_uint8(fgmask); + plhs[1] = ocvMxArrayFromImage_uint8(bgmodel); + + //if(!fgmask.empty()) + fgmask.release(); + //if(!bgmodel.empty()) + bgmodel.release(); + } + else + mexErrMsgTxt("Algorithm not initialized."); +} + +////////////////////////////////////////////////////////////////////////////// +// The main MEX function entry point +////////////////////////////////////////////////////////////////////////////// +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + //mexPrintf("mexFunction()\n"); + checkInputs(nrhs, prhs); + const char *str = mxIsChar(prhs[0]) ? mxArrayToString(prhs[0]) : NULL; + + if (str != NULL) + { + //mexPrintf("%s\n",str); + if (strcmp(str, "construct") == 0) + constructObject(prhs); + else if (strcmp(str, "compute") == 0) + computeForegroundMask(plhs, prhs); + else if (strcmp(str, "destroy") == 0) + exitFcn(); + + // Free memory allocated by mxArrayToString + mxFree((void *)str); + } +} diff --git a/wrapper_matlab/compile.m b/wrapper_matlab/compile.m new file mode 100644 index 0000000000000000000000000000000000000000..314ada17de002e4a63f565b4178cc886a1c2f406 --- /dev/null +++ b/wrapper_matlab/compile.m @@ -0,0 +1,94 @@ +%% 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_matlab/config/.gitignore b/wrapper_matlab/config/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e2a98bb114355ae964e78a929c12d44f75815de --- /dev/null +++ b/wrapper_matlab/config/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except these files +!.gitignore diff --git a/wrapper_matlab/demo.m b/wrapper_matlab/demo.m new file mode 100644 index 0000000000000000000000000000000000000000..942e457fb227cc4f11104f276f0a498d40eb0181 --- /dev/null +++ b/wrapper_matlab/demo.m @@ -0,0 +1,65 @@ +%{ +/* + * 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') +% See the full list of available algorithms in the BGSLibrary website. +function demo(algorithm) +if(nargin < 1) + algorithm = 'FrameDifference'; +end + +% Create video reader object +%filename = 'visiontraffic.avi'; +filename = '../dataset/demo.avi'; +hsrc = vision.VideoFileReader(filename, ... + 'ImageColorSpace', 'RGB', ... + 'VideoOutputDataType', 'uint8'); + +% Create background/foreground segmentation object +hfg = backgroundSubtractor(algorithm); + +disp('Starting...'); +frameCnt = 1; +while ~isDone(hsrc), %disp(frameCnt) + % Read frame + frame = step(hsrc); + + % Compute foreground mask and background model + [fgMask, bgModel] = getForegroundMask(hfg, frame); + + % View results + subplot(1,3,1), imshow(frame,'InitialMagnification','fit'); + subplot(1,3,2), imshow(fgMask,'InitialMagnification','fit'); + subplot(1,3,3), imshow(bgModel,'InitialMagnification','fit'); + pause(0.01); + + % Reset background model + % This step just demonstrates how to use reset method + if (frameCnt==15) + %reset(hfg); + %break; + end + + frameCnt = frameCnt + 1; +end +disp('Finished!'); + +release(hfg); +release(hsrc); diff --git a/wrapper_matlab/mxarray.h b/wrapper_matlab/mxarray.h new file mode 100644 index 0000000000000000000000000000000000000000..6a9afe96bba0bb96065c75f48e1077e08673a05a --- /dev/null +++ b/wrapper_matlab/mxarray.h @@ -0,0 +1,1555 @@ +/** MxArray data conversion library. + * + * Copyright 2014 Kota Yamaguchi. + * + * The library provides mexplus::MxArray class for data conversion between + * mxArray* and C++ types. The static API's are the core of the high-level + * conversions. + * + * int value = MxArray::to<int>(prhs[0]); + * string value = MxArray::to<string>(prhs[0]); + * vector<double> value = MxArray::to<vector<double> >(prhs[0]); + * + * plhs[0] = MxArray::from(20); + * plhs[0] = MxArray::from("text value."); + * plhs[0] = MxArray::from(vector<double>(20, 0)); + * + * Additionally, object API's are there to wrap around a complicated data + * access. + * + * ### Read access + * + * MxArray cell(prhs[0]); // Assumes cell array in prhs[0]. + * int x = cell.at<int>(0); + * vector<double> y = cell.at<vector<double> >(1); + * + * MxArray numeric(prhs[0]); // Assumes numeric array in prhs[0]. + * double x = numeric.at<double>(0); + * int y = numeric.at<int>(1); + * + * ### Write access + * + * MxArray cell(MxArray::Cell(1, 3)); + * cell.set(0, 12); + * cell.set(1, "text value."); + * cell.set(2, vector<double>(4, 0)); + * plhs[0] = cell.release(); + * + * MxArray numeric(MxArray::Numeric<double>(2, 2)); + * numeric.set(0, 0, 1); + * numeric.set(0, 1, 2); + * numeric.set(1, 0, 3); + * numeric.set(1, 1, 4); + * plhs[0] = numeric.release(); + * + * To add your own data conversion, define in namespace mexplus a template + * specialization of MxArray::from() and MxArray::to(). + * + */ + +#ifndef INCLUDE_MEXPLUS_MXARRAY_H_ +#define INCLUDE_MEXPLUS_MXARRAY_H_ + +#include <mex.h> +#include <algorithm> +#include <cstdint> +#include <set> +#include <string> +#include <typeinfo> +#include <vector> +#include "mxtypes.h" + +#pragma warning(once : 4244) + +/** Macro definitions. + */ +#define MEXPLUS_CHECK_NOTNULL(pointer) \ + if (!(pointer)) \ + mexErrMsgIdAndTxt("mexplus:error", \ + "Null pointer exception: %s:%d:%s `" #pointer "`.", \ + __FILE__, \ + __LINE__, \ + __FUNCTION__) + +#define MEXPLUS_ERROR(...) mexErrMsgIdAndTxt("mexplus:error", __VA_ARGS__) +#define MEXPLUS_WARNING(...) mexWarnMsgIdAndTxt("mexplus:warning", __VA_ARGS__) +#define MEXPLUS_ASSERT(condition, ...) \ + if (!(condition)) mexErrMsgIdAndTxt("mexplus:error", __VA_ARGS__) + +namespace mexplus { + +/** mxArray object wrapper for data conversion and manipulation. + * + * The class is similar to a combination of unique_ptr and wrapper around + * Matlab's matrix API. An MxArray object created from a mutable mxArray* + * pointer automatically frees its internal memory unless explicitly + * released. When MxArray is created from a const mxArray*, the object does not + * manage memory but still provides the same matrix API. + */ +class MxArray { + public: + /** Empty MxArray constructor. Use reset() to set a pointer. + */ + MxArray() : array_(NULL), owner_(false) {} + /** NULL assignment. + */ + MxArray& operator= (std::nullptr_t) { + reset(); + return *this; + } + /** Move constructor. + */ + MxArray(MxArray&& array) : array_(NULL), owner_(false) { + *this = std::move(array); + } + /** Move assignment. + */ + MxArray& operator= (MxArray&& rhs) { + if (this != &rhs) { + array_ = rhs.array_; + owner_ = rhs.owner_; + rhs.array_ = NULL; + rhs.owner_ = false; + } + return *this; + } + /** MxArray constructor from const mxArray*. MxArray will not manage memory. + * @param array mxArray pointer given by mexFunction. + */ + explicit MxArray(const mxArray* array) : + array_(const_cast<mxArray*>(array)), + owner_(false) {} + /** MxArray constructor from mutable mxArray*. MxArray will manage memory. + * @param array mxArray pointer. + */ + explicit MxArray(mxArray* array) : array_(array), owner_(array != NULL) {} + /** Assignment from const mxArray*. MxArray will not manage memory. + */ + MxArray& operator= (const mxArray* rhs) { + reset(rhs); + return *this; + } + /** Assignment from mutable mxArray*. MxArray will manage memory. + */ + MxArray& operator= (mxArray* rhs) { + reset(rhs); + return *this; + } + /** MxArray constructor from scalar. + */ + template <typename T> + explicit MxArray(const T& value) : array_(from(value)), owner_(true) {} + /** Destructor. Unreleased pointers will be destroyed. + */ + virtual ~MxArray() { + if (array_ && owner_) + mxDestroyArray(array_); + } + /** Swap operation. + */ + void swap(MxArray& rhs) { + if (this != &rhs) { + mxArray* array = rhs.array_; + bool owner = rhs.owner_; + rhs.array_ = array_; + rhs.owner_ = owner_; + array_ = array; + owner_ = owner; + } + } + /** Reset an mxArray to a const mxArray*. + * + * Caller must be VERY careful with this, as the behavior is undefined when + * the original mxArray* is destroyed. For example, the following will crash. + * @code + * MxArray foo; + * { + * MxArray bar(1); + * foo.reset(bar.get()); + * } + * foo.toInt(); // Error! + * @endcode + */ + void reset(const mxArray* array = NULL) { + if (array_ && owner_) + mxDestroyArray(array_); + array_ = const_cast<mxArray*>(array); + owner_ = false; + } + /** Reset an mxArray. + */ + void reset(mxArray* array) { + if (array_ && owner_) + mxDestroyArray(array_); + array_ = array; + owner_ = (array != NULL); + } + /** Release managed mxArray* pointer, or clone if not owner. + * @return Unmanaged mxArray*. Always caller must destroy. + */ + mxArray* release() { + MEXPLUS_CHECK_NOTNULL(array_); + mxArray* array = (owner_) ? array_ : clone(); + array_ = NULL; + owner_ = false; + return array; + } + /** Clone mxArray. This always allocates new mxArray*. + * @return Unmanaged mxArray*. Always caller must destroy. + */ + mxArray* clone() const { + MEXPLUS_CHECK_NOTNULL(array_); + mxArray* array = mxDuplicateArray(array_); + MEXPLUS_CHECK_NOTNULL(array); + return array; + } + /** Conversion to const mxArray*. + * @return const mxArray* pointer. + */ + inline const mxArray* get() const { return array_; } + /** Get raw mxArray*. + * @return mxArray* pointer. + */ + inline mxArray* getMutable() { return array_; } + /** Return true if the array is not NULL. + */ + operator bool() const { return array_ != NULL; } + /** Return true if owner. + */ + inline bool isOwner() const { return owner_; } + /** Create a new numeric (real or complex) matrix. + * @param rows Number of rows. + * @param columns Number of cols. + */ + template <typename T> + static mxArray* Numeric(int rows = 1, int columns = 1); + /** Create a new numeric (real or complex) matrix. + * @param ndim Number of dimensions. + * @param dims Dimensions array. Each element in the dimensions array + * contains the size of the array in that dimension. + */ + template <typename T> + static mxArray* Numeric(std::vector<std::size_t> dims); + /** Create a new logical matrix. + * @param rows Number of rows. + * @param columns Number of cols. + */ + static mxArray* Logical(int rows = 1, int columns = 1) { + mxArray* logical_array = mxCreateLogicalMatrix(rows, columns); + MEXPLUS_CHECK_NOTNULL(logical_array); + return logical_array; + } + /** Create a new cell matrix. + * @param rows Number of rows. + * @param columns Number of cols. + * + * Example: + * @code + * MxArray cell_array = MxArray::Cell(1, 2); + * cell_array.set(0, 1); + * cell_array.set(1, "another value"); + * plhs[0] = cell_array.release(); + * @endcode + */ + static mxArray* Cell(int rows = 1, int columns = 1) { + mxArray* cell_array = mxCreateCellMatrix(rows, columns); + MEXPLUS_CHECK_NOTNULL(cell_array); + return cell_array; + } + /** Generic constructor for a struct matrix. + * @param fields field names. + * @param nfields number of field names. + * @param rows size of the first dimension. + * @param columns size of the second dimension. + * + * Example: + * @code + * const char* fields[] = {"field1", "field2"}; + * MxArray struct_array(MxArray::Struct(2, fields)); + * struct_array.set("field1", 1); + * struct_array.set("field2", "field2 value"); + * plhs[0] = struct_array.release(); + * @endcode + */ + static mxArray* Struct(int nfields = 0, + const char** fields = NULL, + int rows = 1, + int columns = 1) { + mxArray* struct_array = mxCreateStructMatrix(rows, + columns, + nfields, + fields); + MEXPLUS_CHECK_NOTNULL(struct_array); + return struct_array; + } + /** mxArray* importer methods. + */ + template <typename T> + static mxArray* from(const T& value) { return fromInternal<T>(value); } + static mxArray* from(const char* value) { + mxArray* array = mxCreateString(value); + MEXPLUS_CHECK_NOTNULL(array); + return array; + } + static mxArray* from(int32_t value) { + mxArray* array = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); + MEXPLUS_CHECK_NOTNULL(array); + *reinterpret_cast<int32_t*>(mxGetData(array)) = value; + return array; + } + /** mxArray* exporter methods. + */ + template <typename T> + static void to(const mxArray* array, T* value) { + toInternal<T>(array, value); + } + template <typename T> + static T to(const mxArray* array) { + T value; + toInternal<T>(array, &value); + return value; + } + /** mxArray* element reader methods. + */ + template <typename T> + static T at(const mxArray* array, mwIndex index) { + T value; + atInternal<T>(array, index, &value); + return value; + } + template <typename T> + static void at(const mxArray* array, mwIndex index, T* value) { + atInternal<T>(array, index, value); + } + static const mxArray* at(const mxArray* array, mwIndex index) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_ASSERT(mxIsCell(array), "Expected a cell array."); + return mxGetCell(array, index); + } + template <typename T> + static void at(const mxArray* array, + const std::string& field, + T* value, + mwIndex index = 0) { + atInternal<T>(array, field, index, value); + } + static const mxArray* at(const mxArray* array, + const std::string& field, + mwIndex index = 0) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_ASSERT(mxIsStruct(array), "Expected a struct array."); + return mxGetField(array, index, field.c_str()); + } + /** mxArray* element writer methods. + */ + template <typename T> + static void set(mxArray* array, mwIndex index, const T& value) { + setInternal<T>(array, index, value); + } + static void set(mxArray* array, mwIndex index, mxArray* value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(mxIsCell(array), "Expected a cell array."); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + mxDestroyArray(mxGetCell(array, index)); + mxSetCell(array, index, value); + } + template <typename T> + static void set(mxArray* array, + const std::string& field, + const T& value, + mwIndex index = 0) { + setInternal<T>(array, field, index, value); + } + static void set(mxArray* array, + const std::string& field, + mxArray* value, + mwIndex index = 0) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(mxIsStruct(array), "Expected a struct array."); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + int field_number = mxGetFieldNumber(array, field.c_str()); + if (field_number < 0) { + field_number = mxAddField(array, field.c_str()); + MEXPLUS_ASSERT(field_number >= 0, + "Failed to create a field '%s'", + field.c_str()); + } + mxDestroyArray(mxGetFieldByNumber(array, index, field_number)); + mxSetFieldByNumber(array, index, field_number, value); + } + + /** Convert MxArray to a specified type. + */ + template <typename T> + T to() const { + T value; + toInternal<T>(array_, &value); + return value; + } + template <typename T> + void to(T* value) const { toInternal<T>(array_, value); } + /** Template for element accessor. + * @param index index of the array element. + * @return value of the element at index. + * + * + * Example: + * @code + * MxArray array(prhs[0]); + * double value = array.at<double>(0); + * @endcode + */ + template <typename T> + T at(mwIndex index) const { + T value; + atInternal<T>(array_, index, &value); + return value; + } + template <typename T> + void at(mwIndex index, T* value) const { + atInternal<T>(array_, index, value); + } + const mxArray* at(mwIndex index) const { + return at(array_, index); + } + /** Template for element accessor. + * @param row index of the first dimension. + * @param column index of the second dimension. + * @return value of the element at (row, column). + */ + template <typename T> + T at(mwIndex row, mwIndex column) const; + /** Template for element accessor. + * @param subscripts subscript indexes of elements. + * @return value of the element at subscript index. + */ + template <typename T> + T at(const std::vector<mwIndex>& subscripts) const; + /** Struct element accessor. + * @param field field name of the struct array. + * @param index index of the struct array. + * @return value of the element at the specified field. + */ + template <typename T> + T at(const std::string& field, mwIndex index = 0) const { + T value; + atInternal<T>(array_, field, index, &value); + return value; + } + template <typename T> + void at(const std::string& field, T* value, mwIndex index = 0) const { + atInternal<T>(array_, field, index, value); + } + const mxArray* at(const std::string& field, mwIndex index = 0) const { + return at(array_, field, index); + } + + /** Template for element write accessor. + * @param index offset of the array element. + * @param value value of the field. + */ + template <typename T> + void set(mwIndex index, const T& value) { + setInternal<T>(array_, index, value); + } + /** Template for element write accessor. + * @param row index of the first dimension of the array element. + * @param column index of the first dimension of the array element. + * @param value value of the field. + */ + template <typename T> + void set(mwIndex row, mwIndex column, const T& value); + /** Template for element write accessor. + * @param subscripts subscript index of the element. + * @param value value of the field. + */ + template <typename T> + void set(const std::vector<mwIndex>& subscripts, const T& value); + /** Cell element write accessor. + * @param index index of the element. + * @param value cell element to be inserted. + */ + void set(mwIndex index, mxArray* value) { + MEXPLUS_ASSERT(isOwner(), "Must be an owner to set."); + set(array_, index, value); + } + /** Cell element write accessor. + * @param row index of the first dimension of the array element. + * @param column index of the first dimension of the array element. + * @param value cell element to be inserted. + */ + void set(mwIndex row, mwIndex column, mxArray* value) { + MEXPLUS_ASSERT(isOwner(), "Must be an owner to set."); + set(array_, subscriptIndex(row, column), value); + } + /** Cell element write accessor. + * @param subscripts subscript index of the element. + * @param value value of the field. + */ + void set(const std::vector<mwIndex>& subscripts, mxArray* value) { + MEXPLUS_ASSERT(isOwner(), "Must be an owner to set."); + set(array_, subscriptIndex(subscripts), value); + } + /** Struct element write accessor. + * @param field field name of the struct array. + * @param value value of the field. + * @param index linear index of the struct array element. + */ + template <typename T> + void set(const std::string& field, const T& value, mwIndex index = 0) { + MEXPLUS_ASSERT(isOwner(), "Must be an owner to set."); + setInternal<T>(array_, field, index, value); + } + /** Struct element write accessor. + * @param field field name of the struct array. + * @param value value of the field to be inserted. + * @param index linear index of the struct array element. + */ + void set(const std::string& field, mxArray* value, mwIndex index = 0) { + MEXPLUS_ASSERT(isOwner(), "Must be an owner to set."); + set(array_, field, value, index); + } + /** Get raw data pointer. + * @return pointer T*. If MxArray is not compatible, return NULL. + */ + template <typename T> + T* getData() const; + /** Get raw data pointer to imaginary part. + * @return pointer T*. If MxArray is not compatible, return NULL. + */ + template <typename T> + T* getImagData() const; + mxLogical* getLogicals() const { + MEXPLUS_CHECK_NOTNULL(array_); + MEXPLUS_ASSERT(isLogical(), + "Expected a logical array but %s.", + className().c_str()); + return mxGetLogicals(array_); + } + mxChar* getChars() const { + MEXPLUS_CHECK_NOTNULL(array_); + MEXPLUS_ASSERT(isChar(), + "Expected a char array but %s.", + className().c_str()); + return mxGetChars(array_); + } + /** Class ID of mxArray. + */ + inline mxClassID classID() const { return mxGetClassID(array_); } + /** Class name of mxArray. + */ + inline const std::string className() const { + return std::string(mxGetClassName(array_)); + } + /** Number of elements in an array. + */ + inline mwSize size() const { + return static_cast<mwSize>(mxGetNumberOfElements(array_)); + } + /** Number of dimensions. + */ + inline mwSize dimensionSize() const { + return mxGetNumberOfDimensions(array_); + } + /** Array of each dimension. + */ + inline std::vector<mwSize> dimensions() const { + const mwSize* dimensions = mxGetDimensions(array_); + return std::vector<mwSize>(dimensions, dimensions + dimensionSize()); + } + /** Number of rows in an array. + */ + inline mwSize rows() const { return static_cast<mwSize>(mxGetM(array_)); } + /** Number of columns in an array. + */ + inline mwSize cols() const { return static_cast<mwSize>(mxGetN(array_)); } + /** Number of fields in a struct array. + */ + inline int fieldSize() const { return mxGetNumberOfFields(array_); } + /** Get field name of a struct array. + * @param index index of the struct array. + * @return std::string. + */ + std::string fieldName(int index) const { + const char* field = mxGetFieldNameByNumber(array_, index); + MEXPLUS_ASSERT(field, "Failed to get field name at %d.", index); + return std::string(field); + } + /** Get field names of a struct array. + * @return std::vector<std::string> of struct field names. + */ + std::vector<std::string> fieldNames() const { + MEXPLUS_ASSERT(isStruct(), "Expected a struct array."); + std::vector<std::string> fields(fieldSize()); + for (size_t i = 0; i < fields.size(); ++i) + fields[i] = fieldName(i); + return fields; + } + /** Number of elements in IR, PR, and PI arrays. + */ + inline mwSize nonZeroMax() const { return mxGetNzmax(array_); } + /** Offset from first element to desired element. + * @param row index of the first dimension of the array. + * @param column index of the second dimension of the array. + * @return linear offset of the specified subscript index. + */ + mwIndex subscriptIndex(mwIndex row, mwIndex column) const { + MEXPLUS_ASSERT(row < rows() && column < cols(), + "Subscript is out of range."); + mwIndex subscripts[] = {row, column}; + return mxCalcSingleSubscript(array_, 2, subscripts); + } + /** Offset from first element to desired element. + * @param subscripts subscript indexes of the array. + * @return linear offset of the specified subscript index. + */ + mwIndex subscriptIndex(const std::vector<mwIndex>& subscripts) const { + return mxCalcSingleSubscript(array_, + static_cast<mwSize>(subscripts.size()), + const_cast<mwIndex*>(&subscripts[0])); + } + /** Determine whether input is cell array. + */ + inline bool isCell() const { return mxIsCell(array_); } + /** Determine whether input is string array. + */ + inline bool isChar() const { return mxIsChar(array_); } + /** Determine whether input is vector array. + */ + inline bool isVector() const { + return mxGetNumberOfDimensions(array_) == 2 && + (mxGetM(array_) == 1 || mxGetN(array_) == 1); + } + /** Determine whether array is integral type. + */ + inline bool isIntegral(const char* name) const { + return mxIsNumeric(array_) && !mxIsDouble(array_); + } + /** Determine whether array is member of specified class. + */ + inline bool isClass(const char* name) const { + return mxIsClass(array_, name); + } + /** Determine whether data is complex. + */ + inline bool isComplex() const { return mxIsComplex(array_); } + /** Determine whether mxArray represents data as double-precision, + * floating-point numbers. + */ + inline bool isDouble() const { return mxIsDouble(array_); } + /** Determine whether array is empty. + */ + inline bool isEmpty() const { return mxIsEmpty(array_); } + /** Determine whether input is finite. + */ + static inline bool IsFinite(double value) { return mxIsFinite(value); } + /** Determine whether array was copied from MATLAB global workspace. + */ + inline bool isFromGlobalWS() const { return mxIsFromGlobalWS(array_); } + /** Determine whether input is infinite. + */ + static inline bool IsInf(double value) { return mxIsInf(value); } + /** Determine whether array represents data as signed 8-bit integers. + */ + inline bool isInt8() const { return mxIsInt8(array_); } + /** Determine whether array represents data as signed 16-bit integers. + */ + inline bool isInt16() const { return mxIsInt16(array_); } + /** Determine whether array represents data as signed 32-bit integers. + */ + inline bool isInt32() const { return mxIsInt32(array_); } + /** Determine whether array represents data as signed 64-bit integers. + */ + inline bool isInt64() const { return mxIsInt64(array_); } + /** Determine whether array is of type mxLogical. + */ + inline bool isLogical() const { return mxIsLogical(array_); } + /** Determine whether scalar array is of type mxLogical. + */ + inline bool isLogicalScalar() const { return mxIsLogicalScalar(array_); } + /** Determine whether scalar array of type mxLogical is true. + */ + inline bool isLogicalScalarTrue() const { + return mxIsLogicalScalarTrue(array_); + } + /** Determine whether array is numeric. + */ + inline bool isNumeric() const { return mxIsNumeric(array_); } + /** Determine whether array represents data as single-precision, + * floating-point numbers. + */ + inline bool isSingle() const { return mxIsSingle(array_); } + /** Determine whether input is sparse array. + */ + inline bool isSparse() const { return mxIsSparse(array_); } + /** Determine whether input is structure array. + */ + inline bool isStruct() const { return mxIsStruct(array_); } + /** Determine whether array represents data as unsigned 8-bit integers. + */ + inline bool isUint8() const { return mxIsUint8(array_); } + /** Determine whether array represents data as unsigned 16-bit integers. + */ + inline bool isUint16() const { return mxIsUint16(array_); } + /** Determine whether array represents data as unsigned 32-bit integers. + */ + inline bool isUint32() const { return mxIsUint32(array_); } + /** Determine whether array represents data as unsigned 64-bit integers. + */ + inline bool isUint64() const { return mxIsUint64(array_); } + /** Determine whether a struct array has a specified field. + */ + bool hasField(const std::string& field_name, mwIndex index = 0) const { + return isStruct() && + mxGetField(array_, index, field_name.c_str()) != NULL; + } + /** Element size. + */ + int elementSize() const { + return static_cast<int>(mxGetElementSize(array_)); + } + /** Determine whether input is NaN (Not-a-Number). + */ + static inline bool IsNaN(double value) { return mxIsNaN(value); } + /** Value of infinity. + */ + static inline double Inf() { return mxGetInf(); } + /** Value of NaN (Not-a-Number). + */ + static inline double NaN() { return mxGetNaN(); } + /** Value of EPS. + */ + static inline double Eps() { return mxGetEps(); } + + private: + /** Copy constructor is prohibited except internally. + */ + MxArray(const MxArray& array); + // MxArray(const MxArray& array) = delete; + /** Copy assignment operator is prohibited. + */ + MxArray& operator=(const MxArray& rhs); + // MxArray& operator=(const MxArray& rhs) = delete; + + /*************************************************************/ + /** Templated mxArray importers **/ + /*************************************************************/ + + /** Fundamental numerics. + */ + template <typename T> + static mxArray* fromInternal(const typename std::enable_if< + MxArithmeticType<T>::value, T>::type& value); + /** Complex types, complex<float> or complex<double>. + */ + template <typename T> + static mxArray* fromInternal(const typename std::enable_if< + MxComplexType<T>::value, T>::type& value); + /** Container with fundamental numerics, i.e. vector<double>. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + MxArithmeticCompound<Container>::value, + Container>::type& value); + /** Container with complex numbers, i.e. vector<complex<double>>. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + MxComplexCompound<Container>::value, Container>::type& value); + /** Char type */ + template <typename T> + static mxArray* fromInternal(const typename std::enable_if< + MxCharType<T>::value, T>::type& value); + /** Containter with signed char. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + (MxCharCompound<Container>::value) && + (std::is_signed<typename Container::value_type>::value), + Container>::type& value); + /** Container with unsigned char. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + (MxCharCompound<Container>::value) && + !(std::is_signed<typename Container::value_type>::value), + Container>::type& value); + /** Logicals. + */ + template <typename T> + static mxArray* fromInternal(const typename std::enable_if< + MxLogicalType<T>::value, T>::type& value); + /** Container with logicals. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + MxLogicalCompound<Container>::value, Container>::type& value); + /** Container with cell type content. + */ + template <typename Container> + static mxArray* fromInternal(const typename std::enable_if< + MxCellCompound<Container>::value, Container>::type& value); + + /*************************************************************/ + /** Templated mxArray exporters **/ + /*************************************************************/ + + /** Singleton types. + */ + template <typename T> + static void toInternal(const mxArray* array, + typename std::enable_if< + MxArithmeticType<T>::value || + MxComplexType<T>::value || + MxLogicalType<T>::value || + MxCharType<T>::value, + T + >::type* value) { + atInternal<T>(array, 0, value); + } + /** Vector types. + */ + template <typename T> + static void toInternal(const mxArray* array, + typename std::enable_if< + MxComplexOrArithmeticCompound<T>::value || + MxLogicalCompound<T>::value || + MxCharCompound<T>::value, + T + >::type* value); + /** Nested types (leads into recursive deduction). + */ + template <typename T> + static void toInternal(const mxArray* array, + typename std::enable_if< + MxCellType<T>::value && + (!std::is_compound<T>::value || + MxCellType<typename T::value_type>::value), + T + >::type* value); + + /*************************************************************/ + /** Templated mxArray getters **/ + /*************************************************************/ + + /** Fundamental numeric types. + */ + template <typename T> + static void atInternal(const mxArray* array, mwIndex index, + typename std::enable_if< + MxComplexOrArithmeticType<T>::value || + MxLogicalType<T>::value || + MxCharType<T>::value, + T>::type* value); + /** Converter for nested types. + */ + template <typename T> + static void atInternal(const mxArray* array, mwIndex index, + typename std::enable_if< + std::is_compound<T>::value && + !MxComplexType<T>::value, + T + >::type* value); + /** Structure access. + */ + template <typename T> + static void atInternal(const mxArray* array, + const std::string& field, + mwIndex index, T* value); + + /*************************************************************/ + /** Templated mxArray element setters **/ + /*************************************************************/ + + /** Fundamental numeric and complex types. + */ + template <typename T> + static void setInternal(mxArray* array, mwIndex index, + const typename std::enable_if< + !std::is_compound<T>::value || + MxComplexType<T>::value, + T + >::type& value); + /** Container types. + */ + template <typename T> + static void setInternal(mxArray* array, mwIndex index, + const typename std::enable_if< + MxCellType<T>::value, + T + >::type& value); + /** Structure access. + */ + template <typename T> + static void setInternal(mxArray* array, const std::string& field, + mwIndex index, const T& value); + + /*************************************************************/ + /** Assignment helpers (for MxArray.to<type>(value)) **/ + /*************************************************************/ + + /** Explicit integer element assignment. + */ + template <typename T, typename R> + static void assignTo(const mxArray* array, + mwIndex index, typename std::enable_if< + std::is_integral<R>::value, + R + >::type* value) { + MEXPLUS_ASSERT(!mxIsComplex(array), "Non-complex array expected!"); + *value = (R)*(reinterpret_cast<T*>(mxGetData(array)) + index); + } + /** Explicit floating point element assignment. + */ + template <typename T, typename R> + static void assignTo(const mxArray* array, + mwIndex index, + typename std::enable_if< + std::is_floating_point<R>::value, + R + >::type* value) { + if (mxIsComplex(array)) { + T real_part = *(reinterpret_cast<T*>(mxGetPr(array)) + index); + T imag_part = *(reinterpret_cast<T*>(mxGetPi(array)) + index); + *value = std::abs(std::complex<R>(real_part, imag_part)); + } else { + *value = *(reinterpret_cast<T*>(mxGetData(array)) + index); + } + } + /** Explicit complex element assignment. + */ + template <typename T, typename R> + static void assignTo(const mxArray* array, + mwIndex index, + typename std::enable_if< + MxComplexType<R>::value, + R + >::type* value) { + typename R::value_type real_part, imag_part; + if (mxIsComplex(array)) { + real_part = *(reinterpret_cast<T*>(mxGetPr(array)) + index); + imag_part = *(reinterpret_cast<T*>(mxGetPi(array)) + index); + } else { + real_part = *(reinterpret_cast<T*>(mxGetData(array)) + index); + imag_part = 0.0; + } + *value = std::complex<typename R::value_type>(real_part, imag_part); + } + /** Explicit char (signed) element assignment. + */ + template <typename R> + static void assignCharTo(const mxArray* array, + mwIndex index, + typename std::enable_if< + std::is_signed<R>::value, + R + >::type* value) { + typedef typename std::make_signed<mxChar>::type SignedMxChar; + *value = *(reinterpret_cast<SignedMxChar*>(mxGetChars(array)) + index); + } + /** Explicit char (unsigned) element assignment. + */ + template <typename R> + static void assignCharTo(const mxArray* array, + mwIndex index, + typename std::enable_if< + !std::is_signed<R>::value, + R + >::type* value) { + *value = *(mxGetChars(array) + index); + } + /** Explicit cell element assignment. + */ + template <typename T> + static void assignCellTo(const mxArray* array, mwIndex index, T* value) { + const mxArray* element = mxGetCell(array, index); + MEXPLUS_CHECK_NOTNULL(element); + toInternal<T>(element, value); // Recursion for nested types. + } + /** Explicit numeric array assignment. + */ + template <typename T, typename R> + static void assignTo(const mxArray* array, + typename std::enable_if< + MxArithmeticCompound<R>::value || + MxLogicalCompound<R>::value || + MxCharCompound<R>::value, + R + >::type* value) { + mwSize array_size = static_cast<mwSize>(mxGetNumberOfElements(array)); + if (!mxIsComplex(array)) { + T* data_pointer = reinterpret_cast<T*>(mxGetData(array)); + value->assign(data_pointer, data_pointer + array_size); + } else { + T* real_part = reinterpret_cast<T*>(mxGetPr(array)); + T* imag_part = reinterpret_cast<T*>(mxGetPi(array)); + value->resize(array_size); + for (mwSize i = 0; i < array_size; ++i) { + double mag = std::abs(std::complex<double>( + static_cast<double>(*(real_part++)), + static_cast<double>(*(imag_part++)))); + (*value)[i] = static_cast<T>(mag); + } + } + } + /** Explicit complex array assigment. + */ + template <typename T, typename R> + static void assignTo(const mxArray* array, + typename std::enable_if< + MxComplexCompound<R>::value, + R + >::type* value) { + mwSize array_size = mxGetNumberOfElements(array); + value->resize(array_size); + if (!mxIsComplex(array)) { + T* data_pointer = reinterpret_cast<T*>(mxGetData(array)); + for (mwSize i = 0; i < array_size; ++i) { + (*value)[i] = typename R::value_type(*(data_pointer++), 0.0f); + } + } else { + T* real_part = reinterpret_cast<T*>(mxGetPr(array)); + T* imag_part = reinterpret_cast<T*>(mxGetPi(array)); + for (mwSize i = 0; i < array_size; ++i) { + (*value)[i] = typename R::value_type(*(real_part++), *(imag_part++)); + } + } + } + /** Explicit char (signed) array assignment. + */ + template <typename R> + static void assignStringTo(const mxArray* array, + typename std::enable_if< + std::is_signed<typename R::value_type>::value, + R + >::type* value) { + typedef typename std::make_signed<mxChar>::type SignedMxChar; + SignedMxChar* data_pointer = reinterpret_cast<SignedMxChar*>( + mxGetChars(array)); + value->assign(data_pointer, data_pointer + mxGetNumberOfElements(array)); + } + /** Explicit char (unsigned) array assignment. + */ + template <typename R> + static void assignStringTo(const mxArray* array, + typename std::enable_if< + !std::is_signed<typename R::value_type>::value, + R>::type* value) { + mxChar* data_pointer = mxGetChars(array); + value->assign(data_pointer, data_pointer + mxGetNumberOfElements(array)); + } + /** Explicit cell array assignment. + */ + template <typename T> + static void assignCellTo(const mxArray* array, T* value) { + mwSize array_size = static_cast<mwSize>(mxGetNumberOfElements(array)); + value->resize(array_size); + for (size_t i = 0; i < array_size; ++i) { + const mxArray* element = mxGetCell(array, i); + MEXPLUS_CHECK_NOTNULL(element); + (*value)[i] = to<typename T::value_type>(element); + } + } + + /*************************************************************/ + /** Assignment helpers (for MxArray.set<type>(i, value)) **/ + /*************************************************************/ + + /** Explicit numeric element assignment. + */ + template <typename R, typename T> + static void assignFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + MxArithmeticType<T>::value || MxCharType<T>::value, + T + >::type& value) { + if (mxIsComplex(array)) { + *(reinterpret_cast<R*>(mxGetPr(array)) + index) = value; + *(reinterpret_cast<R*>(mxGetPi(array)) + index) = 0.0; + } else { + *(reinterpret_cast<R*>(mxGetData(array)) + index) = value; + } + } + /** Explicit complex element assignment. + */ + template <typename R, typename T> + static void assignFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + MxComplexType<T>::value, + T + >::type& value) { + if (mxIsComplex(array)) { + *(reinterpret_cast<R*>(mxGetPr(array)) + index) = value.real(); + *(reinterpret_cast<R*>(mxGetPi(array)) + index) = value.imag(); + } else { + *(reinterpret_cast<R*>(mxGetData(array)) + index) = std::abs(value); + } + } + template <typename T> + static void assignCharFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + std::is_floating_point<T>::value, + T + >::type& value) { + *(mxGetChars(array) + index) = value; // whoever needs this... + } + template <typename T> + static void assignCharFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + std::is_integral<T>::value && + std::is_signed<T>::value, + T + >::type& value) { + *(mxGetChars(array) + index) = reinterpret_cast<const typename + std::make_unsigned<T>::type&>(value); + } + template <typename T> + static void assignCharFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + std::is_integral<T>::value && + !std::is_signed<T>::value, + T + >::type& value) { + *(mxGetChars(array) + index) = value; + } + + template <typename T> + static void assignCharFrom(mxArray* array, + mwIndex index, + const typename std::enable_if< + MxComplexType<T>::value, + T + >::type& value) { + *(mxGetChars(array) + index) = std::abs(value); // whoever needs it... + } + + /** Pointer to the mxArray C object. + */ + mxArray* array_; + /** Flag to enable resource management. + */ + bool owner_; +}; + +/*************************************************************/ +/** Templated mxArray importers **/ +/*************************************************************/ + +/** Fundamental numeric type. + */ +template <typename T> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxArithmeticType<T>::value, T>::type& value) { + mxArray* array = mxCreateNumericMatrix(1, + 1, + MxTypes<T>::class_id, + MxTypes<T>::complexity); + MEXPLUS_CHECK_NOTNULL(array); + *reinterpret_cast<T*>(mxGetData(array)) = value; + return array; +} + +/** Complex type, complex<float> or complex<double>. + */ +template <typename T> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxComplexType<T>::value, T>::type& value) { + mxArray* array = mxCreateNumericMatrix(1, 1, + MxTypes<T>::class_id, + MxTypes<T>::complexity); + MEXPLUS_CHECK_NOTNULL(array); + *reinterpret_cast<typename T::value_type*>(mxGetPr(array)) = value.real(); + *reinterpret_cast<typename T::value_type*>(mxGetPi(array)) = value.imag(); + + return array; +} + +/** Container with fundamental numerics, i.e. vector<double>. + */ +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxArithmeticCompound<Container>::value, Container>::type& value) { + typedef typename Container::value_type ValueType; + mxArray* array = mxCreateNumericMatrix(1, + value.size(), + MxTypes<ValueType>::class_id, + MxTypes<ValueType>::complexity); + MEXPLUS_CHECK_NOTNULL(array); + std::copy(value.begin(), + value.end(), + reinterpret_cast<ValueType*>(mxGetData(array))); + return array; +} + +/** Container with complex numbers, i.e. vector<complex<double>>. + */ +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxComplexCompound<Container>::value, Container>::type& value) { + typedef typename Container::value_type ContainerValueType; + typedef typename ContainerValueType::value_type ValueType; + mxArray* array = mxCreateNumericMatrix(1, + value.size(), + MxTypes<ContainerValueType>::class_id, + mxCOMPLEX); + MEXPLUS_CHECK_NOTNULL(array); + ValueType* real = reinterpret_cast<ValueType*>(mxGetPr(array)); + ValueType* imag = reinterpret_cast<ValueType*>(mxGetPi(array)); + typename Container::const_iterator it; + for (it = value.begin(); it != value.end(); it++) { + *real++ = (*it).real(); + *imag++ = (*it).imag(); + } + return array; +} + +template <typename T> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxCharType<T>::value, T>::type& value) { + const char char_array[] = {static_cast<char>(value), 0}; + mxArray* array = mxCreateString(char_array); + MEXPLUS_CHECK_NOTNULL(array); + return array; +} + +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + (MxCharCompound<Container>::value) && + (std::is_signed<typename Container::value_type>::value), + Container>::type& value) { + typedef typename std::make_unsigned<typename Container::value_type>::type + UnsignedValue; + const mwSize dimensions[] = {1, static_cast<mwSize>(value.size())}; + mxArray* array = mxCreateCharArray(2, dimensions); + MEXPLUS_CHECK_NOTNULL(array); + mxChar* array_data = mxGetChars(array); + for (typename Container::const_iterator it = value.begin(); + it != value.end(); + ++it) { + *(array_data++) = reinterpret_cast<const UnsignedValue&>(*it); + } + return array; +} + +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + (MxCharCompound<Container>::value) && + !(std::is_signed<typename Container::value_type>::value), + Container>::type& value) { + const mwSize dimensions[] = {1, static_cast<mwSize>(value.size())}; + mxArray* array = mxCreateCharArray(2, dimensions); + MEXPLUS_CHECK_NOTNULL(array); + std::copy(value.begin(), value.end(), mxGetChars(array)); + return array; +} + +template <typename T> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxLogicalType<T>::value, T>::type& value) { + mxArray* array = mxCreateLogicalScalar(value); + MEXPLUS_CHECK_NOTNULL(array); + return array; +} + +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxLogicalCompound<Container>::value, Container>::type& value) { + mxArray* array = mxCreateLogicalMatrix(1, value.size()); + MEXPLUS_CHECK_NOTNULL(array); + std::copy(value.begin(), value.end(), mxGetLogicals(array)); + return array; +} + +template <typename Container> +mxArray* MxArray::fromInternal(const typename std::enable_if< + MxCellCompound<Container>::value, Container>::type& value) { + mxArray* array = mxCreateCellMatrix(1, value.size()); + MEXPLUS_CHECK_NOTNULL(array); + mwIndex index = 0; + for (typename Container::const_iterator it = value.begin(); + it != value.end(); + ++it) { + mxArray* new_item = from(*it); // Safe in case if from() fails. + mxDestroyArray(mxGetCell(array, index)); + mxSetCell(array, index++, new_item); + } + return array; +} + +/*************************************************************/ +/** Templated mxArray exporters **/ +/*************************************************************/ + +/** Converter from numeric matrix to container. + */ +template <typename T> +void MxArray::toInternal(const mxArray* array, typename std::enable_if< + MxComplexOrArithmeticCompound<T>::value || + MxLogicalCompound<T>::value || + MxCharCompound<T>::value, T>::type* value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + switch (mxGetClassID(array)) { + case mxINT8_CLASS: assignTo<int8_t, T>(array, value); break; + case mxUINT8_CLASS: assignTo<uint8_t, T>(array, value); break; + case mxINT16_CLASS: assignTo<int16_t, T>(array, value); break; + case mxUINT16_CLASS: assignTo<uint16_t, T>(array, value); break; + case mxINT32_CLASS: assignTo<int32_t, T>(array, value); break; + case mxUINT32_CLASS: assignTo<uint32_t, T>(array, value); break; + case mxINT64_CLASS: assignTo<int64_t, T>(array, value); break; + case mxUINT64_CLASS: assignTo<uint64_t, T>(array, value); break; + case mxSINGLE_CLASS: assignTo<float, T>(array, value); break; + case mxDOUBLE_CLASS: assignTo<double, T>(array, value); break; + case mxLOGICAL_CLASS: assignTo<mxLogical, T>(array, value); break; + case mxCHAR_CLASS: assignStringTo<T>(array, value); break; + case mxCELL_CLASS: assignCellTo<T>(array, value); break; + // case mxSPARSE_CLASS: + default: + MEXPLUS_ERROR("Cannot convert %s.", mxGetClassName(array)); + } +} + +/** Converter from nested types to container. + */ +template <typename T> +void MxArray::toInternal(const mxArray* array, + typename std::enable_if< + MxCellType<T>::value && + (!std::is_compound<T>::value || + MxCellType<typename T::value_type>::value), + T + >::type* value) { + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(mxIsCell(array), "Expected a cell array."); + mwSize array_size = mxGetNumberOfElements(array); + value->resize(array_size); + for (size_t i = 0; i < array_size; ++i) { + const mxArray* element = mxGetCell(array, i); + (*value)[i] = to<typename T::value_type>(element); + } +} + +/*************************************************************/ +/** Templated mxArray getters **/ +/*************************************************************/ + +/** Converter from fundamental numeric or complex types. + */ +template <typename T> +void MxArray::atInternal(const mxArray* array, mwIndex index, + typename std::enable_if< + MxComplexOrArithmeticType<T>::value || + MxLogicalType<T>::value || + MxCharType<T>::value, T>::type* value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + switch (mxGetClassID(array)) { + case mxINT8_CLASS: assignTo<int8_t, T>(array, index, value); break; + case mxUINT8_CLASS: assignTo<uint8_t, T>(array, index, value); break; + case mxINT16_CLASS: assignTo<int16_t, T>(array, index, value); break; + case mxUINT16_CLASS: assignTo<uint16_t, T>(array, index, value); break; + case mxINT32_CLASS: assignTo<int32_t, T>(array, index, value); break; + case mxUINT32_CLASS: assignTo<uint32_t, T>(array, index, value); break; + case mxINT64_CLASS: assignTo<int64_t, T>(array, index, value); break; + case mxUINT64_CLASS: assignTo<uint64_t, T>(array, index, value); break; + case mxSINGLE_CLASS: assignTo<float, T>(array, index, value); break; + case mxDOUBLE_CLASS: assignTo<double, T>(array, index, value); break; + case mxLOGICAL_CLASS: assignTo<mxLogical, T>(array, index, value); break; + case mxCHAR_CLASS: assignCharTo<T>(array, index, value); break; + case mxCELL_CLASS: assignCellTo<T>(array, index, value); break; + // case mxSPARSE_CLASS: + default: + MEXPLUS_ASSERT(true, "Cannot convert %s", mxGetClassName(array)); + } +} + +template <typename T> +void MxArray::atInternal(const mxArray* array, mwIndex index, + typename std::enable_if< + std::is_compound<T>::value && + !MxComplexType<T>::value, T>::type* value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + MEXPLUS_ASSERT(mxIsCell(array), "Expected a cell array."); + const mxArray* element = mxGetCell(array, index); + to<T>(element, value); +} + +template <typename T> +void MxArray::atInternal(const mxArray* array, + const std::string& field, + mwIndex index, + T* value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_CHECK_NOTNULL(value); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + MEXPLUS_ASSERT(mxIsStruct(array), "Expected a struct array."); + const mxArray* element = mxGetField(array, index, field.c_str()); + MEXPLUS_ASSERT(element, "Invalid field name %s.", field.c_str()); + to<T>(element, value); +} + +/*************************************************************/ +/** Templated mxArray setters **/ +/*************************************************************/ + +/** Converter from fundamental numeric or complex types. + */ +template <typename T> +void MxArray::setInternal(mxArray* array, + mwIndex index, + const typename std::enable_if< + !std::is_compound<T>::value || + MxComplexType<T>::value, T>::type& value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + switch (mxGetClassID(array)) { + case mxINT8_CLASS: assignFrom<int8_t, T>(array, index, value); break; + case mxUINT8_CLASS: assignFrom<uint8_t, T>(array, index, value); break; + case mxINT16_CLASS: assignFrom<int16_t, T>(array, index, value); break; + case mxUINT16_CLASS: assignFrom<uint16_t, T>(array, index, value); break; + case mxINT32_CLASS: assignFrom<int32_t, T>(array, index, value); break; + case mxUINT32_CLASS: assignFrom<uint32_t, T>(array, index, value); break; + case mxINT64_CLASS: assignFrom<int64_t, T>(array, index, value); break; + case mxUINT64_CLASS: assignFrom<uint64_t, T>(array, index, value); break; + case mxSINGLE_CLASS: assignFrom<float, T>(array, index, value); break; + case mxDOUBLE_CLASS: assignFrom<double, T>(array, index, value); break; + case mxCHAR_CLASS: assignCharFrom<T>(array, index, value); break; + case mxLOGICAL_CLASS: assignFrom<mxLogical, T>(array, index, value); break; + case mxCELL_CLASS: { + mxArray* new_item = from(value); // Safe in case if from() fails. + + mxDestroyArray(mxGetCell(array, index)); + mxSetCell(array, index, new_item); + break; + } + default: + MEXPLUS_ERROR("Cannot assign to %s array.", mxGetClassName(array)); + } +} + +/** Converter from fundamental numeric or complex types. + */ +template <typename T> +void MxArray::setInternal(mxArray* array, + mwIndex index, + const typename std::enable_if< + MxCellType<T>::value, T>::type& value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + MEXPLUS_ASSERT(mxIsCell(array), "Expected a cell array."); + mxArray* new_item = from(value); // Safe in case if from() fails. + mxDestroyArray(mxGetCell(array, index)); + mxSetCell(array, index, new_item); +} + +template <typename T> +void MxArray::setInternal(mxArray* array, + const std::string& field, + mwIndex index, + const T& value) { + MEXPLUS_CHECK_NOTNULL(array); + MEXPLUS_ASSERT(static_cast<size_t>(index) < mxGetNumberOfElements(array), + "Index out of range: %u.", + index); + MEXPLUS_ASSERT(mxIsStruct(array), "Expected a struct array."); + int field_number = mxGetFieldNumber(array, field.c_str()); + if (field_number < 0) { + field_number = mxAddField(array, field.c_str()); + MEXPLUS_ASSERT(field_number >= 0, + "Failed to create a field '%s'", + field.c_str()); + } + mxArray* new_item = from(value); + mxDestroyArray(mxGetFieldByNumber(array, index, field_number)); + mxSetFieldByNumber(array, index, field_number, new_item); +} + +template <typename T> +mxArray* MxArray::Numeric(int rows, int columns) { + typedef typename std::enable_if< + MxComplexOrArithmeticType<T>::value, T>::type Scalar; + mxArray* numeric = mxCreateNumericMatrix(rows, + columns, + MxTypes<Scalar>::class_id, + MxTypes<Scalar>::complexity); + MEXPLUS_CHECK_NOTNULL(numeric); + return numeric; +} + +template <typename T> +mxArray* MxArray::Numeric(std::vector<std::size_t> dims) { + typedef typename std::enable_if< + MxComplexOrArithmeticType<T>::value, T>::type Scalar; + mxArray* numeric = mxCreateNumericArray(dims.size(), + &dims[0], + MxTypes<Scalar>::class_id, + MxTypes<Scalar>::complexity); + MEXPLUS_CHECK_NOTNULL(numeric); + return numeric; +} + +template <typename T> +T* MxArray::getData() const { + MEXPLUS_CHECK_NOTNULL(array_); + MEXPLUS_ASSERT(MxTypes<T>::class_id == classID(), + "Expected a %s array.", + typeid(T).name()); + return reinterpret_cast<T*>(mxGetData(array_)); +} + +template <typename T> +T* MxArray::getImagData() const { + MEXPLUS_CHECK_NOTNULL(array_); + MEXPLUS_ASSERT(MxTypes<T>::class_id == classID(), + "Expected a %s array.", + typeid(T).name()); + return reinterpret_cast<T*>(mxGetPi(array_)); +} + +template <typename T> +T MxArray::at(mwIndex row, mwIndex column) const { + return at<T>(subscriptIndex(row, column)); +} + +template <typename T> +T MxArray::at(const std::vector<mwIndex>& subscripts) const { + return at<T>(subscriptIndex(subscripts)); +} + +template <typename T> +void MxArray::set(mwIndex row, mwIndex column, const T& value) { + set<T>(subscriptIndex(row, column), value); +} + +template <typename T> +void MxArray::set(const std::vector<mwIndex>& subscripts, const T& value) { + set<T>(subscriptIndex(subscripts), value); +} + +} // namespace mexplus + +#endif // INCLUDE_MEXPLUS_MXARRAY_H_ diff --git a/wrapper_matlab/mxtypes.h b/wrapper_matlab/mxtypes.h new file mode 100644 index 0000000000000000000000000000000000000000..bc8c1aa370f776d65b68ba67550b4c36dc014830 --- /dev/null +++ b/wrapper_matlab/mxtypes.h @@ -0,0 +1,345 @@ +/** MxTypes and other type traits for template. + * + * Copyright 2014 Kota Yamaguchi. + */ + +#ifndef INCLUDE_MEXPLUS_MXTYPES_H_ +#define INCLUDE_MEXPLUS_MXTYPES_H_ + +#include <mex.h> +#include <complex> +#include <type_traits> + +namespace mexplus { + +/************************************************************/ +/* Traits for fundamental datatypes. + Don't use with function templates due to type promotion! + (Ignore it and get PITA!) */ +/************************************************************/ + +/** Traits for mxLogical-convertibles. + */ +template <typename T, typename U = T> +struct MxLogicalTy : std::false_type {}; + +template <typename T> +struct MxLogicalTy<T, typename std::enable_if< + std::is_same<typename std::remove_cv<T>::type, bool>::value || + std::is_same<typename std::remove_cv<T>::type, mxLogical>::value, + T>::type> : std::true_type {}; + +/** Traits for mxChar-convertibles. + * + * Treat them as an integer types when they are specified signed or unsigned, + * because uint8_t is exactly unsigned char and there is no way to tell them + * apart. + */ +template <typename T, typename U = T> +struct MxCharTy : std::false_type {}; + +template <typename T> +struct MxCharTy<T, typename std::enable_if< + std::is_same<typename std::remove_cv<T>::type, char>::value || + // Visual Studio cannot distinguish these from uint. + // std::is_same<typename std::remove_cv<T>::type, char16_t>::value || + // std::is_same<typename std::remove_cv<T>::type, char32_t>::value || + std::is_same<typename std::remove_cv<T>::type, mxChar>::value || + std::is_same<typename std::remove_cv<T>::type, wchar_t>::value, + T>::type> : std::true_type {}; + +/** Traits for integer numerics. + */ +template <typename T, typename U = T> +struct MxIntTy : std::false_type {}; +template <typename T> +struct MxIntTy<T, typename std::enable_if< + std::is_integral<T>::value && + !MxLogicalTy<T>::value && + !MxCharTy<T>::value, + T>::type> : std::true_type {}; +/** Traits for arithmetic types. + */ +template <typename T, typename U = T> +struct MxArithmeticTy : std::false_type {}; +template <typename T> +struct MxArithmeticTy<T, typename std::enable_if< + (std::is_floating_point<T>::value) || (MxIntTy<T>::value), + T>::type> : std::true_type {}; + +/**********************************************/ +/* Introducing traits for MATLAB array types. */ +/**********************************************/ + +typedef struct mxNumeric_tag {} mxNumeric; +typedef struct mxCell_tag {} mxCell; +typedef struct mxComplex_tag {} mxComplex; +// mxLogical already defined in MATLAB (matrix.h). + +/** Traits for mxArray. + */ +template <typename T, typename U = T> +struct MxTypes { + typedef T type; + typedef mxCell array_type; + static const mxClassID class_id = mxUNKNOWN_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<MxCharTy<T>::value, T>::type> { + typedef T type; + typedef mxChar array_type; + static const mxClassID class_id = mxCHAR_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<MxLogicalTy<T>::value, T>::type> { + typedef T type; + typedef mxLogical array_type; + static const mxClassID class_id = mxLOGICAL_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_signed<T>::value && + MxIntTy<T>::value && + sizeof(T) == 1, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxINT8_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_unsigned<T>::value && + MxIntTy<T>::value && + sizeof(T) == 1, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxUINT8_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_signed<T>::value && + MxIntTy<T>::value && + sizeof(T) == 2, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxINT16_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_unsigned<T>::value && + MxIntTy<T>::value && + sizeof(T) == 2, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxUINT16_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_signed<T>::value && + MxIntTy<T>::value && + sizeof(T) == 4, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxINT32_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_unsigned<T>::value && + MxIntTy<T>::value && + sizeof(T) == 4, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxUINT32_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_signed<T>::value && + MxIntTy<T>::value && + sizeof(T) == 8, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxINT64_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_unsigned<T>::value && + MxIntTy<T>::value && + sizeof(T) == 8, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxUINT64_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_floating_point<T>::value && + sizeof(T) == 4, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxSINGLE_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if<std::is_floating_point<T>::value && + sizeof(T) == 8, T>::type> { + typedef T type; + typedef mxNumeric array_type; + static const mxClassID class_id = mxDOUBLE_CLASS; + static const mxComplexity complexity = mxREAL; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if< + std::is_same<typename std::remove_cv<T>::type, + std::complex<float>>::value, + T>::type> { + typedef T type; + typedef mxComplex array_type; + static const mxClassID class_id = mxSINGLE_CLASS; + static const mxComplexity complexity = mxCOMPLEX; +}; + +template <typename T> +struct MxTypes<T, typename std::enable_if< + std::is_same<typename std::remove_cv<T>::type, + std::complex<double>>::value, + T>::type> { + typedef T type; + typedef mxComplex array_type; + static const mxClassID class_id = mxDOUBLE_CLASS; + static const mxComplexity complexity = mxCOMPLEX; +}; + +/********************************************/ +/* Type traits for function template usage. */ +/********************************************/ + +/* Traits for logical types. + */ +template <typename T, typename U = T> +struct MxLogicalType : std::false_type {}; +template<typename T> +struct MxLogicalType<T, typename std::enable_if< + std::is_same<typename MxTypes<T>::array_type, mxLogical>::value, + T>::type> : std::true_type {}; + +/* Traits for char types. + */ +template <typename T, typename U = T> +struct MxCharType : std::false_type {}; +template<typename T> +struct MxCharType<T, typename std::enable_if< + std::is_same<typename MxTypes<T>::array_type, mxChar>::value, + T>::type> : std::true_type {}; + +/* Traits for arithmetic types. + */ +template <typename T, typename U = T> +struct MxArithmeticType : std::false_type {}; +template<typename T> +struct MxArithmeticType<T, typename std::enable_if< + std::is_same<typename MxTypes<T>::array_type, mxNumeric>::value, + T>::type> : std::true_type {}; + +/* Traits for complex types. + */ +template <typename T, typename U = T> +struct MxComplexType : std::false_type {}; +template<typename T> +struct MxComplexType<T, typename std::enable_if< + std::is_same<typename MxTypes<T>::array_type, mxComplex>::value, + T>::type> : std::true_type {}; + +/* Traits for complex or arithmetic types. + */ +template <typename T, typename U = T> +struct MxComplexOrArithmeticType : std::false_type {}; +template <typename T> +struct MxComplexOrArithmeticType<T, typename std::enable_if< + MxComplexType<T>::value, + T>::type> : std::true_type {}; +template <typename T> +struct MxComplexOrArithmeticType<T, typename std::enable_if< + MxArithmeticTy<T>::value, + T>::type> : std::true_type {}; + +/* Traits for cell types. + */ +template <typename T, typename U = T> +struct MxCellType : std::false_type {}; +template <typename T> +struct MxCellType<T, typename std::enable_if< + std::is_same<typename MxTypes<T>::array_type, mxCell>::value, + T>::type> : std::true_type {}; + +/* Traits for logical type compounds. + */ +template <typename T, typename U = T> +struct MxLogicalCompound : std::false_type {}; +template <typename T> +struct MxLogicalCompound<T, typename std::enable_if< + MxLogicalType<typename T::value_type>::value, + T>::type> : std::true_type {}; + +/* Traits for char type compounds. + */ +template <typename T, typename U = T> +struct MxCharCompound : std::false_type {}; +template <typename T> +struct MxCharCompound<T, typename std::enable_if< + MxCharType<typename T::value_type>::value, + T>::type> : std::true_type {}; + +/* Traits for arithmetic type compounds. + */ +template <typename T, typename U = T> +struct MxArithmeticCompound : std::false_type {}; +template <typename T> +struct MxArithmeticCompound<T, typename std::enable_if< + (MxArithmeticType<typename T::value_type>::value) && + !(MxComplexType<T>::value), + T>::type> : std::true_type {}; + +/* Traits for complex type compounds. + */ +template <typename T, typename U = T> +struct MxComplexCompound : std::false_type {}; +template <typename T> +struct MxComplexCompound<T, typename std::enable_if< + MxComplexType<typename T::value_type>::value, + T>::type> : std::true_type {}; + +/* Traits for complex or arithmetic type compounds. + */ +template <typename T, typename U = T> +struct MxComplexOrArithmeticCompound : std::false_type {}; +template <typename T> +struct MxComplexOrArithmeticCompound<T, typename std::enable_if< + MxComplexCompound<T>::value || + MxArithmeticCompound<T>::value, + T>::type> : std::true_type {}; + +/* Traits for cell compounds. + */ +template <typename T, typename U = T> +struct MxCellCompound : std::false_type {}; +template <typename T> +struct MxCellCompound<T, typename std::enable_if< + MxCellType<typename T::value_type>::value, + T>::type> : std::true_type {}; + +} // namespace mexplus + +#endif // INCLUDE_MEXPLUS_MXTYPES_H_ diff --git a/wrapper_matlab/run_demo.m b/wrapper_matlab/run_demo.m new file mode 100644 index 0000000000000000000000000000000000000000..e27174dfa82de5f47c9b8d68efeb5fb6ddcb3e16 --- /dev/null +++ b/wrapper_matlab/run_demo.m @@ -0,0 +1,49 @@ +%% Compile the BGSLibrary wrapper +compile; + +%% Run demo +demo; + +%% Run a specific algorithm +demo('FrameDifference') +% demo('StaticFrameDifference') +% demo('WeightedMovingMean') +% demo('WeightedMovingVariance') +% demo('MixtureOfGaussianV1') % only for OpenCV 2.x +% demo('MixtureOfGaussianV2') +% demo('AdaptiveBackgroundLearning') +% demo('AdaptiveSelectiveBackgroundLearning') +% demo('GMG') % only on OpenCV >= 2.4.3 +% demo('KNN') % only on OpenCV 3.x +% demo('DPAdaptiveMedian') +% demo('DPGrimsonGMM') +% demo('DPZivkovicAGMM') +% demo('DPMean') +% demo('DPWrenGA') +% demo('DPPratiMediod') +% demo('DPEigenbackground') +% demo('DPTexture') +% demo('T2FGMM_UM') +% demo('T2FGMM_UV') +% demo('T2FMRF_UM') +% demo('T2FMRF_UV') +% demo('FuzzySugenoIntegral') +% demo('FuzzyChoquetIntegral') +% demo('LBSimpleGaussian') +% demo('LBFuzzyGaussian') +% demo('LBMixtureOfGaussians') +% demo('LBAdaptiveSOM') +% demo('LBFuzzyAdaptiveSOM') +% demo('LBP_MRF') +% demo('MultiLayer') +% demo('PixelBasedAdaptiveSegmenter') +% demo('VuMeter') +% demo('KDE') +% demo('IndependentMultimodal') +% demo('MultiCue') +% demo('SigmaDelta') +% demo('SuBSENSE') +% demo('LOBSTER') +% demo('PAWCS') +% demo('TwoPoints') +% demo('ViBe') \ 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..edb75a8552bbc29d4e27ef72485d7859e38851c8 --- /dev/null +++ b/wrapper_python/bgslibrary_module.cpp @@ -0,0 +1,265 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..6050f6b40e5815670d2f2f8383381642ee2fd413 --- /dev/null +++ b/wrapper_python/np_opencv_converter.cpp @@ -0,0 +1,103 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..68386f0f16c8855ff0c0b7c74dac2a58ea9b6438 --- /dev/null +++ b/wrapper_python/np_opencv_converter.h @@ -0,0 +1,122 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..3db5613a9e4a1f694fbbf008c2c0c6d0913eb730 --- /dev/null +++ b/wrapper_python/utils/container.h @@ -0,0 +1,208 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..7ca21dd59b201947fb16ff6bf60c18a04073998e --- /dev/null +++ b/wrapper_python/utils/conversion.cpp @@ -0,0 +1,349 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..8ce616dbcd540e9842de24d4ec04d780f0c04e80 --- /dev/null +++ b/wrapper_python/utils/conversion.h @@ -0,0 +1,75 @@ +/* +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 new file mode 100644 index 0000000000000000000000000000000000000000..3f0b535a8df7b92d645d63787787900644f77f56 --- /dev/null +++ b/wrapper_python/utils/template.h @@ -0,0 +1,44 @@ +/* +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); + } + +};