进行运动物体检测就是将动态的前景从静态的背景中分离出来。将当前画面与假设是静态背景进行比较发现有明显的变化的区域,就可以认为该区域出现移动的物体。在实际情况中由于光照阴影等因素干扰比较大,通过像素直接进行比较往往很容易造成误检。因此有不少算法被开发出来在进行前后景分离的时候对运动和其他因素造成的变动进行区分。opencv中提供了多种背景减除的算法,其中基于高斯混合模型(GMM)的cv2.BackgroundSubtractorMOG()cv2.BackgroundSubtractorMOG2()已经基于贝叶斯模型的cv2.bgsegm.createBackgroundSubtractorGMG()最为常用。

1) GMM法

GMM进行前后景分离最早是在2001年的文章An improved adaptive background mixture model for real-time tracking with shadow detection中提出的。其设计思路为:

  1. 在不知道图像历史的时候,假设每个像素点的值都是可以分解为一组adaptive Gaussian。adaptive是由于需要跟随光照条件的变化而变化。
  2. 像素值的历史由一组高斯分布进行建模,包括每个分布的权重。
  3. 每次新图像输入的时候都会用这一组高斯分布进行评估,如果像素匹配上其中一个分布就会认为这个像素属于背景,而高斯分布的均值和方差等参数会用当前像素的值进行更新。
  4. 标记为前景的像素通过connected component analysis进行分组。

    opencv的cv2.BackgroundSubtractorMOG()的函数就是对次方法的实现。

基于2004年提出的Improved adaptive Gausian mixture model for background subtractio和2006年提出的Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction算法对上述GMM算法进行改良的就是opencv的cv2.BackgroundSubtractorMOG2()的函数。主要的提升是对每个像素都选择合适数量的高斯分布而非原来的全部相同的个数。此外,这个函数还允许是否检测阴影。

使用方法(以MOG2为例)

import cv2

cam = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG()
while cam.isOpened():
ret, frame = cam.read()
if ret:
fgmask = fgbg.apply(frame)
# 通过腐蚀和膨胀过滤一些噪声
erode = cv2.erode(fgmask, (21, 21), iterations=1)
dilate = cv2.dilate(fgmask, (21, 21), iterations=1)
(_, cnts, _) = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
c_area = cv2.contourArea(c)
if c_area < 1600 or c_area > 16000: # 过滤太小或太大的运动物体,这类误检概率比较高
continue
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
cv2.imshow("origin", frame)
if cv2.waitKey(1) == ord('q'):
break
cv2.destroyAllWindows()

2)GMG法

根据2012年的文章Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive Audio Art Installation, opencv开发了相应的函数cv2.bgsegm.createBackgroundSubtractorGMG() (好像在3.2中被放到了contrib中,在之前可以直接用cv2.createBackgroundSubtractorGMG()进行调用)。这个方法默认使用前120张图片进行背景的建模,并使用概率前景分割算法找到可能的前景(基于贝叶斯推测)。为了更好适应不同光照变化的影响,新的图片的权重比旧图片要高。

使用方法

cam = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (8, 8))
fgbg = cv2.bgsegm.createBackgroundSubtractorGMG(initializationFrames=10)
while cam.isOpened():
ret, frame = cam.read()
if ret:
fgmask = fgbg.apply(frame)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel) # 过滤噪声
(_, cnts, _) = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
c_area = cv2.contourArea(c)
if c_area < 1600 or c_area > 16000: # 过滤太小或太大的运动物体,这类误检概率比较高
continue
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
cv2.imshow("origin", frame)
if cv2.waitKey(1) == ord('q'):
break
cv2.destroyAllWindows()

参考:

  1. https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html
  2. http://android4arduino.com/computer-vision/motion-detection/
  3. https://www.pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/
  4. https://docs.opencv.org/3.0-beta/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=createbackgroundsubtractormog

