diff --git a/Demo.cpp b/Demo.cpp index fec54d85fe804e6bece7ec0bd1e6d5c2b7fe7626..f1022a50c5b140a0a94bfa3e07cc4cf8ff0c0186 100644 --- a/Demo.cpp +++ b/Demo.cpp @@ -84,6 +84,7 @@ int main(int argc, char **argv) //bgs = new PAWCS; //bgs = new TwoPoints; //bgs = new ViBe; + //bgs = new CodeBook; int key = 0; cv::Mat img_input; diff --git a/Demo.py b/Demo.py index 71bc35232e73fe4ff54b70d40d3690b274c31af7..b1f6c02e954144f25b9b08dd6725c42afe665766 100644 --- a/Demo.py +++ b/Demo.py @@ -71,7 +71,7 @@ while True: else: capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1) - print "frame is not ready" + print "Frame is not ready" cv2.waitKey(1000) # break diff --git a/Demo2.cpp b/Demo2.cpp index 22c6ffc36d5100967cfd2873b82f0bdb13b61268..75c906beedcd2be7de7a66377bb501234ee8d960 100644 --- a/Demo2.cpp +++ b/Demo2.cpp @@ -68,6 +68,7 @@ int main(int argc, char **argv) //bgs = new PAWCS; //bgs = new TwoPoints; //bgs = new ViBe; + //bgs = new CodeBook; int frameNumber = 1; int key = 0; diff --git a/FrameProcessor.cpp b/FrameProcessor.cpp index 50881219f6d4bf5e703840f3912204b006777686..3180589a6cab0d8c29399530a645f6c8d0d30f65 100644 --- a/FrameProcessor.cpp +++ b/FrameProcessor.cpp @@ -65,6 +65,11 @@ namespace bgslibrary gmg = new GMG; #endif +#if CV_MAJOR_VERSION == 3 + if (enableKNN) + knn = new KNN; +#endif + if (enableDPAdaptiveMedian) dpAdaptiveMedian = new DPAdaptiveMedian; @@ -125,10 +130,8 @@ namespace bgslibrary if (enableLbpMrf) lbpMrf = new LBP_MRF; -#if CV_MAJOR_VERSION == 2 if (enableMultiLayer) multiLayer = new MultiLayer; -#endif if (enablePBAS) pixelBasedAdaptiveSegmenter = new PixelBasedAdaptiveSegmenter; @@ -154,6 +157,18 @@ namespace bgslibrary if (enableLOBSTER) lobster = new LOBSTER; + if (enablePAWCS) + pawcs = new PAWCS; + + if (enableTwoPoints) + twoPoints = new TwoPoints; + + if (enableViBe) + vibe = new ViBe; + + if (enableCodeBook) + codeBook = new CodeBook; + if (enableForegroundMaskAnalysis) foregroundMaskAnalysis = new ForegroundMaskAnalysis; } @@ -205,6 +220,11 @@ namespace bgslibrary process("GMG", gmg, img_preProcessor, img_gmg); #endif +#if CV_MAJOR_VERSION == 3 + if (enableKNN) + process("KNN", knn, img_preProcessor, img_knn); +#endif + if (enableDPAdaptiveMedian) process("DPAdaptiveMedian", dpAdaptiveMedian, img_preProcessor, img_dpAdaptiveMedian); @@ -265,14 +285,12 @@ namespace bgslibrary if (enableLbpMrf) process("LbpMrf", lbpMrf, img_preProcessor, img_lbpMrf); -#if CV_MAJOR_VERSION == 2 if (enableMultiLayer) { multiLayer->setStatus(MultiLayer::MLBGS_LEARN); //multiLayer->setStatus(MultiLayer::MLBGS_DETECT); process("MultiLayer", multiLayer, img_preProcessor, img_multiLayer); } -#endif if (enablePBAS) process("PBAS", pixelBasedAdaptiveSegmenter, img_preProcessor, img_pixelBasedAdaptiveSegmenter); @@ -298,6 +316,18 @@ namespace bgslibrary if (enableLOBSTER) process("LOBSTER", lobster, img_preProcessor, img_lobster); + if (enablePAWCS) + process("PAWCS", pawcs, img_preProcessor, img_pawcs); + + if (enableTwoPoints) + process("TwoPoints", twoPoints, img_preProcessor, img_twoPoints); + + if (enableViBe) + process("ViBe", vibe, img_preProcessor, img_vibe); + + if (enableCodeBook) + process("CodeBook", codeBook, img_preProcessor, img_codeBook); + if (enableForegroundMaskAnalysis) { foregroundMaskAnalysis->stopAt = frameToStop; @@ -314,6 +344,9 @@ namespace bgslibrary 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 +#if CV_MAJOR_VERSION == 3 + foregroundMaskAnalysis->process(frameNumber, "KNN", img_knn); #endif foregroundMaskAnalysis->process(frameNumber, "DPAdaptiveMedian", img_dpAdaptiveMedian); foregroundMaskAnalysis->process(frameNumber, "DPGrimsonGMM", img_dpGrimsonGMM); @@ -335,9 +368,7 @@ namespace bgslibrary 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); @@ -346,6 +377,10 @@ namespace bgslibrary foregroundMaskAnalysis->process(frameNumber, "SigmaDelta", img_sigmaDelta); foregroundMaskAnalysis->process(frameNumber, "SuBSENSE", img_subSENSE); foregroundMaskAnalysis->process(frameNumber, "LOBSTER", img_lobster); + foregroundMaskAnalysis->process(frameNumber, "PAWCS", img_pawcs); + foregroundMaskAnalysis->process(frameNumber, "TwoPoints", img_twoPoints); + foregroundMaskAnalysis->process(frameNumber, "ViBe", img_vibe); + foregroundMaskAnalysis->process(frameNumber, "CodeBook", img_codeBook); } firstTime = false; @@ -374,6 +409,18 @@ namespace bgslibrary if (enableForegroundMaskAnalysis) delete foregroundMaskAnalysis; + if (enableCodeBook) + delete codeBook; + + if (enableViBe) + delete vibe; + + if (enableTwoPoints) + delete twoPoints; + + if (enablePAWCS) + delete pawcs; + if (enableLOBSTER) delete lobster; @@ -398,10 +445,8 @@ namespace bgslibrary if (enablePBAS) delete pixelBasedAdaptiveSegmenter; -#if CV_MAJOR_VERSION == 2 if (enableMultiLayer) delete multiLayer; -#endif if (enableLBFuzzyAdaptiveSOM) delete lbFuzzyAdaptiveSOM; @@ -418,10 +463,8 @@ namespace bgslibrary if (enableLBSimpleGaussian) delete lbSimpleGaussian; -#if !defined(_WIN32) if (enableLbpMrf) delete lbpMrf; -#endif if (enableFuzzyChoquetIntegral) delete fuzzyChoquetIntegral; @@ -470,6 +513,11 @@ namespace bgslibrary delete gmg; #endif +#if CV_MAJOR_VERSION == 3 + if (enableKNN) + delete knn; +#endif + if (enableAdaptiveBackgroundLearning) delete adaptiveBackgroundLearning; @@ -531,6 +579,9 @@ namespace bgslibrary #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 cvWriteInt(fs, "enableGMG", enableGMG); #endif +#if CV_MAJOR_VERSION == 3 + cvWriteInt(fs, "enableKNN", enableKNN); +#endif cvWriteInt(fs, "enableDPAdaptiveMedian", enableDPAdaptiveMedian); cvWriteInt(fs, "enableDPGrimsonGMM", enableDPGrimsonGMM); @@ -555,10 +606,7 @@ namespace bgslibrary cvWriteInt(fs, "enableLBFuzzyAdaptiveSOM", enableLBFuzzyAdaptiveSOM); cvWriteInt(fs, "enableLbpMrf", enableLbpMrf); - -#if CV_MAJOR_VERSION == 2 cvWriteInt(fs, "enableMultiLayer", enableMultiLayer); -#endif cvWriteInt(fs, "enablePBAS", enablePBAS); cvWriteInt(fs, "enableVuMeter", enableVuMeter); cvWriteInt(fs, "enableKDE", enableKDE); @@ -567,6 +615,10 @@ namespace bgslibrary cvWriteInt(fs, "enableSigmaDelta", enableSigmaDelta); cvWriteInt(fs, "enableSuBSENSE", enableSuBSENSE); cvWriteInt(fs, "enableLOBSTER", enableLOBSTER); + cvWriteInt(fs, "enablePAWCS", enablePAWCS); + cvWriteInt(fs, "enableTwoPoints", enableTwoPoints); + cvWriteInt(fs, "enableViBe", enableViBe); + cvWriteInt(fs, "enableCodeBook", enableCodeBook); cvReleaseFileStorage(&fs); } @@ -593,6 +645,9 @@ namespace bgslibrary #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >= 4 && CV_SUBMINOR_VERSION >= 3 enableGMG = cvReadIntByName(fs, 0, "enableGMG", false); #endif +#if CV_MAJOR_VERSION == 3 + enableKNN = cvReadIntByName(fs, 0, "enableKNN", false); +#endif enableDPAdaptiveMedian = cvReadIntByName(fs, 0, "enableDPAdaptiveMedian", false); enableDPGrimsonGMM = cvReadIntByName(fs, 0, "enableDPGrimsonGMM", false); @@ -617,10 +672,7 @@ namespace bgslibrary enableLBFuzzyAdaptiveSOM = cvReadIntByName(fs, 0, "enableLBFuzzyAdaptiveSOM", false); enableLbpMrf = cvReadIntByName(fs, 0, "enableLbpMrf", false); - -#if CV_MAJOR_VERSION == 2 enableMultiLayer = cvReadIntByName(fs, 0, "enableMultiLayer", false); -#endif enablePBAS = cvReadIntByName(fs, 0, "enablePBAS", false); enableVuMeter = cvReadIntByName(fs, 0, "enableVuMeter", false); enableKDE = cvReadIntByName(fs, 0, "enableKDE", false); @@ -629,6 +681,10 @@ namespace bgslibrary enableSigmaDelta = cvReadIntByName(fs, 0, "enableSigmaDelta", false); enableSuBSENSE = cvReadIntByName(fs, 0, "enableSuBSENSE", false); enableLOBSTER = cvReadIntByName(fs, 0, "enableLOBSTER", false); + enablePAWCS = cvReadIntByName(fs, 0, "enablePAWCS", false); + enableTwoPoints = cvReadIntByName(fs, 0, "enableTwoPoints", false); + enableViBe = cvReadIntByName(fs, 0, "enableViBe", false); + enableCodeBook = cvReadIntByName(fs, 0, "enableCodeBook", false); cvReleaseFileStorage(&fs); } diff --git a/FrameProcessor.h b/FrameProcessor.h index 228fa4c0e8a8b57f0d1a345f0d35700c25a60715..025984a56c4e422d366edfd9cf76ed42bcbf8f39 100644 --- a/FrameProcessor.h +++ b/FrameProcessor.h @@ -75,6 +75,12 @@ namespace bgslibrary bool enableGMG; #endif +#if CV_MAJOR_VERSION == 3 + cv::Mat img_knn; + KNN* knn; + bool enableKNN; +#endif + cv::Mat img_dpAdaptiveMedian; DPAdaptiveMedian* dpAdaptiveMedian; bool enableDPAdaptiveMedian; @@ -155,11 +161,9 @@ namespace bgslibrary LBP_MRF* lbpMrf; bool enableLbpMrf; -#if CV_MAJOR_VERSION == 2 cv::Mat img_multiLayer; MultiLayer* multiLayer; bool enableMultiLayer; -#endif cv::Mat img_pixelBasedAdaptiveSegmenter; PixelBasedAdaptiveSegmenter* pixelBasedAdaptiveSegmenter; @@ -193,6 +197,22 @@ namespace bgslibrary LOBSTER* lobster; bool enableLOBSTER; + cv::Mat img_pawcs; + PAWCS* pawcs; + bool enablePAWCS; + + cv::Mat img_twoPoints; + TwoPoints* twoPoints; + bool enableTwoPoints; + + cv::Mat img_vibe; + ViBe* vibe; + bool enableViBe; + + cv::Mat img_codeBook; + CodeBook* codeBook; + bool enableCodeBook; + ForegroundMaskAnalysis* foregroundMaskAnalysis; bool enableForegroundMaskAnalysis; diff --git a/VideoCapture.cpp b/VideoCapture.cpp index b302a3f5e2921bef2c1424819f244efd5b76ac18..c7e12ea13739f5c6872af4477cf252d996be3898 100644 --- a/VideoCapture.cpp +++ b/VideoCapture.cpp @@ -82,6 +82,7 @@ namespace bgslibrary enableFlip(false), cameraIndex(0) { std::cout << "VideoCapture()" << std::endl; + setup("./config/VideoCapture.xml"); } VideoCapture::~VideoCapture() @@ -94,11 +95,10 @@ namespace bgslibrary frameProcessor = frameProcessorPtr; } - void VideoCapture::setCamera(int index) + void VideoCapture::setCamera(int _index) { useCamera = true; - cameraIndex = index; - + cameraIndex = _index; useVideo = false; } @@ -111,11 +111,10 @@ namespace bgslibrary std::cerr << "Cannot initialize webcam!\n" << std::endl; } - void VideoCapture::setVideo(std::string filename) + void VideoCapture::setVideo(std::string _filename) { useVideo = true; - videoFileName = filename; - + videoFileName = _filename; useCamera = false; } @@ -132,43 +131,49 @@ namespace bgslibrary void VideoCapture::start() { - loadConfig(); - if (useCamera) setUpCamera(); if (useVideo) setUpVideo(); //if (!capture) std::cerr << "Capture error..." << std::endl; + using namespace std::chrono_literals; + do + { + capture >> frame; + if (frame.empty()) + { + std::cout << "Frame is not ready" << std::endl; + std::this_thread::sleep_for(1s); + } + else + break; + } while (1); + int input_fps = capture.get(CV_CAP_PROP_FPS); std::cout << "input->fps:" << input_fps << std::endl; + std::cout << "input->width:" << frame.size().width << std::endl; + std::cout << "input->height:" << frame.size().height << std::endl; - /* - IplImage* frame1 = cvQueryFrame(capture); - frame = cvCreateImage(cvSize( - (int)((frame1->width*input_resize_percent) / 100), - (int)((frame1->height*input_resize_percent) / 100)), frame1->depth, frame1->nChannels); - //cvCreateImage(cvSize(frame1->width/input_resize_factor, frame1->height/input_resize_factor), frame1->depth, frame1->nChannels); - std::cout << "input->resize_percent:" << input_resize_percent << std::endl; - std::cout << "input->width:" << frame->width << std::endl; - std::cout << "input->height:" << frame->height << std::endl; - */ - - double loopDelay = 33.333; if (input_fps > 0) loopDelay = (1. / input_fps)*1000.; std::cout << "loopDelay:" << loopDelay << std::endl; std::cout << "Press 'ESC' to stop..." << std::endl; - bool firstTime = true; do { frameNumber++; - cv::Mat frame; capture >> frame; if (frame.empty()) break; - //cvResize(frame1, frame); + cv::resize(frame, frame, cv::Size(), input_resize_percent/100., input_resize_percent / 100.); + if (firstTime && input_resize_percent != 100) + { + std::cout << "Resized to:" << std::endl; + std::cout << "input->width:" << frame.size().width << std::endl; + std::cout << "input->height:" << frame.size().height << std::endl; + } + //if (enableFlip) // cvFlip(frame, frame, 0); @@ -178,7 +183,6 @@ namespace bgslibrary do { - //cv::Mat img_input = cv::cvarrToMat(frame); cv::Mat img_input; frame.copyTo(img_input); @@ -220,16 +224,12 @@ namespace bgslibrary frame = frame(roi); } - //cv::Mat img_input = cv::cvarrToMat(frame); cv::Mat img_input; frame.copyTo(img_input); if (showOutput) cv::imshow("Input", img_input); - if (firstTime) - saveConfig(); - start_time = cv::getTickCount(); frameProcessor->process(img_input); int64 delta_time = cv::getTickCount() - start_time; @@ -259,7 +259,7 @@ namespace bgslibrary void VideoCapture::saveConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_WRITE); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), 0, CV_STORAGE_WRITE); cvWriteInt(fs, "stopAt", stopAt); cvWriteInt(fs, "input_resize_percent", input_resize_percent); @@ -277,18 +277,18 @@ namespace bgslibrary void VideoCapture::loadConfig() { - CvFileStorage* fs = cvOpenFileStorage("./config/VideoCapture.xml", 0, CV_STORAGE_READ); - - stopAt = cvReadIntByName(fs, 0, "stopAt", 0); - input_resize_percent = cvReadIntByName(fs, 0, "input_resize_percent", 100); - enableFlip = cvReadIntByName(fs, 0, "enableFlip", false); - VC_ROI::use_roi = cvReadIntByName(fs, 0, "use_roi", true); - VC_ROI::roi_defined = cvReadIntByName(fs, 0, "roi_defined", false); - VC_ROI::roi_x0 = cvReadIntByName(fs, 0, "roi_x0", 0); - VC_ROI::roi_y0 = cvReadIntByName(fs, 0, "roi_y0", 0); - VC_ROI::roi_x1 = cvReadIntByName(fs, 0, "roi_x1", 0); - VC_ROI::roi_y1 = cvReadIntByName(fs, 0, "roi_y1", 0); - showOutput = cvReadIntByName(fs, 0, "showOutput", true); + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); + + stopAt = cvReadIntByName(fs, nullptr, "stopAt", 0); + input_resize_percent = cvReadIntByName(fs, nullptr, "input_resize_percent", 100); + enableFlip = cvReadIntByName(fs, nullptr, "enableFlip", false); + VC_ROI::use_roi = cvReadIntByName(fs, nullptr, "use_roi", true); + VC_ROI::roi_defined = cvReadIntByName(fs, nullptr, "roi_defined", false); + VC_ROI::roi_x0 = cvReadIntByName(fs, nullptr, "roi_x0", 0); + VC_ROI::roi_y0 = cvReadIntByName(fs, nullptr, "roi_y0", 0); + VC_ROI::roi_x1 = cvReadIntByName(fs, nullptr, "roi_x1", 0); + VC_ROI::roi_y1 = cvReadIntByName(fs, nullptr, "roi_y1", 0); + showOutput = cvReadIntByName(fs, nullptr, "showOutput", true); cvReleaseFileStorage(&fs); } diff --git a/VideoCapture.h b/VideoCapture.h index 0e88c87023b8fedbb4f089e0bf19dfc0222c3d28..b7876824cde2b2b5f27641f1cff785d620d61091 100644 --- a/VideoCapture.h +++ b/VideoCapture.h @@ -17,6 +17,8 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #pragma once #include <iostream> +#include <chrono> +#include <thread> #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc_c.h> #include <opencv2/imgproc/types_c.h> @@ -31,13 +33,13 @@ namespace bgslibrary private: IFrameProcessor* frameProcessor; cv::VideoCapture capture; - IplImage* frame; + cv::Mat frame; int key; int64 start_time; int64 delta_time; double freq; double fps; - long frameNumber; + long long frameNumber; long stopAt; bool useCamera; int cameraIndex; @@ -46,6 +48,17 @@ namespace bgslibrary int input_resize_percent; bool showOutput; bool enableFlip; + double loopDelay = 33.333; + bool firstTime = true; + 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(); + } + } public: VideoCapture(); diff --git a/config/FrameProcessor.xml b/config/FrameProcessor.xml index 3cf398cc4f421bd0c42bf3a19631c425af5add42..91c3466779fc01c8d430647f83078928d477a6e1 100644 --- a/config/FrameProcessor.xml +++ b/config/FrameProcessor.xml @@ -7,10 +7,9 @@ <enableStaticFrameDifference>0</enableStaticFrameDifference> <enableWeightedMovingMean>0</enableWeightedMovingMean> <enableWeightedMovingVariance>0</enableWeightedMovingVariance> -<enableMixtureOfGaussianV1>0</enableMixtureOfGaussianV1> <enableMixtureOfGaussianV2>0</enableMixtureOfGaussianV2> <enableAdaptiveBackgroundLearning>0</enableAdaptiveBackgroundLearning> -<enableGMG>0</enableGMG> +<enableKNN>0</enableKNN> <enableDPAdaptiveMedian>0</enableDPAdaptiveMedian> <enableDPGrimsonGMM>0</enableDPGrimsonGMM> <enableDPZivkovicAGMM>0</enableDPZivkovicAGMM> @@ -40,4 +39,8 @@ <enableSigmaDelta>0</enableSigmaDelta> <enableSuBSENSE>0</enableSuBSENSE> <enableLOBSTER>0</enableLOBSTER> +<enablePAWCS>0</enablePAWCS> +<enableTwoPoints>0</enableTwoPoints> +<enableViBe>0</enableViBe> +<enableCodeBook>0</enableCodeBook> </opencv_storage> diff --git a/package_bgs/CodeBook.cpp b/package_bgs/CodeBook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1e4056de98c4391fc9751a16f501d6740fbce84 --- /dev/null +++ b/package_bgs/CodeBook.cpp @@ -0,0 +1,216 @@ +/* +This file is part of BGSLibrary. + +BGSLibrary is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +BGSLibrary is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more 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 "CodeBook.h" + +using namespace bgslibrary::algorithms; + +CodeBook::CodeBook() : + t(0), learningFrames(DEFAULT_LEARNFRAMES), alpha(DEFAULT_ALPHA), beta(DEFAULT_BETA) +{ + std::cout << "CodeBook()" << std::endl; + setup("./config/CodeBook.xml"); +} + +CodeBook::~CodeBook() +{ + std::cout << "~CodeBook()" << std::endl; +} + +void CodeBook::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel) +{ + init(img_input, img_output, img_bgmodel); + + if(firstTime) + { + img_foreground = cv::Mat::zeros(img_input.size(), CV_8UC1); + //img_background = cv::Mat::zeros(img_input.size(), CV_8UC3); + + initializeCodebook(img_input.rows, img_input.cols); + } + + cv::Mat img_input_gray; + cv::cvtColor(img_input, img_input_gray, CV_BGR2GRAY); + + fg_cb(img_input_gray, img_foreground); + +#ifndef MEX_COMPILE_FLAG + if (showOutput) + { + cv::imshow("Codebook FG", img_foreground); + //cv::imshow("Codebook BG", img_background); + } +#endif + + img_foreground.copyTo(img_output); + //img_background.copyTo(img_bgmodel); + + firstTime = false; +} + +void CodeBook::initializeCodebook(int w, int h) +{ + cbMain = new std::vector<codeword>*[w]; + for (int i = 0; i < w; ++i) + cbMain[i] = new std::vector<codeword>[h]; + + cbCache = new std::vector<codeword>*[w]; + for (int i = 0; i < w; ++i) + cbCache[i] = new std::vector<codeword>[h]; +} + +void CodeBook::update_cb(const cv::Mat& frame) +{ + if (t > learningFrames) + return; + + for (int i = 0; i < frame.rows; i++) + { + for (int j = 0; j < frame.cols; j++) + { + int pix = frame.at<uchar>(i, j); + std::vector<codeword>& cm = cbMain[i][j]; + bool found = false; + for (int k = 0; k<cm.size(); k++) + { + if (cm[k].min <= pix && pix <= cm[k].max && !found) + { + found = true; + cm[k].min = ((pix - alpha) + (cm[k].f*cm[k].min)) / (cm[k].f + 1); + cm[k].max = ((pix + alpha) + (cm[k].f*cm[k].max)) / (cm[k].f + 1); + cm[k].l = 0; + cm[k].last = t; + cm[k].f++; + } + else + { + cm[k].l++; + } + } + if (!found) + { + codeword n = {}; + n.min = std::max(0, pix - alpha); + n.max = std::min(255, pix + alpha); + n.f = 1; + n.l = 0; + n.first = t; + n.last = t; + cm.push_back(n); + } + } + } + t++; +} + +void CodeBook::fg_cb(const cv::Mat& frame, cv::Mat& fg) +{ + //fg = cv::Mat::zeros(frame.size(), CV_8UC1); + //if (cbMain == 0) initializeCodebook(frame.rows, frame.cols); + + if (t <= learningFrames) + { + update_cb(frame); + return; + } + + for (int i = 0; i<frame.rows; i++) + { + for (int j = 0; j<frame.cols; j++) + { + int pix = frame.at<uchar>(i, j); + std::vector<codeword>& cm = cbMain[i][j]; + bool found = false; + for (int k = 0; k<cm.size(); k++) + { + if (cm[k].min <= pix && pix <= cm[k].max && !found) + { + cm[k].min = ((1 - beta)*(pix - alpha)) + (beta*cm[k].min); + cm[k].max = ((1 - beta)*(pix + alpha)) + (beta*cm[k].max); + cm[k].l = 0; + cm[k].first = t; + cm[k].f++; + found = true; + } + else + cm[k].l++; + } + cm.erase(remove_if(cm.begin(), cm.end(), [](codeword& c) { return c.l >= Tdel; }), cm.end()); + fg.at<uchar>(i, j) = found ? 0 : 255; + if (found) continue; + found = false; + std::vector<codeword>& cc = cbCache[i][j]; + for (int k = 0; k<cc.size(); k++) + { + if (cc[k].min <= pix && pix <= cc[k].max && !found) + { + cc[k].min = ((1 - beta)*(pix - alpha)) + (beta*cc[k].min); + cc[k].max = ((1 - beta)*(pix + alpha)) + (beta*cc[k].max); + cc[k].l = 0; + cc[k].first = t; + cc[k].f++; + found = true; + } + else + cc[k].l++; + } + + if (!found) + { + codeword n = {}; + n.min = std::max(0, pix - alpha); + n.max = std::min(255, pix + alpha); + n.f = 1; + n.l = 0; + n.first = t; + n.last = t; + cc.push_back(n); + } + + cc.erase(remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.l >= Th; }), cc.end()); + + for (std::vector<codeword>::iterator it = cc.begin(); it != cc.end(); it++) + if (it->f > Tadd) + cm.push_back(*it); + + cc.erase(remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.f > Tadd; }), cc.end()); + } + } +} + +void CodeBook::saveConfig() +{ + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_WRITE); + + cvWriteInt(fs, "alpha", alpha); + cvWriteReal(fs, "beta", beta); + cvWriteInt(fs, "learningFrames", learningFrames); + cvWriteInt(fs, "showOutput", showOutput); + + cvReleaseFileStorage(&fs); +} + +void CodeBook::loadConfig() +{ + CvFileStorage* fs = cvOpenFileStorage(config_xml.c_str(), nullptr, CV_STORAGE_READ); + + alpha = cvReadIntByName(fs, nullptr, "alpha", DEFAULT_ALPHA); + beta = cvReadRealByName(fs, nullptr, "beta", DEFAULT_BETA); + learningFrames = cvReadIntByName(fs, nullptr, "learningFrames", DEFAULT_LEARNFRAMES); + showOutput = cvReadIntByName(fs, nullptr, "showOutput", true); + + cvReleaseFileStorage(&fs); +} diff --git a/package_bgs/CodeBook.h b/package_bgs/CodeBook.h new file mode 100644 index 0000000000000000000000000000000000000000..ec224ab1eda74360f09d19c06046595c8da57117 --- /dev/null +++ b/package_bgs/CodeBook.h @@ -0,0 +1,68 @@ +/* +This file is part of BGSLibrary. + +BGSLibrary is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +BGSLibrary is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once + +#include <opencv2/opencv.hpp> + +#include "IBGS.h" + +namespace bgslibrary +{ + namespace algorithms + { + struct codeword { + float min; + float max; + float f; + float l; + int first; + int last; + bool isStale; + }; + + class CodeBook : public IBGS + { + private: + static const int Tdel = 200; + static const int Tadd = 150; + static const int Th = 200; + const int DEFAULT_ALPHA = 10; + const float DEFAULT_BETA = 1.; + const int DEFAULT_LEARNFRAMES = 10; + int t = 0; + int learningFrames = 10; + int alpha = 10; + float beta = 1; + std::vector<codeword> **cbMain; + std::vector<codeword> **cbCache; + + public: + CodeBook(); + ~CodeBook(); + + void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel); + + private: + void initializeCodebook(int w, int h); + void update_cb(const cv::Mat& frame); + void fg_cb(const cv::Mat& frame, cv::Mat& fg); + + void saveConfig(); + void loadConfig(); + }; + } +} diff --git a/package_bgs/bgslibrary.h b/package_bgs/bgslibrary.h index 3895ba85b6f9e646e76965506563f3a0c635eb26..e95a06d25688d79b257ebb971034f1e82d406e07 100644 --- a/package_bgs/bgslibrary.h +++ b/package_bgs/bgslibrary.h @@ -58,6 +58,7 @@ along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>. #include "PAWCS.h" #include "TwoPoints.h" #include "ViBe.h" +#include "CodeBook.h" //#include "_template_/MyBGS.h" //#include "_template_/Amber.h"