Search code examples
opencvbackground-subtractionmog

OpenCV: how to use createBackgroundSubtractorMOG


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

http://docs.opencv.org/trunk/doc/tutorials/video/background_subtraction/background_subtraction.html#background-subtraction

The MOG pointer is initialized as

Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor

and in main, it is used in the following manner:

pMOG = createBackgroundSubtractorMOG();

However, this yields the following error:

    Error: Identifier "createBackgroundSubtractorMOG" is undefined

Also, when the background model is to be updated, the following command is used:

pMOG->apply(frame, fgMaskMOG);

Which in turn yields the following error:

    Error: class "cv::BackgroundSubtractor" has no member "apply"

Any idea of what can be done about this? Many thanks in advance!

Here is the entire tutorial code:

//opencv
#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
  pMOG = createBackgroundSubtractorMOG(); //MOG approach
  pMOG2 = createBackgroundSubtractorMOG2(); //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
    pMOG->apply(frame, fgMaskMOG);
    pMOG2->apply(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(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
    pMOG->apply(frame, fgMaskMOG);
    pMOG2->apply(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);
  }
}

Solution

  • 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);
        }
    }