《OpenCV》—— 背景建模

news/2025/2/27 6:26:22

背景建模是什么?

在这里插入图片描述

背景建模的意义?

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

背景建模的方法

在这里插入图片描述

帧差法

帧差法的原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于 K 近邻的前景分割算法(KNN)

原理

基于 K 近邻的前景分割算法是一种基于统计的背景建模方法。该算法为每个像素位置维护一个样本集,样本集中存储了该像素在历史帧中的取值。在检测当前帧的像素时,计算该像素值与样本集中每个样本的距离,根据距离最近的 K 个样本的情况来判断该像素是属于背景还是前景。如果该像素与背景样本集的距离小于某个阈值,则认为它是背景像素;否则,认为它是前景像素。

优缺点

  • 优点
    • 对背景变化适应性强:能够较好地适应背景的缓慢变化和动态背景,因为它可以不断更新样本集来反映背景的变化。
    • 鲁棒性较好:在一定程度上能够抵抗噪声的干扰,对于复杂场景有较好的分割效果。
  • 缺点
    • 计算复杂度较高:需要维护每个像素的样本集,并且在检测时需要计算距离,随着样本集的增大,计算量也会相应增加。
    • 参数选择敏感:K 值和距离阈值的选择对分割效果影响较大,需要根据具体场景进行调整。

基于高斯混合的背景分割算法(GMM)

原理

基于高斯混合的背景分割算法假设每个像素的颜色值(或灰度值)服从多个高斯分布的混合。每个高斯分布代表背景中的一种模式,例如不同的光照条件或背景物体的颜色变化。通过对视频序列的学习,估计每个像素位置处高斯分布的参数(均值、协方差和权重)。在检测时,根据当前像素值与各个高斯分布的匹配程度判断其属于背景还是前景。如果当前像素值与某个高斯分布的匹配度较高,且该高斯分布的权重较大,则认为该像素属于背景;否则,认为它是前景像素。

优缺点

  • 优点
    • 能处理复杂背景:可以很好地处理背景中的多模态情况,如不同颜色的背景物体、光照变化等,对复杂背景有较强的建模能力。
    • 自适应更新:能够自适应地更新背景模型,随着时间的推移,不断调整高斯分布的参数,以适应背景的变化。
  • 缺点
    • 计算复杂度高:需要估计多个高斯分布的参数,计算量较大,尤其是在高分辨率图像和复杂场景下,处理速度较慢。
    • 初始化和参数调整困难:高斯分布的数量、初始参数等的选择对分割效果影响较大,需要一定的经验和实验来确定合适的参数。

实例

本实例使用基于高斯混合模型实现背景建模。

  • 导入所需库
import cv2
  • 打开视频
# 打开视频文件 'test.avi',用于后续视频帧的读取
cap = cv2.VideoCapture('test.avi')
  • 创建结构元素
# getStructuringElement(shape,ksize,anchor=None)得到一个结构元素。主要用于后续的腐蚀、膨胀、开、闭等运算。
# 参数:
# shape:设定卷积核的形状,可选如下三个参数:
# ①:MORPH_RECT(矩形卷积核)
# ②:MORPH_CROSS(十字形卷积核)
# ③:MORPH_ELLIPSE(圆形卷积核)
# ksize:设定卷积核的大小。
# anchor:表示锚点的位置,一般 (-1, -1) 表示锚点位于中心
# 这里创建一个 3x3 的十字形结构元素,用于后续的形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
  • 创建背景减除器
# 创建基于高斯混合模型(GMM)的背景减除器对象
# 该对象可以从视频帧中分离出前景和背景
fgbg = cv2.createBackgroundSubtractorMOG2()

  • 逐帧处理视频
