【python】实现基于混合高斯模型的运动目标检测 | 方案和代码
在视频监控场景中,应用基于背景减去法的运动目标检测是比较常见的。
目录
一 安装依赖
二 函数
① cv2.createBackgroundSubtractorMOG2()
② apply()
③ cv2.findContours()
三 实现基于背景减去法的运动目标检测的方法
四 实践
① 代码
② 效果图
一 安装依赖
通过以下命令安装相关依赖:
pip install opencv-python numpy
二 函数
① cv2.createBackgroundSubtractorMOG2()
cv2.createBackgroundSubtractorMOG2()函数是OpenCV库中用于创建混合高斯模型(Gaussian Mixture Model,简称GMM)背景减除器的方法。
初始化一个背景减除器对象,用于实时视频流中前景目标的检测。
函数的参数:
▲ history:整型参数,指定最近多少帧用于学习背景模型。较大的history值可以使模型更加稳定,但也会增加响应时间,即模型适应新背景的时间会更长。history=450意味着模型将基于最近450帧的历史数据来学习背景。
▲ varThreshold:整型参数,设置混合高斯模型的方差阈值。这个参数决定了如何将前景像素与背景模型区分开来。较大的varThreshold值会减少误报,但可能会漏掉一些真正的前景对象;较小的varThreshold值则会增加敏感度,但可能会增加误报。varThreshold=16是一个相对适中的设置,适用于大多数场景。
▲ detectShadows:布尔型参数,决定是否检测阴影。如果设为True,背景减除器将尝试识别并标记阴影区域。这在光照变化较大的环境中很有用,但可能会稍微降低性能。
② apply()
apply()方法返回一个前景掩码。
③ cv2.findContours()
在OpenCV中,cv2.findContours()函数用于从二值图像中检测物体的轮廓。该函数接受三个主要参数:输入图像(通常是二值图像)、轮廓检索模式和轮廓近似方法。
contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
参数含义如下:
▲ fgmask:这是背景减除后的前景掩膜图像,通常是一个二值图像,其中前景像素值为255,背景像素值为0。
▲ cv2.RETR_EXTERNAL:这是一个轮廓检索模式,只检索最外层的轮廓,忽略内嵌的轮廓。这通常用于只需要最外层物体边界的场景。
▲ cv2.CHAIN_APPROX_SIMPLE:这是一个轮廓近似方法,它压缩水平的、垂直的和对角线的元素,只留下端点。这样可以大大减少存储轮廓所需的点的数量,同时保留轮廓的基本形状。
函数返回两个值:
contours 和 _(通常被忽略)。contours是一个Python列表,其中每一个元素都是图像中的一个轮廓,表示为Numpy数组,数组中的每一行存储轮廓上一个点的坐标(x, y)。_通常代表层次结构信息,但在大多数情况下,只关心轮廓本身,所以通常用_来忽略这个返回值。
使用cv2.findContours()获取轮廓后,可以进一步处理这些轮廓,比如计算轮廓的面积、周长、中心点、最小包围矩形等,或者在原图像上绘制这些轮廓。这些操作对于目标检测、物体识别、手势识别等计算机视觉应用是非常基础且重要的。
三 实现基于背景减去法的运动目标检测的方法
① 创建了一个BackgroundSubtractorMOG2对象,是OpenCV提供的基于混合高斯模型的背景减除类。
② 从视频流中读取每一帧,应用背景减除。
③ 使用形态学操作(如开运算)来去除小的噪声区域。
④ 检测前景中的轮廓,并为面积大于设定阈值的轮廓绘制边界框。
⑤ 显示目标检测结果。
四 实践
① 代码
import cv2
import numpy as np
# 创建BackgroundSubtractorMOG2对象
fgbg = cv2.createBackgroundSubtractorMOG2(history=450, varThreshold=20, detectShadows=True)
# 打开视频文件
cap = cv2.VideoCapture('test.mp4')
while True:
ret, frame = cap.read()
if not ret:
break
# 应用背景减除
fgmask = fgbg.apply(frame)
# 使用形态学操作去除噪声
kernel = np.ones((3,3),np.uint8)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
# 查找轮廓
contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制边界框
for contour in contours:
if cv2.contourArea(contour) > 300:
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 显示结果
cv2.imshow('Frame', frame)
# cv2.imshow('FG Mask', fgmask)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
② 效果图
至此,本文的内容就结束啦。
作者:Jackilina_Stone