内容来自OpenCV-Python Tutorials 自己翻译整理
目标:
这一节要了解背景减除算法在opencv中的应用。
基础:
背景减除算法是很多以机器视觉为基础的应用中,非常重要的预处理算法。例如,使用固定的摄像头来统计一个房间的进出人数或者交通摄像头提取关于交通工具的信息等等。在所有这些例子当中,你首先要做的就是把人和交通工具单独提取出来。从技术上来讲,你需要把移动的前景从静止的背景当中提取出来。
如果你要一张单独的背景图片,例如一个没有游客的房间照片,没有任何交通工具的街道照片等等,这有一个很简单的方法,只要从新的图片当中减去背景图片即可。你就能得到单独的前景照片。但是在多数的例子当中,你不可能有这样的背景照片,所以我们需要从我们手头有的照片中提取前景。当存在阴影等效果的时候,这相当复杂了。因为影子是会移动的,简单的减除方法会将阴影部分同样当成是前景。这是个很糟糕的事情。
下面介绍了一些算法,opencv当中实现了3种很好用的方法。一个一个的看一下。
BackgroundSubtractorMOG:
这是一个基于混合高斯模型的背景前景分割算法。来自论文:An improved adaptive background mixture model for real-time tracking with shadow detection。
它使用的方法是对每个背景像素由k个混合高斯模型进行建模,k通常为3或5。彩色信息在场景中存在时间的比例作为高斯混合模型的权重大小。最有可能的背景颜色信息是停留时间最长且更为静止的。
编写代码的时候需要使用一个函数来创建的一个背景对象cv2.createBackgroundSubtractorMOG()。
这里有一些可选参数,如历史时间(length of history),高斯模型的数量,阈值等等。这些值全部被设置为缺省。
获取背景后,进入视频循环,使用函数backgroundsubtractor.apply() 来获取前景的蒙板。
函数原型:
retval = cv.bgsegm.createBackgroundSubtractorMOG( [, history[, nmixtures[, backgroundRatio[, noiseSigma]]]] )
参数:
history Length of the history.
nmixtures Number of Gaussian mixtures.
backgroundRatio Background ratio.
noiseSigma Noise strength (standard deviation of the brightness or each color channel). 0 means some automatic value.
例子:(本人cv版本是3.3 调用该函数时要加上bgsegm)
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
效果(看起来很玄乎)
BackgroundSubtractorMOG2:
该方法同样是使用基于高斯混合模型的背景前景分割算法。基于两篇论文:
Improved adaptive Gausian mixture model for background subtraction
Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction
该算法的一个重要特征是它对每个像素点选择了合适数量的高斯分布模型。因此它也提供了一个在光照变换场景中更好的适应能力。
该函数可以选择是否要探测阴影部分,detectShadows = True,缺省情况下是探测的,但是速度会下降。
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
fgbg = cv2.createBackgroundSubtractorMOG2()
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
cv2.imshow('org',frame)
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
该方法对亮度变换非常敏感!
BackgroundSubtractorGMG:
该算法结合了静态背景图片估计和每个像素的贝叶斯分割方法。来源于论文:
Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive Audio Art Installation
该系统运行了一个成功的音频交互的艺术装置,该装置叫“Are We There Yet?” 而且运行了很长时间哦~(略过一些废话)
该方法默认使用前120帧图像进行建模(所以在打开视频的时候你得等一会再把移动的物体放上),使用概率前景分割算法,即使用贝叶斯推断方法来识别一个物体是否是前景。
该估计算法是一种自适应的估计方法,新的被观察物体比旧的观察物体有更改的权重,这样可以适应变化的光照。一些形态学吕布的操作,例如闭运算和开运算可以用来去除不想要的噪声。
在开始的前几帧当中你会得到一个黑色的窗口。这很适合使用形态学滤波的开运算来去除噪声。
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
fgbg = cv2.bgsegm.createBackgroundSubtractorGMG()
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
cv2.imshow('org',frame)
cv2.imshow('frame',fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
效果