# 进入循环,逐帧处理视频
while (True):
    # 从视频中读取一帧,ret 为布尔值,表示是否成功读取到帧,frame 为读取到的帧图像
    ret, frame = cap.read()
    if not ret:
        # 如果没有成功读取到帧,说明视频结束,退出循环
        break
    # 显示原始的视频帧
    cv2.imshow('frame', frame)

    # 将当前帧图像输入到背景减除器中,得到前景掩码
    # 前景掩码是一个二值图像,前景像素为白色,背景像素为黑色
    fgmask = fgbg.apply(frame)
    # 显示前景掩码
    cv2.imshow('fgmask', fgmask)

    # 对前景掩码进行开运算,开运算先进行腐蚀操作,再进行膨胀操作
    # 可以去除小的噪声点和连接断开的物体,使用之前创建的十字形结构元素
    fgmask_new = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
    # 显示经过开运算后的前景掩码
    cv2.imshow('fgmask1', fgmask_new)

    # 在经过开运算后的前景掩码中查找轮廓
    # cv2.findContours 函数返回三个值,这里我们只关注第二个值 contours,它是一个包含所有轮廓点的列表
    # cv2.RETR_EXTERNAL 表示只检测外部轮廓
    # cv2.CHAIN_APPROX_SIMPLE 表示只保留轮廓的端点,压缩轮廓数据
    _, contours, h = cv2.findContours(fgmask_new, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 遍历所有检测到的轮廓
    for c in contours:
        # 计算当前轮廓的周长
        perimeter = cv2.arcLength(c, True)
        # 如果轮廓的周长大于 188,认为是一个较大的前景物体
        if perimeter > 188:
            # 计算当前轮廓的外接矩形,返回矩形的左上角坐标 (x, y) 以及宽度 w 和高度 h
            x, y, w, h = cv2.boundingRect(c)
            # 在原始视频帧上绘制该外接矩形,颜色为绿色(0, 255, 0),线宽为 2
            fgmask_new_rect = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 显示绘制了外接矩形的视频帧
    cv2.imshow('fgmask_new_rect', fgmask_new_rect)

    # 等待 60 毫秒,等待用户按键
    k = cv2.waitKey(60)
    # 如果用户按下 ESC 键(键码为 27),则退出循环
    if k == 27:
        break

  • 释放视频捕获对象,关闭所有打开的窗口
cap.release()
cv2.destroyAllWindows()

主要功能是读取视频文件,使用高斯混合模型进行背景减除,对前景掩码进行开运算去除噪声,然后检测前景物体的轮廓,对周长大于一定阈值的轮廓绘制外接矩形,最后显示处理后的视频帧。
结果:
在这里插入图片描述

完整代码

import cv2

# 打开视频文件 'test.avi',用于后续视频帧的读取
cap = cv2.VideoCapture('test.avi')

# getStructuringElement(shape,ksize,anchor=None)得到一个结构元素。主要用于后续的腐蚀、膨胀、开、闭等运算。
# 参数:
# shape:设定卷积核的形状,可选如下三个参数:
# ①:MORPH_RECT(矩形卷积核)
# ②:MORPH_CROSS(十字形卷积核)
# ③:MORPH_ELLIPSE(圆形卷积核)
# ksize:设定卷积核的大小。
# anchor:表示锚点的位置,一般 (-1, -1) 表示锚点位于中心
# 这里创建一个 3x3 的十字形结构元素,用于后续的形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))

# 创建基于高斯混合模型(GMM)的背景减除器对象
# 该对象可以从视频帧中分离出前景和背景
fgbg = cv2.createBackgroundSubtractorMOG2()

# 进入循环,逐帧处理视频
while (True):
    # 从视频中读取一帧,ret 为布尔值,表示是否成功读取到帧,frame 为读取到的帧图像
    ret, frame = cap.read()
    if not ret:
        # 如果没有成功读取到帧,说明视频结束,退出循环
        break
    # 显示原始的视频帧
    cv2.imshow('frame', frame)

    # 将当前帧图像输入到背景减除器中,得到前景掩码
    # 前景掩码是一个二值图像,前景像素为白色,背景像素为黑色
    fgmask = fgbg.apply(frame)
    # 显示前景掩码
    cv2.imshow('fgmask', fgmask)

    # 对前景掩码进行开运算,开运算先进行腐蚀操作,再进行膨胀操作
    # 可以去除小的噪声点和连接断开的物体,使用之前创建的十字形结构元素
    fgmask_new = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
    # 显示经过开运算后的前景掩码
    cv2.imshow('fgmask1', fgmask_new)

    # 在经过开运算后的前景掩码中查找轮廓
    # cv2.findContours 函数返回三个值,这里我们只关注第二个值 contours,它是一个包含所有轮廓点的列表
    # cv2.RETR_EXTERNAL 表示只检测外部轮廓
    # cv2.CHAIN_APPROX_SIMPLE 表示只保留轮廓的端点,压缩轮廓数据
    _, contours, h = cv2.findContours(fgmask_new, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 遍历所有检测到的轮廓
    for c in contours:
        # 计算当前轮廓的周长
        perimeter = cv2.arcLength(c, True)
        # 如果轮廓的周长大于 188,认为是一个较大的前景物体
        if perimeter > 188:
            # 计算当前轮廓的外接矩形,返回矩形的左上角坐标 (x, y) 以及宽度 w 和高度 h
            x, y, w, h = cv2.boundingRect(c)
            # 在原始视频帧上绘制该外接矩形,颜色为绿色(0, 255, 0),线宽为 2
            fgmask_new_rect = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 显示绘制了外接矩形的视频帧
    cv2.imshow('fgmask_new_rect', fgmask_new_rect)

    # 等待 60 毫秒,等待用户按键
    k = cv2.waitKey(60)
    # 如果用户按下 ESC 键(键码为 27),则退出循环
    if k == 27:
        break

# 释放视频捕获对象,关闭所有打开的窗口
cap.release()
cv2.destroyAllWindows()

http://www.niftyadmin.cn/n/5868159.html

相关文章

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: #

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: # 如下: 项目文件目录如下: pytest.ini文件内容: [pytest] addopts -v -s --alluredir ./allure-results # 自动添加的命令行参数:# -…

【利用conda配置管理Python版本和依赖环境】

1. 创建新的Python环境 # conda create -n [虚拟环境名] python[python指定的版本] # -y直接安装不用询问,没有时,会提示询问等待用户确定才安装 conda create -n pygnu python3.10 -y验证并检查新建的Python环境 conda activate pygun python --versi…

uni-app 开发 App 、 H5 横屏签名(基于lime-signature)

所用插件&#xff1a;lime-signature 使用到 CSS 特性 绝对定位transform 旋转transform-origin transform 原点 复习一下定位元素&#xff08;相对定位、绝对定位、粘性定位&#xff09; 代码# <template><view class"signature-page"><view clas…

Java多线程中的死锁问题

1.什么是死锁 线程在获取资源的时候&#xff0c;由于获取不到&#xff0c;导致线程卡死&#xff08;阻塞&#xff09;&#xff0c;程序就不执行了。 2.发生死锁的情况 1.一个线程获取一把锁 一个线程如果同时获取一把锁两次&#xff0c;如果是可重入锁&#xff0c;就没有问…

Maven 从下载到实战,xml帮助文档

一、Maven 免费下载 1. 官方下载地址 官网推荐&#xff1a;访问 Maven 官网&#xff0c;选择最新稳定版本&#xff08;如 3.8.1 或 3.6.3&#xff09;的 bin.zip 文件179。 国内镜像&#xff1a;若官网下载缓慢&#xff0c;可使用以下网盘资源&#xff08;注意版权风险&#…

Mac 上安装多版本的 JDK 且实现 自由切换

1.可以通过查看以下目录中的内容&#xff0c;确认当前已经安装的 jdk 版本。 cd /Library/Java/JavaVirtualMachines2.命令行查看 jdk 的安装路径 /usr/libexec/java_home -V3.下载要安装的jdk版本&#xff0c;修改环境变量( cat ~/.bash_profile) # 定义JDK 8和JDK 17的安装路…

Ajax数据采集与分析详解

文章目录 1. 什么是 Ajax&#xff1f;2. Ajax 的工作原理3. Ajax 在网页中的应用场景4. 爬取 Ajax 数据的方法4.1 分析网络请求4.2 模拟 Ajax 请求4.3 使用 Selenium 模拟浏览器4.4 使用 Headless 浏览器 5. 处理动态参数6. 处理分页和滚动加载7. 处理反爬虫机制8. 数据存储9. …

IPTools for .NET:快速查询全球IP信息

IPTools for .NET&#xff1a;快速查询全球IP信息 IPTools 是一个用于快速查询全球 IP 地址信息的库&#xff0c;支持国内和国际 IP 查询&#xff0c;提供详细的地理位置信息&#xff08;如国家、省份、城市&#xff09;以及经纬度等数据。 1. IPTools.China IPTools.China …