计算机视觉——Opencv(背景建模实现目标检测)

一、背景建模是是什么

指在计算机视觉中,从视频序列中提取出静态背景的一种技术。在视频中,背景通常被定义为相对稳定的部分,例如墙壁、地面或天空等。

背景建模的目标是将动态的前景对象与静态的背景进行分离,以便进一步分析和处理。

二、背景建模的目的

通过背景建模,我们可以实现很多应用,例如运动检测、目标跟踪

三、背景建模的方法

1、帧差法backgroundSubtractor

2、基于K近邻的背景/前景分割算法BackgroundSubtractorKNN

3、基于高斯混合的背景/前景分割算法BackgroundSubtractorMOG2

帧差法的原理

由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值,当绝对值超过一定阈值时,即可判断为运动目标,从而实现目标的检测功能。

帧差法的优缺点

帧差法非常简单,但是会引入噪音和空洞(人物中间是黑色的)问题

四、核心技术原理

1、混合高斯模型(MOG2):背景建模与前景提取

视频由一帧帧连续的图像组成,运动目标检测的本质是区分 "静止背景" 和 "运动前景"

混合高斯模型(Gaussian Mixture Model, GMM)是实现这一目标的经典算法,OpenCV 封装的createBackgroundSubtractorMOG2是其优化版本,核心优势如下:

  • 自适应背景更新:能自动学习并更新背景模型,适应光线变化、背景轻微扰动(如树叶晃动)等场景;

  • 前景掩码输出:处理后会生成一张黑白掩码图(前景掩码),白色区域代表运动目标,黑色区域代表背景;

  • 无需手动标注:无需提前采集背景帧,可直接对视频流进行实时处理。

2、形态学开运算:去除噪点干扰

通过 MOG2 提取的前景掩码通常会包含大量细小噪点(如光线突变、视频压缩噪声),这些噪点会干扰后续的轮廓检测。形态学开运算(先腐蚀后膨胀)能有效解决这个问题:

  • 腐蚀:消除小的亮区域(噪点),收缩前景目标的边界;

  • 膨胀:恢复前景目标的原始大小,弥补腐蚀造成的边界收缩;

  • 组合效果:保留大面积的运动目标,去除零散的小噪点,让前景轮廓更规整。

3、轮廓检测与筛选:精准定位运动目标

在处理后的前景掩码基础上,通过轮廓检测找到所有连通的前景区域,再通过轮廓周长 / 面积筛选,排除小的无效区域,最终用矩形框标出真正的运动目标,实现 "检测 - 定位" 一体化

五、完整代码与解析

python 复制代码
import cv2

# 1. 读取测试视频文件(替换为你的视频路径)
cap = cv2.VideoCapture(r"E:\xwechat_files\wxid_qi43v1w2nqcb12_e432\msg\file\2026-01\test(1).avi")

# 2. 创建形态学运算卷积核(十字形,3x3)
# MORPH_CROSS:十字形核,适合保留目标的边缘特征;ksize=(3,3):核大小,越小越精细
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, ksize=(3, 3))

# 3. 初始化混合高斯背景建模器
# createBackgroundSubtractorMOG2:默认参数已适配大多数场景,可添加detectShadows=False去除阴影检测
fgbg = cv2.createBackgroundSubtractorMOG2()

