
目录
[1. 导入库](#1. 导入库)
[2. 创建背景建模对象](#2. 创建背景建模对象)
[3. 打开视频源](#3. 打开视频源)
[4. 逐帧处理视频](#4. 逐帧处理视频)
[5. 应用背景建模获得前景掩码](#5. 应用背景建模获得前景掩码)
[6. 形态学操作去除噪声](#6. 形态学操作去除噪声)
[6.1 定义形态学核](#6.1 定义形态学核)
[6.2 开运算去除噪点](#6.2 开运算去除噪点)
[6.3 膨胀操作填补前景区域空洞](#6.3 膨胀操作填补前景区域空洞)
[7. 轮廓检测识别动态物体](#7. 轮廓检测识别动态物体)
[8. 绘制轮廓和边界框](#8. 绘制轮廓和边界框)
[9. 显示处理结果](#9. 显示处理结果)
[10. 退出控制与资源释放](#10. 退出控制与资源释放)

代码说明
主要功能是通过背景建模检测视频中的运动目标。其工作流程如下:
- 读取视频帧;
- 利用 MOG2 算法生成前景掩码;
- 通过形态学操作(开运算和膨胀)对掩码进行噪声去除和平滑处理;
- 检测前景中的轮廓,并过滤掉小的噪声区域;
- 在原始帧上绘制出运动目标的轮廓和边界框;
- 显示处理后的结果。
具体来说可以应用于安防监控、运动检测、交通监控等领域,在背景相对稳定的场景中表现较好(一定要稳定,不然容易将背景也识别进去)。
1. 导入库
python
import cv2 import numpy as np
- cv2:这是 OpenCV 库,用于计算机视觉相关操作,如图像处理、视频读取、背景建模、形态学操作和轮廓检测等。
- numpy:用于数值计算,特别是对图像数组的操作。
2. 创建背景建模对象
python
backSub = cv2.createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=True)
- cv2.createBackgroundSubtractorMOG2:使用高斯混合模型(MOG2)创建一个背景减除器,可以对视频进行背景建模。
- 参数说明 :
history=500
:指定模型用于背景建模的历史帧数,越大的值适应慢的场景变化。varThreshold=16
:设定阈值,用于判断当前像素是否为前景,值越小敏感度越高。detectShadows=True
:启用阴影检测,可以将阴影区域也标记出来(通常阴影会以灰色显示)。
3. 打开视频源
python
cap = cv2.VideoCapture('video.mp4')
- 使用
cv2.VideoCapture
打开视频文件。 - 参数
'video.mp4'
表示视频文件名,若要使用摄像头,则传入参数0
(或其它对应摄像头的编号)。
4. 逐帧处理视频
python
while True: ret, frame = cap.read() if not ret: break
- cap.read() :从视频中读取一帧。
ret
表示是否读取成功;frame
为当前帧的图像数据。
- 当读取失败(如视频结束)时,跳出循环。
5. 应用背景建模获得前景掩码
python
fgMask = backSub.apply(frame)
- 对每一帧应用背景建模算法,得到一个前景掩码
fgMask
。 - 在该掩码中,前景(运动目标)通常为白色,而背景为黑色(或者带有阴影区域的灰色)。
6. 形态学操作去除噪声
6.1 定义形态学核
python
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
- 这里使用一个椭圆形的核(大小为 3x3),适用于后续的腐蚀、膨胀和开运算等操作。
6.2 开运算去除噪点
python
fgMask = cv2.morphologyEx(fgMask, cv2.MORPH_OPEN, kernel, iterations=1)
- 开运算(先腐蚀后膨胀)用于消除小的噪声点,使前景区域更加平滑。
6.3 膨胀操作填补前景区域空洞
python
fgMask = cv2.dilate(fgMask, kernel, iterations=2)
- 膨胀可以使前景区域中的小空洞被填补,进一步增强目标区域的完整性。
7. 轮廓检测识别动态物体
python
contours, hierarchy = cv2.findContours(fgMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
- cv2.findContours:在前景掩码中查找轮廓。
- 参数说明:
cv2.RETR_EXTERNAL
表示只检测外部轮廓;cv2.CHAIN_APPROX_SIMPLE
对轮廓点进行简单压缩,只保留必要的端点,从而节省内存。
8. 绘制轮廓和边界框
python
for cnt in contours: area = cv2.contourArea(cnt) if area > 500: cv2.drawContours(frame, [cnt], -1, (0, 0, 255), 2) x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
- 遍历所有检测到的轮廓 :
cv2.contourArea(cnt)
计算轮廓的面积。- 过滤掉面积小于 500 的轮廓(通常为噪声)。
- 绘制轮廓 :
- 使用
cv2.drawContours
将符合条件的轮廓用红色(BGR 中(0, 0, 255))绘制在原始帧上。
- 使用
- 绘制边界框 :
- 使用
cv2.boundingRect
得到轮廓的最小外接矩形; - 用
cv2.rectangle
在图像上绘制绿色((0, 255, 0))矩形框,用以标识动态物体的位置。
- 使用
9. 显示处理结果
python
cv2.imshow('原始帧', frame) cv2.imshow('前景掩码', fgMask)
- 分别显示绘制了轮廓和边界框的原始视频帧以及经过形态学处理后的前景掩码。
10. 退出控制与资源释放
python
if cv2.waitKey(30) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
- cv2.waitKey(30) :等待 30 毫秒,同时捕捉键盘输入。按下
q
键时,退出循环。 - 循环结束后,释放视频资源并关闭所有 OpenCV 窗口。

整体代码
python
import cv2
import numpy as np
# 创建背景建模对象,使用高斯混合模型
backSub = cv2.createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=True)
# 打开视频文件,或者使用摄像头(参数0代表摄像头)
cap = cv2.VideoCapture('video.mp4') # 请将'video.mp4'替换成你的文件路径,或使用0打开摄像头
while True:
ret, frame = cap.read()
if not ret:
break
# 应用背景建模,获得前景掩码
fgMask = backSub.apply(frame)
# 形态学操作:先用开运算去除噪声(先腐蚀后膨胀)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
fgMask = cv2.morphologyEx(fgMask, cv2.MORPH_OPEN, kernel, iterations=1)
# 膨胀操作:填补前景区域中的小空洞,使目标区域更加完整
fgMask = cv2.dilate(fgMask, kernel, iterations=2)
# 使用轮廓检测识别动态物体
contours, hierarchy = cv2.findContours(fgMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 在原始帧上绘制轮廓和边界框
for cnt in contours:
area = cv2.contourArea(cnt)
# 过滤掉较小的噪点
if area > 500:
# 绘制轮廓(红色)
cv2.drawContours(frame, [cnt], -1, (0, 0, 255), 2)
# 计算边界框并绘制(绿色)
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示结果
cv2.imshow('原始帧', frame)
cv2.imshow('前景掩码', fgMask)
# 按 'q' 键退出循环
if cv2.waitKey(30) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
效果展示
人物高亮显示效果展示
人物高亮之隐身