OpenCV: how to use createBackgroundSubtractorMOG

前端 未结 4 498
太阳男子
太阳男子 2020-12-13 14:44

I was trying to go through this tutorial på OpenCV.org:

http://docs.opencv.org/trunk/doc/tutorials/video/background_subtraction/background_subtraction.html#backgroun

相关标签:
4条回答
  • 2020-12-13 15:32

    I happened to meet this problem today. This tutorial is for opencv 3.0, not for opencv 2.4+, make a few changes as follows:

    //opencv
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/video/background_segm.hpp>
    //C
    #include <stdio.h>
    //C++
    #include <iostream>
    #include <sstream>
    
    using namespace cv;
    using namespace std;
    
    //global variables
    Mat frame; //current frame
    Mat fgMaskMOG; //fg mask generated by MOG method
    Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
    Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor
    Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
    int keyboard;
    
    //function declarations
    void help();
    void processVideo(char* videoFilename);
    void processImages(char* firstFrameFilename);
    
    void help()
    {
        cout
            << "--------------------------------------------------------------------------"  << endl
            << "This program shows how to use background subtraction methods provided by "   << endl
            << " OpenCV. You can process both videos (-vid) and images (-img)."              << endl
            << endl
            << "Usage:"                                                                      << endl
            << "./bs {-vid <video filename>|-img <image filename>}"                          << endl
            << "for example: ./bs -vid video.avi"                                            << endl
            << "or: ./bs -img /data/images/1.png"                                            << endl
            << "--------------------------------------------------------------------------"  << endl
            << endl;
    }
    
    int main(int argc, char* argv[])
    {
        //print help information
        help();
    
        //check for the input parameter correctness
        if(argc != 3) {
            cerr <<"Incorret input list" << endl;
            cerr <<"exiting..." << endl;
            return EXIT_FAILURE;
        }
    
        //create GUI windows
        namedWindow("Frame");
        namedWindow("FG Mask MOG");
        namedWindow("FG Mask MOG 2");
    
        //create Background Subtractor objects
       //NOTE HERE!!!!
        pMOG= new BackgroundSubtractorMOG(); //MOG approach
        pMOG2 = new BackgroundSubtractorMOG2(); //MOG2 approach
    
        if(strcmp(argv[1], "-vid") == 0) {
            //input data coming from a video
            processVideo(argv[2]);
        }
        else if(strcmp(argv[1], "-img") == 0) {
            //input data coming from a sequence of images
            processImages(argv[2]);
        }
        else {
            //error in reading input parameters
            cerr <<"Please, check the input parameters." << endl;
            cerr <<"Exiting..." << endl;
            return EXIT_FAILURE;
        }
        //destroy GUI windows
        destroyAllWindows();
        return EXIT_SUCCESS;
    }
    
    void processVideo(char* videoFilename) {
        //create the capture object
        VideoCapture capture(videoFilename);
        if(!capture.isOpened()){
            //error in opening the video input
            cerr << "Unable to open video file: " << videoFilename << endl;
            exit(EXIT_FAILURE);
        }
        //read input data. ESC or 'q' for quitting
        while( (char)keyboard != 'q' && (char)keyboard != 27 ){
            //read the current frame
            if(!capture.read(frame)) {
                cerr << "Unable to read next frame." << endl;
                cerr << "Exiting..." << endl;
                exit(EXIT_FAILURE);
            }
            //update the background model
               //AND HERE!!!
            pMOG->operator()(frame, fgMaskMOG);
            pMOG2->operator()(frame, fgMaskMOG2);
            //get the frame number and write it on the current frame
            stringstream ss;
            rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
                cv::Scalar(255,255,255), -1);
            ss << capture.get(CV_CAP_PROP_POS_FRAMES);
            string frameNumberString = ss.str();
            putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
                FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
            //show the current frame and the fg masks
            imshow("Frame", frame);
            imshow("FG Mask MOG", fgMaskMOG);
            imshow("FG Mask MOG 2", fgMaskMOG2);
            //get the input from the keyboard
            keyboard = waitKey( 30 );
        }
        //delete capture object
        capture.release();
    }
    
    void processImages(char* fistFrameFilename) {
        //read the first file of the sequence
        frame = imread(fistFrameFilename);
        if(!frame.data){
            //error in opening the first image
            cerr << "Unable to open first image frame: " << fistFrameFilename << endl;
            exit(EXIT_FAILURE);
        }
        //current image filename
        string fn(fistFrameFilename);
        //read input data. ESC or 'q' for quitting
        while( (char)keyboard != 'q' && (char)keyboard != 27 ){
            //update the background model
                //ALSO HERE!!!!
            pMOG->operator()(frame, fgMaskMOG);
            pMOG2->operator()(frame, fgMaskMOG2);
            //get the frame number and write it on the current frame
            size_t index = fn.find_last_of("/");
            if(index == string::npos) {
                index = fn.find_last_of("\\");
            }
            size_t index2 = fn.find_last_of(".");
            string prefix = fn.substr(0,index+1);
            string suffix = fn.substr(index2);
            string frameNumberString = fn.substr(index+1, index2-index-1);
            istringstream iss(frameNumberString);
            int frameNumber = 0;
            iss >> frameNumber;
            rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
                cv::Scalar(255,255,255), -1);
            putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
                FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
            //show the current frame and the fg masks
            imshow("Frame", frame);
            imshow("FG Mask MOG", fgMaskMOG);
            imshow("FG Mask MOG 2", fgMaskMOG2);
            //get the input from the keyboard
            keyboard = waitKey( 30 );
            //search for the next image in the sequence
            ostringstream oss;
            oss << (frameNumber + 1);
            string nextFrameNumberString = oss.str();
            string nextFrameFilename = prefix + nextFrameNumberString + suffix;
            //read the next frame
            frame = imread(nextFrameFilename);
            if(!frame.data){
                //error in opening the next image in the sequence
                cerr << "Unable to open image frame: " << nextFrameFilename << endl;
                exit(EXIT_FAILURE);
            }
            //update the path of the current frame
            fn.assign(nextFrameFilename);
        }
    }
    
    0 讨论(0)
  • 2020-12-13 15:32

    Accordingly to the previous answer the background subtractor can be also defined as:

    BackgroundSubtractorMOG MOG;
    

    instead of:

    Ptr<BackgroundSubtractor> pMOG;
    pMOG= new BackgroundSubtractorMOG(); //MOG approach
    

    that would also require to delete pMOG when it is not used anymore, furthermore functor can be used to update foreground mask in a bit smarter way:

    MOG(newFrame, foregroundMask);
    

    insted of:

    pMOG->operator()(frame, fgMaskMOG);
    

    The default assumption of openCV is that the background is quite constant and does not need any update, so, after the learning initial phase the Mixture of Gaussians is not changed any more. A detailed and clear description can be also be found here:

    http://hal.archives-ouvertes.fr/docs/00/33/82/06/PDF/RPCS_2008.pdf

    0 讨论(0)
  • 2020-12-13 15:41

    I also had the same issue: Error: Identifier "createBackgroundSubtractorMOG" is undefined which was because I was missing link to opencv library libopencv_video.so in my algorithm.

    I solved this by including libopencv_video.so during linking of the project which can be done in your Makefile like this: -L/usr/local/lib/libopencv_video.so

    It resolved the error and I am able to use the original tutorial as given here: http://docs.opencv.org/3.0-beta/doc/tutorials/video/background_subtraction/background_subtraction.html

    0 讨论(0)
  • 2020-12-13 15:42

    If you want the MOG method to work, you should

    #include "opencv2/bgsegm.hpp"
    

    and then

    pMOG = bgsegm::createBackgroundSubtractorMOG();
    
    0 讨论(0)
提交回复
热议问题