How to get moving object's mask using OpenCV BackgroundSubtractorMOG2

Alston picture Alston · Nov 28, 2012 · Viewed 10.2k times · Source

I want to mask the moving objects from video. I found that OpenCV has some built-in BackgroundSubtractors which could possibly saving my time a lot. However, according to the official reference, the function:

void BackgroundSubtractorMOG2::operator()(InputArray image, OutputArray fgmask, double learningRate=-1)

should output a mask, fgmask, but it doesn't. The fgmask variable will contain the "contour of the mask" instead after invoking above method. That's weird. All I want is a simple closed region filled with white color(for example) to represent the moving objects. How could I do that?

Any reply or recommendation would be very appreciate. Thanks a lot.

Here's my code:

int main(int argc, char *argv[])
{
    cv::BackgroundSubtractorMOG2 bg = BackgroundSubtractorMOG2(30,16.0,false);
    cv::VideoCapture cap(0);
    cv::Mat frame, mask, _frame, _fmask;
    cvNamedWindow("mask", CV_WINDOW_AUTOSIZE);
    for(;;)
    {
        cap >> frame;
        bg(frame,fmask,-1);

        _frame = IplImage(frame);
        _fmask = IplImage(fmask);

        cvShowImage("mask", &_fmask);
        if(cv::waitKey(30) >= 0) break;
    }
    return 0;
}

A snapshot of the output video is: enter image description here

p.s. My working environment is OpenCV2.4.3 on OSX 10.8 and XCode 4.5.2 with apple LLVM compiler 4.1.

Answer

sam18 picture sam18 · Dec 18, 2012

If you want to acquire the whole objects filled with white pixels in the foreground then I would ask you to tell me something about your experience.

My question is, for the code, you mentioned above, do you get more white pixels when you generate more motion in front of your camera?

If yes then there are two paramenters to learn about for your requirement.

First is the History parameter. which you have configured as 30 in the constructor BackgroundSubtractorMOG2(30,16.0,false);. You can test this param by incresing, say to 300. It will maintain the motion history of the object in the foreground. So if you have moved completely from your starting location within the 300 frames then you will get whole object covered with white pixels as you want. but it will be erased gradually. So it cannot give you the 100% solution.

The second parameter is called learning rate. In the code you mentioned bg(frame,fmask,-1); where -1 is your learning rate. you can set it to 0.0 to 1.0 and default is -1. When you set it 0, you will get what you want for the objects which are not part of the frame in the starting of the video. You can call this kind of object "foreign objects". You will get foreign object covered with white pixels.

Explore your testing from the information I have mentioned above and share your experience.