运动目标检测

文章目录


前言

前景/背景分割法提取前景物体的方法比较简单,适用于背景相对固定的简易场景。但是在很多情况下,背景中的某些部位会在不同的值之间波动,导致背景检测结果频繁出错。背景物体的移动(如树叶)、刺眼的物体(如水面)等因素都是产生这种现象的原因。物体的阴影也会带来问题,因为阴影也是会移动的。为了解决这些问题,我们引入了更复杂的背景模型。


提示:以下是本篇文章正文内容,下面案例可供参考

一、混合高斯模型是什么?

  混合高斯方法是这些改进型算法中的一种。它的处理方式与前面介绍的基本一致,但做了几项改进。

  首先,该方法适用于每个像素有不止一个模型(即不止一个滑动平均值)的情况。这样的话,如果—个背景像素在两个值之间波动,那么就会储存两个滑动平均值。只有当新的像素值不属于任何一个频繁出现的模型时,才会认为这个像素是前景。模型的数量可以在参数中设置,通常为5个。

  其次,每个模型不仅保存了滑动平均值,还保存了滑动均差。它的计算方式如下所示:
运动目标检测
  计算得到的平均值和方差用于构建高斯模型,根据高斯模型就可计算某个像素值属于背景的概率。用概率替代绝对差值后,阈值的选择就会更加容易。这样.如果某个区域的背景波动较大,就需要有更大的差值才能被认定为前景物体。

  最后,这是一个自适应模型。也就是说.如果某个高斯模型满足条件的概率不够高,它就会被排除在背景模刑之外,反之,如果发现一个像素值在当前背景模型之外(即为一个前景像素),那么就会创建一个新的高斯模型。如果这个新建的模型随后频繁收到像素,就把它作为正确的背景模型。

二、API

混合高斯模型API,提取运动目标

//应用时需要加上头文件 #include <opencv2/bgsegm.hpp>
cv::Ptr<cv::BackgroundSubtractor> ptrMOG = cv::bgsegm::createBackgroundSubtractorMOG();
ptrMOG->apply(frame, frame, 0.03);

检测并画出轮廓API

cv::findContours(imgl, contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);  //检测轮廓点
r0 = cv::boundingRect(contours[i]);  //通过检测到的轮廓点形成矩形
cv::drawContours(imglo, contours, -1, 0, 2);  //画出轮廓点

计算矩

cv::Moments mom = cv::moments(contours[i]);//计算轮廓的矩
cv::Point center = cv::Point(mom.m10 / mom.m00, mom.m01 / mom.m00);//轮廓的质心
cv::circle(imglo, center, 2, cv::Scalar(0, 0, 255), 2);//画出质点

1.代码

代码如下(示例):

int main()
{
	cv::VideoCapture cap("D:\\桌面\\代码区\\20201206132227.avi");
	cv::Mat imglo, imgro, imgl,imgr,frame,background;
	bool status = true;
	cv::Ptr<cv::BackgroundSubtractor> ptrMOG = cv::bgsegm::createBackgroundSubtractorMOG();
	while (status)
	{
		cap >> frame;
		clock_t start, end;
		start= clock();

		int w = frame.cols;
		int h = frame.rows;
		if (frame.empty())
		{
			break;
		}

		cv::GaussianBlur(frame, frame, cv::Size(5, 5), 0, 0);
		cv::Mat kernel = (cv::Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
		cv::filter2D(frame, frame, -1, kernel);
		
		imglo = frame;

		ptrMOG->apply(frame, frame, 0.03);
		cv::threshold(frame, frame, 100, 255, cv::THRESH_BINARY_INV);
	
		//cv::dilate(frame, frame, cv::Mat());
		cv::erode(frame, frame, cv::Mat());

		cv::imshow("frame", frame);

		imgl = frame;

		std::vector<std::vector<cv::Point>> contours;
		cv::findContours(imgl, contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
		int max_s = 0;
		cv::Rect r0,r1;
		for (int i = 0; i < contours.size(); i++)
		{
			r0 = cv::boundingRect(contours[i]);
			if (r0.area() < w*h && r0.area() > 2200)
			{
				cv::rectangle(imglo, r0, 0, 2);
				cv::Moments mom = cv::moments(contours[i]);//轮廓的矩
				cv::Point center = cv::Point(mom.m10 / mom.m00, mom.m01 / mom.m00);//轮廓的质心
				cv::circle(imglo, center, 2, cv::Scalar(0, 0, 255), 2);
			}
		}
		
		/*for (int i = 0; i < contours.size(); i++)
		{
			r0 = cv::boundingRect(contours[i]);
			if (r0.area()>max_s && r0.area()<w*h && r0.area()>10)
			{
				max_s=r0.area();
				r1 = r0;
			}
		}
		cv::rectangle(imglo, r1, 0, 2);*/
		//cv::findContours(imgl, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
		//cv::drawContours(imglo, contours, -1, 0, 2);
		
		end = clock();		//程序结束用时
		double endtime = (double)(end - start) / CLOCKS_PER_SEC;
		cout << "Total time:" << endtime << endl;		//s为单位

		cv::imshow("L", imglo);

		if (cv::waitKey(30) > 0)
		{
			status = false;
		}
			
	}

	//system("pause");
	return 0;
}

2.结果

运动目标检测

上一篇:[Mysql]一对多关系是如何发挥作用的?


下一篇:iOS 内存管理