背景建模
上一篇文章中有一个平均差分的简单背景建模方法,现在介绍opencv库中封装好的背景建模方法。
我们只需要知道它的用法,然后具体的细节参考每个背景建模的具体算法,在这里给大家一个实例,用于实际实现opencv中的背景建模方法,opencv的版本是4.0,contribute版本也是4.0
背景建模方法:
在opencv中各种背景提取的方法已经被包装好了,我们只要使用即可,下面介绍一些语法规则。
首先所有的背景提取方法都继承于BackgroundSubstractor这个基类
class cv::BackgroundSubstractor{
Public:
Virtual ~BackgroundSubstractor(){} //析构函数
Virtual void apply(InputArray image,OutputArray fmask, double learningRate = -1);
Virtual void getBackgroundImage(OutputArray image) const;
};
用类图表示如下:
故我们建立一个基类的指针,通过创建不同的实例方法,即可使用不同的方法进行背景提取。
用例:
Ptr<BackgroundSubtractor> pBgSub; // THE SAME BASE CLASS 只需要在此选择不同的方法即可。
//pBgSub = bgsegm::createBackgroundSubtractorLSBP();
//pBgSub= createBackgroundSubtractorMOG2();
//pBgSub = bgsegm::createBackgroundSubtractorGMG();
//pBgSub = bgsegm::createBackgroundSubtractorCNT();
//pBgSub = bgsegm::createBackgroundSubtractorGSOC();
pBgSub = createBackgroundSubtractorKNN();
pBgSub->apply(frame,mask);
下面给出全部例程代码:
static void help()
{
printf("\n"
"This program demonstrated a simple method of connected components clean up of background subtraction\n"
"When the program starts, it begins learning the background.\n"
"You can toggle background learning on and off by hitting the space bar.\n"
"Call\n"
"./segment_objects [video file, else it reads camera 0]\n\n");
}
int test02()
{
VideoCapture cap;
help();
cap.open(1);
bool update_bg_model = true;
if (!cap.isOpened())
{
printf("\nCan not open camera or video file\n");
return -1;
}
Mat frame, fgMask;
Ptr<BackgroundSubtractor> pBgSub; // THE SAME BASE CLASS 只需要在此选择不同的方法即可。
//pBgSub = bgsegm::createBackgroundSubtractorLSBP();
//pBgSub= createBackgroundSubtractorMOG2();
//pBgSub = bgsegm::createBackgroundSubtractorGMG();
//pBgSub = bgsegm::createBackgroundSubtractorCNT();
//pBgSub = bgsegm::createBackgroundSubtractorGSOC();
pBgSub = createBackgroundSubtractorKNN();
while (true) {
cap >> frame;
if (frame.empty())
break;
//! [apply]
//update the background model
pBgSub->apply(frame, fgMask);// apply方法是background基类方法 virture apply(inputimg,outputimg);
rectangle(frame, Point(10, 2), Point(100, 20),
Scalar(255, 255, 255), -1);
stringstream ss;
ss << cap.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));
//! [display_frame_number]
//! [show]
//show the current frame and the fg masks
Mat kennel = getStructuringElement(1, Size(5, 5));
erode(fgMask, fgMask, kennel);
dilate(fgMask, fgMask, kennel);
imshow("Frame", frame);
imshow("FG Mask", fgMask);
//! [show]
//get the input from the keyboard
int keyboard = waitKey(30);
if (keyboard == 'q' || keyboard == 27)
break;
}
}
int main()
{
//test(); 平均背景法
test02();
return 0;
}
以下为KNN背景建模法的结果
小结
1.所有的背景提取方法只是在背景创建上有所不同,我们只需要用到某个背景建模的方法,学习它的核心思想即可。
2.由于每个背景建模的方法都是基于摄像头不动的情况下建模的,假设相机有一点点的干扰,一点点的扰动效果也不好。这也是每个背景建模的缺点。
3.如果有任何不对的地方还希望多多指正