利用opencv进行移动物体检测的更多相关文章

  1. opencv,关于物体检测

    关于物体检测 环境:opencv 2.4.11+vs2013 参考: http://www.cnblogs.com/tornadomeet/archive/2012/06/02/2531705.htm ...

  2. OpenCV学习 物体检测 人脸识别 填充颜色

    介绍 OpenCV是开源计算机视觉和机器学习库.包含成千上万优化过的算法.项目地址:http://opencv.org/about.html.官方文档:http://docs.opencv.org/m ...

  3. OpenCV 使用光流法检测物体运动

    OpenCV 可以使用光流法检测物体运动,贴上代码以及效果. // opticalflow.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" ...

  4. [PyImageSearch] Ubuntu16.04 使用深度学习和OpenCV实现物体检测

    上一篇博文中讲到如何用OpenCV实现物体分类,但是接下来这篇博文将会告诉你图片中物体的位置具体在哪里. 我们将会知道如何使用OpenCV‘s的dnn模块去加载一个预训练的物体检测网络,它能使得我们将 ...

  5. OpenCV平面物体检测

    平面物体检测 这个教程的目标是学习如何使用 features2d 和 calib3d 模块来检测场景中的已知平面物体. 测试数据: 数据图像文件,比如 “box.png”或者“box_in_scene ...

  6. 利用modelarts和物体检测方式识别验证码

    近来有朋友让老山帮忙识别验证码.在github上查看了下,目前开源社区中主要流行以下几种验证码识别方式: tesseract-ocr模块: 这是HP实验室开发由Google 维护的开源 OCR引擎,内 ...

  7. OpenCV神技——人脸检测,猫脸检测

    简介   OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 ...

  8. 如何利用OpenCV自带的级联分类器训练程序训练分类器

    介绍 使用级联分类器工作包括两个阶段:训练和检测. 检测部分在OpenCVobjdetect 模块的文档中有介绍,在那个文档中给出了一些级联分类器的基本介绍.当前的指南描述了如何训练分类器:准备训练数 ...

  9. OPENCV图像特征点检测与FAST检测算法

    前面描述角点检测的时候说到,角点其实也是一种图像特征点,对于一张图像来说,特征点分为三种形式包括边缘,焦点和斑点,在OPENCV中,加上角点检测,总共提供了以下的图像特征点检测方法 FAST SURF ...

随机推荐

  1. 介绍一个小工具 Linqer

    http://www.cnblogs.com/huangxincheng/archive/2011/05/12/2044990.html

  2. 201521123022 《Java程序设计》 第十一周学习总结

    1.本章学习总结 2.书面作业 本次PTA作业题集多线程 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问 Q1.1 除了使用synchronized修饰方法实现互斥同步访问,还 ...

  3. 【工具】Idea GenerateAllSetter

    使用工具自动生成setter方法调用,不是idea原生态生成getter/setter https://github.com/gejun123456/intellij-generateAllSetMe ...

  4. splay详解(三)

    前言 上一节我们学习了splay所能解决的基本问题,这节我来讲一下splay怎么搞区间问题 实现 splay搞区间问题非常简单,比如我们要在区间$l,r$上搞事情,那么我们首先把$l$的前驱旋转到根节 ...

  5. 二十:让行内元素在div中垂直居中

    (1)使用display:table-cell配合vertical-align:center(淘宝也是这样用的) <div class="method4"> <s ...

  6. css3实现单行文本溢出显示省略号

    文本超出一定宽度让其隐藏,以省略号替代 width:200px; white-space:nowrap; text-overflow:ellipsis; overflow:hidden; 如下图

  7. C# 比较两个路径是否指向同一对象

    string path1 = @"c:\test\rootpath"; string path2 = @"C:\TEST\..\TEST\ROOTPATH"; ...

  8. react中创建组件

    第1种 - 创建组件的方式 > 使用构造函数来创建组件,如果要接收外界传递的数据,需要在 构造函数的参数列表中使用`props`来接收:> 必须要向外return一个合法的JSX创建的虚拟 ...

  9. loganalyzer

  10. 如何查看USB方式连接Android设备的外接设备信息

    1,USB存储设备(如:U盘,移动硬盘): //USB存储设备 插拔监听与 SD卡插拔监听一致. private USBBroadCastReceiver mBroadcastReceiver; In ...