# 4. 循环处理视频每一帧
while True:
    # 读取当前帧:ret为布尔值(是否读取成功),frame为帧图像(BGR格式)
    ret, frame = cap.read()
    if not ret:  # 读取失败(如视频结束),退出循环
        break

    # 显示原始视频帧
    cv2.imshow('Original Frame', frame)

    # 5. 应用背景建模,提取前景掩码
    # fgmask:8位灰度图,白色(255)为前景(运动目标),黑色(0)为背景
    fgmask = fgbg.apply(frame)
    cv2.imshow('Foreground Mask (Raw)', fgmask)

    # 6. 形态学开运算:去除噪点,优化前景掩码
    # MORPH_OPEN:开运算(腐蚀→膨胀),消除小噪点,保留大的运动区域
    fgmask_new = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
    cv2.imshow('Foreground Mask (Processed)', fgmask_new)

    # 7. 轮廓检测:查找前景掩码中的所有轮廓
    # RETR_EXTERNAL:只检索最外层轮廓,减少计算量;CHAIN_APPROX_SIMPLE:压缩轮廓点,节省内存
    contours, hierarchy = cv2.findContours(fgmask_new, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 8. 遍历轮廓,筛选并绘制运动目标矩形框
    for c in contours:
        # 计算轮廓周长,用于筛选小的无效区域
        perimeter = cv2.arcLength(c, closed=True)
        # 周长阈值(188):可根据视频分辨率/目标大小调整,过滤小噪点轮廓
        if perimeter > 188:
            # 计算轮廓的外接矩形:x(左)、y(上)、w(宽)、h(高)
            x, y, w, h = cv2.boundingRect(c)
            # 在原始帧上绘制绿色矩形框(BGR格式:(0,255,0))
            cv2.rectangle(frame, pt1=(x, y), pt2=(x + w, y + h), color=(0, 255, 0), thickness=2)

    # 显示绘制了目标框的视频帧
    cv2.imshow('Motion Detection Result', frame)

    # 9. 按键控制:等待60ms,按ESC键(27)退出
    k = cv2.waitKey(60) & 0xFF  # 0xFF解决跨平台按键兼容问题
    if k == 27:
        break

# 10. 释放资源:关闭视频流,销毁所有窗口
cap.release()
cv2.destroyAllWindows()

形态学卷积核创建:

python 复制代码
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, ksize=(3, 3))
  • cv2.MORPH_CROSS:十字形卷积核,相比矩形核,能更好地保留目标的边缘细节,适合细长型运动目标(如行人、车辆);

  • ksize=(3,3):核的大小为 3×3,是平衡去噪效果和计算效率的常用值;若噪点较多,可改为(5,5),但会增加计算量。

混合高斯模型初始化

python 复制代码
fgbg = cv2.createBackgroundSubtractorMOG2()

该函数默认开启阴影检测(detectShadows=True),阴影区域会显示为灰色(值为 127),若不需要检测阴影,可改为:

python 复制代码
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=False)

前景掩码提取与优化

python 复制代码
fgmask = fgbg.apply(frame)
fgmask_new = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
  • fgbg.apply(frame):对当前帧进行背景建模,输出的fgmask是灰度图,白色区域为运动目标;

  • cv2.morphologyEx(..., cv2.MORPH_OPEN, kernel):开运算先腐蚀后膨胀,核心作用是 "去小留大"------ 消除面积小于卷积核的噪点,同时不改变大目标的整体形状。

轮廓检测与筛选

python 复制代码
contours, hierarchy = cv2.findContours(fgmask_new, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
    perimeter = cv2.arcLength(c, closed=True)
    if perimeter > 188:
        x, y, w, h = cv2.boundingRect(c)
        cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)
  • cv2.findContours:返回所有轮廓的列表,每个轮廓是一组点的坐标;

  • cv2.arcLength(c, True):计算轮廓的闭合周长,阈值188是经验值 ------ 需根据视频分辨率调整(如 720P 视频可设为 100,4K 视频可设为 300);

  • cv2.boundingRect(c):为每个符合条件的轮廓生成最小外接矩形,用cv2.rectangle绘制在原始帧上,实现目标可视化。

运行结果

运行代码,会弹出 4 个窗口:

Original Frame:原始视频帧;

Foreground Mask (Raw):MOG2 提取的原始前景掩码(含噪点);

Foreground Mask (Processed):开运算处理后的前景掩码(无噪点);

Motion Detection Result:绘制了绿色矩形框的最终检测结果;

相关推荐
伴野星辰19 小时前
如何提高YOLO8目标检测的准确性?
人工智能·目标检测·机器学习
美狐美颜sdk1 天前
2026主流直播美颜sdk对比:效果、算法与成本分析
前端·人工智能·计算机视觉·美颜sdk·直播美颜sdk·第三方美颜sdk·视频美颜sdk
EDPJ1 天前
从 Grounding DINO 到 DINO-X:开放集目标检测的架构演进与细节拆解
目标检测·计算机视觉·架构·图像分割·图像分类
code_pgf1 天前
目标检测(AABB)评估指标
目标检测
code_pgf1 天前
VOC/COCO风格评估差异对照表
人工智能·目标检测
xinxiangwangzhi_1 天前
CREStereo 论文总结(2022)
计算机视觉
reset20211 天前
安防监控中目标检测方案探讨
人工智能·yolo·目标检测·目标跟踪
Fevered 路小小呀!1 天前
mediapipe新版本怎么玩--面部特征检测
人工智能·python·计算机视觉
Hong_Youth1 天前
OpenCV + YOLOv5 落地工程:视频实时计数、追踪、画线统计
opencv·yolo·音视频
sali-tec1 天前
C# 基于OpenCv的视觉工作流-章45-圆卡尺
图像处理·人工智能·opencv·算法·计算机视觉