OpenCV(10):视频目标跟踪、视频背景减除

ops/2025/2/27 12:19:33/

1 视频目标跟踪

        在计算机视觉领域,视频目标跟踪是一个非常重要的任务。视频目标跟踪广泛应用于监控、自动驾驶、人机交互等多个领域。OpenCV 提供了多种目标跟踪算法,其中 MeanShift 和 CamShift 是两种经典且常用的算法。本文将详细讲解这两种算法的原理、实现步骤以及如何在 OpenCV 中使用它们。

1.1 MeanShift 算法

1.1.1 算法原理

        MeanShift(均值漂移)算法是一种基于密度的非参数化聚类算法,最初用于图像分割,后来被引入到目标跟踪领域。其核心思想是通过迭代计算目标区域的质心,并将窗口中心移动到质心位置,从而实现目标的跟踪。

        MeanShift 算法的基本步骤如下:

  1. 初始化窗口:在视频的第一帧中,手动或自动选择一个目标区域,作为初始窗口。
  2. 计算质心:在当前窗口中,计算目标区域的质心(即像素点的均值)。
  3. 移动窗口:将窗口中心移动到质心位置。
  4. 迭代:重复步骤 2 和 3,直到窗口中心不再变化或达到最大迭代次数。

1.1.2 OpenCV 中的实现

        在 OpenCV 中,MeanShift 算法通过 cv2.meanShift() 函数实现。以下是一个简单的示例代码:

import cv2
import numpy as np# 读取视频
cap = cv2.VideoCapture('example.mp4')
cv2.namedWindow('MeanShift Tracking', cv2.WINDOW_NORMAL)
cv2.resizeWindow('MeanShift Tracking', 640, 480)
# 读取第一帧
ret, frame = cap.read()# 设置初始窗口 (x, y, width, height)
x, y, w, h = 1200, 500, 200, 100
track_window = (x, y, w, h)# 设置 ROI (Region of Interest)
roi = frame[y:y + h, x:x + w]# 转换为 HSV 颜色空间
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)# 创建掩膜并计算直方图
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)# 设置终止条件
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)while True:ret, frame = cap.read()if not ret:break# 转换为 HSV 颜色空间hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)# 计算反向投影dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)# 应用 MeanShift 算法ret, track_window = cv2.meanShift(dst, track_window, term_crit)# 绘制跟踪结果x, y, w, h = track_windowimg2 = cv2.rectangle(frame, (x, y), (x + w, y + h), 255, 2)cv2.imshow('MeanShift Tracking', img2)if cv2.waitKey(25) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

1.1.3 优缺点

        优点

  • 简单易实现,计算效率高。
  • 对目标的形状和大小变化不敏感。

        缺点

  • 对目标的快速运动或遮挡处理能力较差。
  • 窗口大小固定,无法自适应目标大小的变化。

1.2 CamShift 算法

1.2.1 算法原理

        CamShift(Continuously Adaptive MeanShift)算法是 MeanShift 的改进版本,它通过自适应调整窗口大小来更好地跟踪目标。CamShift 算法在 MeanShift 的基础上增加了窗口大小和方向的调整,使其能够适应目标在视频中的尺寸和旋转变化。

        CamShift 算法的基本步骤如下:

  1. 初始化窗口:与 MeanShift 相同,在视频的第一帧中选择初始窗口。
  2. 计算质心:在当前窗口中,计算目标区域的质心。
  3. 移动窗口:将窗口中心移动到质心位置。
  4. 调整窗口大小和方向:根据目标的尺寸和方向调整窗口。
  5. 迭代:重复步骤 2 到 4,直到窗口中心不再变化或达到最大迭代次数。

1.2.2 OpenCV 中的实现

        在 OpenCV 中,CamShift 算法通过 cv2.CamShift() 函数实现。以下是一个简单的示例代码:

import cv2
import numpy as np# 读取视频
cap = cv2.VideoCapture('example.mp4')
cv2.namedWindow('CamShift Tracking', cv2.WINDOW_NORMAL)
cv2.resizeWindow('CamShift Tracking', 640, 480)
# 读取第一帧
ret, frame = cap.read()# 设置初始窗口 (x, y, width, height)
x, y, w, h = 1200, 500, 100, 50
track_window = (x, y, w, h)# 设置 ROI (Region of Interest)
roi = frame[y:y + h, x:x + w]# 转换为 HSV 颜色空间
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)# 创建掩膜并计算直方图
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)# 设置终止条件
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)while True:ret, frame = cap.read()if not ret:break# 转换为 HSV 颜色空间hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)# 计算反向投影dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)# 应用 CamShift 算法ret, track_window = cv2.CamShift(dst, track_window, term_crit)# 绘制跟踪结果pts = cv2.boxPoints(ret)pts = np.int32(pts)img2 = cv2.polylines(frame, [pts], True, (0, 0, 255),2)cv2.imshow('CamShift Tracking', img2)if cv2.waitKey(25) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

