利⽤opencv进⾏移动物体检测
进⾏运动物体检测就是将动态的前景从静态的背景中分离出来。将当前画⾯与假设是静态背景进⾏⽐较发现有明显的变化的区域,就可以认为该区域出现移动的物体。在实际情况中由于光照阴影等因素⼲扰⽐较⼤,通过像素直接进⾏⽐较往往很容易造成误检。因此有不少算法被开发出来在进⾏前后景分离的时候对运动和其他因素造成的变动进⾏区分。opencv中提供了多种背景减除的算法,其中基于⾼斯混合模型(GMM)的
cv2.BackgroundSubtractorMOG()和cv2.BackgroundSubtractorMOG2()已经基于贝叶斯模型的
ateBackgroundSubtractorGMG()最为常⽤。
1) GMM法
GMM进⾏前后景分离最早是在2001年的⽂章An improved adaptive background mixture model for real-time tracking with shadow detection中提出的。其设计思路为:
在不知道图像历史的时候,假设每个像素点的值都是可以分解为⼀组adaptive Gaussian。adaptive是由于需要跟随光照条件的变化⽽变化。
像素值的历史由⼀组⾼斯分布进⾏建模,包括每个分布的权重。
每次新图像输⼊的时候都会⽤这⼀组⾼斯分布进⾏评估,如果像素匹配上其中⼀个分布就会认为这个像素属于背景,⽽⾼斯分布的均值和⽅差等参数会⽤当前像素的值进⾏更新。
标记为前景的像素通过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 = ateBackgroundSubtractorMOG()while cam.isOpened():
ret, frame = ad()
if ret:
fgmask = fgbg.apply(frame)
# 通过腐蚀和膨胀过滤⼀些噪声        erode = de(fgmask, (21, 21), iterations=1)
dilate = cv2.dilate(fgmask, (21, 21), iterations=1)
(_, cnts, _) = cv2.py(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
c_area = urArea(c)
if c_area < 1600 or c_area > 16000:  # 过滤太⼩或太⼤的运动物体,这类误检概率⽐较⾼                continue            (x, y, w,
h) = cv2.boundingRect(c)
cv2.imshow("origin", frame)
if cv2.waitKey(1) == ord('q'):
breakcv2.destroyAllWindows()
2)GMG法
根据2012年的⽂章Visual Tracking of Human Visitors under Variable-Lighting Conditions for a Responsive Audio Art Installation, opencv开发了相应的函数ateBackgroundSubtractorGMG() (好像在3.2中被放到了contrib中,在之前可以直接⽤ateBackgroundSubtractorGMG()进⾏调⽤)。这个⽅法默认使⽤前120张图⽚进⾏背景的建模,并使⽤概率前景分割算法到可能的前景(基于贝叶斯推测)。为了更好适应不同光照变化的影响,新的图⽚的权重⽐旧图⽚要⾼。
使⽤⽅法
cam = cv2.VideoCapture(0)
kernel = StructuringElement(cv2.MORPH_ELLIPSE, (8, 8))
fgbg = ateBackgroundSubtractorGMG(initializationFrames=10)while cam.isOpened():
ret, frame = ad()
if ret:
fgmask = fgbg.apply(frame)
fgmask = phologyEx(fgmask, cv2.MORPH_OPEN, kernel)  # 过滤噪声        (_, cnts, _) =
cv2.py(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
c_area = urArea(c)
if c_area < 1600 or c_area > 16000:  # 过滤太⼩或太⼤的运动物体,这类误检概率⽐较⾼                continue            (x, y, w, h) = cv2.boundingRect(c)
rectangle函数opencv
cv2.imshow("origin", frame)
if cv2.waitKey(1) == ord('q'):
breakcv2.destroyAllWindows()
参考: