目标检测是将运动的物体从背景中检测出来,人们希望设计能适用于各种监控环境,不受光照、天气等外界因素影响的目标检测算法。但这种算法难免复杂度大,现有一些算法大多是针对某一类问题提出的,主要包括背景减法、相邻帧差法和光流法等

1.1背景减法

       背景减法(backgroundsubtraction)是目前运动目标检测的主流方法,其基本思想是将当前每一帧图像与事先存储或实时获取的背景图像相减,计算出与背景偏离超过一定阀值的区域作为运动区域。该算法实现简单,相减结果直接给出目标的位置、大小、形状等信息,能够提供关于运动目标区域的完整描述,特别是对于摄像机静止的情况,背景减法是实现运动目标实时检测和提取的首选方法。
       背景减法实现的关键是背景模型的获取和更新。背景获取算法通常要求在场景中存在运动目标的情况下获取背景图像,更新过程使背景能够适应场景的各种变化和干扰,如外界光线的改变,背景中对象的扰动和固定对象的移动,阴影的影响等。一种典型的背景建模方法是用混合高斯模型描述背景图像像素值的分布,目标检测过程中判断图像的当前像素值是否符合该分布,若是被判为前景点,否则为背景点。同时根据新获取的图像,对背景图像参数进行自适应更新。该方法能够可靠处理光照变化、背景混乱运动的干扰以及长时间的场景变化等。在此基础上,对背景、静止目标和运动目标三者采取不同的更新策略,以减弱背景更新过程中运动目标对背景的影响。

1.2 BS算法

   OpenCV提供的BS算法:

  • 图像分割(GMM - 高斯混合模型)
  • 机器学习(KNN - K个最近邻)

   以下代码将通过GMM和KNN两种方法,实现了实时检测运动目标效果的对比。

代码:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	VideoCapture cap(0);

	if (!cap.isOpened())
	{
		printf("\nCan not open camera \n");
		return -1;
	}
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));

	// intialization BS
	Ptr<BackgroundSubtractor> pMOG2 = createBackgroundSubtractorMOG2();
   //Ptr<BackgroundSubtractor> pKNN = createBackgroundSubtractorKNN();

	Mat tmp_frame;
	Mat bsmaskMOG2, bsmaskKNN;

	for (;;)
	{
		cap >> tmp_frame;
		if (tmp_frame.empty())
			break;
		// MOG BS
		pMOG2->apply(tmp_frame, bsmaskMOG2);
		morphologyEx(bsmaskMOG2, bsmaskMOG2, MORPH_OPEN, kernel, Point(-1, -1));
		imshow("MOG2", bsmaskMOG2);

		// KNN BS mask
		//pKNN->apply(tmp_frame, bsmaskKNN);
		//imshow("KNN Model", bsmaskKNN);

		imshow("video", tmp_frame);
		
		char keycode = (char)waitKey(30);//按ESC推出
		if (keycode == 27)
			break;
	}
	cap.release();
	return 0;
}