1.2.3 优缺点

优点

  • 能够自适应目标的大小和方向变化。
  • 对目标的形状变化和旋转具有较好的鲁棒性。

缺点

  • 对目标的快速运动或遮挡处理能力仍然有限。
  • 计算复杂度略高于 MeanShift。

1.3 MeanShift 与 CamShift 的对比

        MeanShift 和 CamShift 是两种经典的目标跟踪算法,它们在 OpenCV 中都有现成的实现。MeanShift 算法简单高效,适用于目标尺寸和方向变化不大的场景,而 CamShift 算法通过自适应调整窗口大小和方向,能够更好地处理目标尺寸和方向的变化。在实际应用中,可以根据具体需求选择合适的算法。

特性MeanShiftCamShift
窗口大小固定大小自适应调整大小和方向
适用场景目标大小固定的场景目标大小和方向变化的场景
计算复杂度较低较高
实时性较好稍差

2 视频背景减除 (MOG, MOG2)

        在计算机视觉领域,背景减除(Background Subtraction)是一种常用的技术,用于从视频序列中提取前景对象,主要用于检测视频中的运动对象。背景减除的核心思想是通过建模背景,然后将当前帧与背景模型进行比较,从而分离出前景对象。OpenCV 提供了多种背景减除算法,其中 MOG(Mixture of Gaussians)和 MOG2 是最常用的两种方法。其基本流程如下:

  1. 背景建模:通过分析视频序列中的多帧图像,建立一个背景模型。
  2. 前景检测:将当前帧与背景模型进行比较,找出与背景差异较大的区域,这些区域即为前景对象。
  3. 背景更新:随着时间的推移,背景可能会发生变化(如光照变化、背景物体的移动等),因此需要不断更新背景模型。

      背景消除主要应用:

  • 视频监控: 用于检测监控视频中的移动目标,如行人、车辆等。
  • 运动分析: 用于分析视频中目标的运动轨迹和行为。
  • 人机交互: 用于检测用户的手势或面部,实现人机交互。

2.1 MOG(Mixture of Gaussians)算法

2.1.1 原理

        MOG 算法是一种基于高斯混合模型(Gaussian Mixture Model, GMM)的背景减除方法。其核心思想是使用多个高斯分布来建模背景中的像素值。每个像素的值被看作是一个随机变量,其分布由多个高斯分布组成。通过这种方式,MOG 能够处理背景中的复杂变化,如光照变化、阴影等。算法步骤:

  1. 初始化:为每个像素初始化多个高斯分布。
  2. 模型更新:对于每一帧图像,更新每个像素的高斯分布参数(均值、方差、权重)。
  3. 前景检测:将当前帧的像素值与背景模型中的高斯分布进行比较,如果像素值不在任何高斯分布的范围内,则将其标记为前景。

2.1.2 OpenCV 中的实现

        在 OpenCV 中,MOG 算法可以通过 cv2.bgsegm.createBackgroundSubtractorMOG() 函数来创建背景减除器。以下是一个简单的示例代码:

        如果cv2.bgsegm报错需要安装扩展包:

pip install opencv-contrib-python
import cv2# 创建 MOG 背景减除器
mog = cv2.bgsegm.createBackgroundSubtractorMOG()# 读取视频
cap = cv2.VideoCapture('example.mp4')while True:ret, frame = cap.read()if not ret:break# 应用背景减除fg_mask = mog.apply(frame)# 显示结果cv2.imshow('Frame', frame)cv2.imshow('FG Mask', fg_mask)if cv2.waitKey(30) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

2.2 MOG2(Mixture of Gaussians Version 2)算法

