ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

运动目标检测

2020-12-08 22:33:07  阅读:193  来源: 互联网

标签:r0 模型 检测 frame 目标 contours mom 运动 cv


文章目录


前言

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


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

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

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

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

在这里插入图片描述

标签:r0,模型,检测,frame,目标,contours,mom,运动,cv
来源: https://blog.csdn.net/qq_43587345/article/details/110890753

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有