消除背景建模就是找出视频中移动的区域,把移动的区域设为白色对象方便观察,其他没有移动的区域设为黑色背景。
消除背景建模是视频跟踪最基本的方法。可用基于机器学习的KNN算法或者图像分割MOG算法
不论是KNN还是MOG,它们对于消除背景建模的思路是一样的
以KNN为例:假设在视频的第10帧为开始,用KNN算法可以把第10帧图像中的所有像素点划分为K类。即每个像素点都有属于自己的类别。
第11帧时,对第11帧图像进行KNN分类,如果视频中没有物体移动,则第11帧和第10帧图像中所有对应像素点的类别是一样的。如果视频中有物体移动了,则第11帧和第10帧图像中不是所有对应像素点的类别是一样的,不是同一类别的像素点就是移动物体的区域,把该区域设为白色背景。
以下是opencv c++具体代码。
//BSM背景消除建模
//分为机器学习 KNN 和 图像分割MOG2
//用于在视频监控情况下找运动背景
#include <iostream>
#include<opencv2/opencv.hpp>
#include<string>
using namespace cv;
using namespace std;
int main(int argc, char ** argv)
{
Mat frame, KNNmask, MOG2mask;
VideoCapture capture;
Mat kenel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//形态学模版
vector<vector<Point>>contours; //求轮廓的参数
vector<Vec4i>hierarchy;//求轮廓的参数
string target = "Target";//求显示标签的参数
ostringstream oss;//定义字符串与数字结合
capture.open(0);
if (!capture.isOpened())
{
printf("can not open ......\n");
return -1;
}
namedWindow("KNNmask", WINDOW_AUTOSIZE);
namedWindow("MOG2mask", WINDOW_AUTOSIZE);
namedWindow("output", WINDOW_AUTOSIZE);
Ptr<BackgroundSubtractor> pKNN = createBackgroundSubtractorKNN();//调用KNN背景消除模型,指针类型
Ptr<BackgroundSubtractor> pMOG2 = createBackgroundSubtractorMOG2();//调用MOG2背景消除模型,指针类型
while (capture.read(frame))
{
int a = 1;//求显示标签的参数
pKNN->apply(frame, KNNmask);//把frame在KNN模型下赋值给KNNmask
pMOG2->apply(frame, MOG2mask);
//KNN
//二值化
threshold(KNNmask, KNNmask, 100, 255, THRESH_BINARY);
//利用形态学消除噪声。开环
morphologyEx(KNNmask, KNNmask, MORPH_OPEN, kenel, Point(-1, -1));
//MOG2
threshold(MOG2mask, MOG2mask, 100, 255, THRESH_BINARY);
morphologyEx(MOG2mask, MOG2mask, MORPH_OPEN, kenel, Point(-1, -1));
//找轮廓
findContours(KNNmask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);//求轮廓面积
Rect rect = boundingRect(contours[i]);//求轮廓最小包围矩阵
if (area < 500 || rect.width < 50 || rect.height < 50) //不画出面积,长,宽过小的轮廓矩阵
continue;
oss << target << a;//结合显示的字符串与数字
rectangle(frame, rect, Scalar(0, 0, 255), 2);//画矩形框
putText(frame, oss.str(), Point(rect.x, rect.y), CV_FONT_NORMAL, FONT_HERSHEY_PLAIN, Scalar(0, 255, 0), 1, 8);
oss.str("");//把oss之前存放的字符全部清除
a = a + 1;//a为矩形框个数
}
//显示
imshow("KNNmask", KNNmask);
imshow("MOG2mask", MOG2mask);
imshow("output", frame);
waitKey(1);
}
capture.release();//释放内存
waitKey(0);
return 0;
}