2.2.1 原理

        MOG2 是 MOG 的改进版本,主要区别在于它能够自动选择高斯分布的数量,并且能够更好地适应背景的变化。MOG2 通过动态调整高斯分布的数量和参数,能够更准确地建模背景,从而提高前景检测的准确性。算法步骤:

  1. 初始化:为每个像素初始化多个高斯分布。
  2. 模型更新:对于每一帧图像,更新每个像素的高斯分布参数,并根据需要增加或减少高斯分布的数量。
  3. 前景检测:将当前帧的像素值与背景模型中的高斯分布进行比较,如果像素值不在任何高斯分布的范围内,则将其标记为前景。

    2.2.2 OpenCV 中的实现

            在 OpenCV 中,MOG2 算法可以通过 cv2.createBackgroundSubtractorMOG2() 函数来创建背景减除器。以下是一个简单的示例代码:

    import cv2# 创建 MOG 背景减除器
    mog = cv2.createBackgroundSubtractorMOG2()# 读取视频
    cap = cv2.VideoCapture('example.mp4')
    cv2.namedWindow('Frame', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('Frame', 640, 480)
    cv2.namedWindow('FG Mask', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('FG Mask', 640, 480)while True:ret, frame = cap.read()if not ret:break# 应用背景减除fg_mask = mog.apply(frame)# 显示结果cv2.imshow('Frame', frame)cv2.imshow('FG Mask', fg_mask)if cv2.waitKey(30) & 0xFF == ord('q'):breakcap.release()
    cv2.destroyAllWindows()
    

    2.3 MOG 与 MOG2 的比较

            背景减除是视频分析中的重要技术,MOG 和 MOG2 是 OpenCV 中常用的两种背景减除算法。MOG 算法通过固定数量的高斯分布来建模背景,适用于背景变化较少的场景,而 MOG2 算法通过动态调整高斯分布的数量和参数,能够更好地适应背景的变化,适用于背景变化较多的场景。

    特性MOGMOG2
    高斯分布数量固定动态调整
    背景更新速度较慢较快
    适应背景变化能力较弱较强
    计算复杂度较低较高
    适用场景背景变化较少的场景背景变化较多的场景

    http://www.ppmy.cn/ops/161669.html

    相关文章

    Git原理+使用(超详细)

    Git初识 当我们写项目代码时,需要不断的更新版本,那么就需要一个东西去管理这些不同版本的文件—版本控制器。 目前最主流的版本控制器就是Git。它是一个可以记录工程的每一次改动和版本迭代的管理系统,同时方便多人协同作业。 &#xff0…

    el-table

    el-table合并 参考&#xff1a; https://www.jianshu.com/p/6067708bd1ee https://blog.csdn.net/weixin_43862642/article/details/122055745 某个列合并&#xff0c;前面序号也要跟着对应合并 <el-table:data"list":span-method"objectSpanMethod" …

    协方差(Covariance)与得分函数:从Fisher信息矩阵看统计关联

    协方差与得分函数&#xff1a;从Fisher信息矩阵看统计关联 协方差&#xff08;Covariance&#xff09;是统计学中一个基础但强大的概念&#xff0c;它描述了两个随机变量之间的关系。在Fisher信息矩阵中&#xff0c;协方差以一种特别的形式出现&#xff1a;得分函数的协方差。…

    Spring Boot 项目中如何在 `pom.xml` 文件中引入本地 JAR 包

    文章目录 Spring Boot 项目中如何在 pom.xml 文件中引入本地 JAR 包1. 准备工作2. 将本地 JAR 包安装到本地 Maven 仓库2.1 使用 mvn install:install-file 命令2.2 验证安装 3. 在 pom.xml 中引入本地 JAR 包3.1 添加依赖3.2 完整示例 4. 使用 system 作用域引入本地 JAR 包&a…

    开源一款DDS信号发生扩展板-FreakStudio多米诺系列

    原文链接&#xff1a; FreakStudio的博客 摘要 信号发生扩展板通过SPI接口生成可调频率和幅度的正弦波、方波和三角波&#xff0c;频率小于1MHz。支持幅度调节&#xff0c;提供原始和6倍放大输出接口。配备5阶低通滤波器、噪声抑制功能&#xff0c;优化信号稳定性。 往期推…

    普中单片机-51TFT-LCD显示屏(1.8寸 STM32)

    普中官方论坛&#xff1a; http://www.prechin.cn/gongsixinwen/208.html 普中科技-各型号开发板资料链接&#xff1a;https://www.bilibili.com/read/cv23681775/?spm_id_from333.999.0.0 27-TFTLCD显示实验_哔哩哔哩_bilibili 2.程序烧录 2.1设置彩屏驱动 3.实验效果

    捌拾- 量子态层析 以及 布洛赫球 (1)

    1. 奥卡姆剃刀 在上一篇学习文章中 柒拾玖- 贝尔不等式 &#xff0c;我感觉&#xff0c;为啥这么量子计算的门槛那么高呢&#xff1f; 结果我打开了上级目录&#xff0c;发现&#xff0c;原来他是按首字母排序… 经过一系列查看&#xff0c;我挑了一个最简单的 量子态层析 …

    1472.设计浏览器历史记录

    这里是模拟浏览器的回退和前进 用一个列表来存储浏览器的历史记录 cur指向当前浏览器记录的位置 visit 就是清空之前访问过的历史记录&#xff0c;把当前的放进去 self.cur1代表进下一个访问 然后删掉 当前的和之前的&#xff0c;加入新的 前进和回退要考虑边界 class Browser…