Bootstrap

OpenCV之背景减除

OpenCV之背景减除

介绍

背景减除,官网是这样介绍的。

背景减法(BS)是通过使用静态相机来生成前景蒙版(即,包含属于场景中的运动对象的像素的二进制图像)的通用且广泛使用的技术。
顾名思义,BS计算前景蒙版,在当前帧和背景模型之间执行减法运算,其中包含场景的静态部分,或者更一般而言,考虑到所观察场景的特征,可以视为背景的所有内容。

其实不难理解,我们建立了背景模型,那么前景就很容易分离出来了。当然,这个方法使用场景一般上是静态的背景场景。
后台建模包括两个主要步骤,后台初始化和后台更新,背景减除在OpenCV中的是cv::BackgroundSubtractor类,下面是例子:

官方例子

#include <iostream>
#include <sstream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
const char* params
    = "{ help h         |           | Print usage }"
      "{ input          | vtest.avi | Path to a video or a sequence of image }"
      "{ algo           | MOG2      | Background subtraction method (KNN, MOG2) }";
int main(int argc, char* argv[])
{
    CommandLineParser parser(argc, argv, params);
    parser.about( "This program shows how to use background subtraction methods provided by "
                  " OpenCV. You can process both videos and images.\n" );
    if (parser.has("help"))
    {
        //print help information
        parser.printMessage();
    }
    //create Background Subtractor objects
    Ptr<BackgroundSubtractor> pBackSub;
    if (parser.get<String>("algo") == "MOG2")
        pBackSub = createBackgroundSubtractorMOG2();
    else
        pBackSub = createBackgroundSubtractorKNN();
    VideoCapture capture( samples::findFile( parser.get<String>("input") ) );
    if (!capture.isOpened()){
        //error in opening the video input
        cerr << "Unable to open: " << parser.get<String>("input") << endl;
        return 0;
    }
    Mat frame, fgMask;
    while (true) {
        capture >> frame;
        if (frame.empty())
            break;
        //update the background model
        pBackSub->apply(frame, fgMask);
        //get the frame number and write it on the current frame
        rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
                  cv::Scalar(255,255,255), -1);
        stringstream ss;
        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", fgMask);
        //get the input from the keyboard
        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;
    }
    return 0;
}

截图:
示例

简单分析

Ptr<BackgroundSubtractor> pBackSub,创建背景减除的对象,然后createBackgroundSubtractorMOG2()createBackgroundSubtractorKNN()用来选择更新背景的算法,MOG2或者KNN。然后pBackSub->apply(frame, fgMask);用来更新背景模型。

总的来说用起来是比较煎简单的。其实背景减除最简单的实现,可以直接用当前帧减去前一帧的图像作为背景,这个办法最简单粗暴。优化的话,我们就得对所有的帧差进行建模,用来得到最优的背景模型。

;