OpenCV 自适应背景更新 cv2.accumulateWeighted

OpenCV 自适应背景更新 cv2.accumulateWeighted

flyfish

cv2.accumulateWeighted 主要用于实现自适应背景更新。

作用

在视频处理中,背景通常是相对稳定的部分,而前景则是在背景上移动或变化的物体。自适应背景更新的目的是根据视频帧的变化动态地更新背景模型,以适应光照变化、背景缓慢移动等情况。cv2.accumulateWeighted 函数可以帮助我们逐步更新背景模型,使得背景模型能够更好地反映当前的背景状态。

原理

cv2.accumulateWeighted 函数基于加权平均的方法来更新背景模型。对于每一帧视频图像,它会将当前帧与之前存储的背景模型进行加权平均,得到新的背景模型。具体的计算公式如下:

B n e w = α × F + ( 1 − α ) × B o l d B_{new} = \alpha \times F + (1 - \alpha) \times B_{old} Bnew=α×F+(1−α)×Bold

其中:

  • B n e w B_{new} Bnew 是更新后的背景模型。
  • α \alpha α 是加权系数,取值范围是 0 < α ≤ 1 0 < \alpha \leq 1 0<α≤1。 α \alpha α 越大,当前帧在新背景模型中所占的权重就越大,背景模型更新得就越快;反之, α \alpha α 越小,背景模型更新得就越慢。
  • F F F 是当前帧的图像。
  • B o l d B_{old} Bold 是之前的背景模型。

使用方法

下面是一个使用 cv2.accumulateWeighted 进行自适应背景更新的示例代码:

python 复制代码
import cv2

# 打开视频文件
cap = cv2.VideoCapture('input_video.mp4')

# 读取第一帧作为初始背景
ret, frame = cap.read()
if not ret:
    print("无法读取视频帧")
    exit()

# 将第一帧转换为灰度图像
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 创建一个与帧大小相同的背景模型,初始化为第一帧
background = gray.copy().astype("float")

# 定义加权系数
alpha = 0.01

while True:
    # 读取下一帧
    ret, frame = cap.read()
    if not ret:
        break

    # 将当前帧转换为灰度图像
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 使用 cv2.accumulateWeighted 更新背景模型
    cv2.accumulateWeighted(gray, background, alpha)

    # 将背景模型转换为 8 位无符号整数类型
    background_vis = cv2.convertScaleAbs(background)

    # 计算当前帧与背景模型的差值
    diff = cv2.absdiff(gray, background_vis)

    # 对差值图像进行阈值处理,得到前景掩码
    _, thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)

    # 显示原始帧、背景模型和前景掩码
    cv2.imshow('Original Frame', frame)
    cv2.imshow('Background Model', background_vis)
    cv2.imshow('Foreground Mask', thresh)

    # 按 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

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

简单写

py 复制代码
import cv2
import numpy as np

video_path = 'input_video.mp4'
cap = cv2.VideoCapture(video_path)

# 初始化背景模型
ret, first_frame = cap.read()
background = np.zeros_like(first_frame[:, :, 0], dtype=np.float32)  # 初始化为全0或第一帧
alpha = 0.05  # 学习率

while True:
    ret, frame = cap.read()
    if not ret:
        break
    
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 转为 float32 类型(与背景模型类型一致)
    frame_gray = frame_gray.astype(np.float32)
    
    # 自适应更新背景
    cv2.accumulateWeighted(frame_gray, background, alpha)
    background_uint8 = background.astype(np.uint8)
    
    # 显示背景模型
    cv2.imshow('Background', background_uint8)
    if cv2.waitKey(1) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

1. cv2.accumulateWeighted(frame_gray, background, alpha)

作用
  • 动态更新背景模型
    通过加权平均的方式,将当前帧的灰度图像 frame_gray 与历史背景模型 background 结合,逐步更新背景,使其适应场景中的缓慢变化(如光线变化、轻微移动的物体等)。
参数说明
  • frame_gray :当前帧的灰度图像(单通道,通常为 float32 类型)。
  • background :背景模型(初始化为与 frame_gray 相同大小的 float32 数组)。
  • alpha学习率 (取值范围 0 < alpha < 1),控制新帧与旧背景的权重:
    • alpha 越小:背景更新越慢,对缓慢变化(如光线)更鲁棒,但对快速变化(如新物体进入)反应较慢。
    • alpha 越大:背景更新越快,能更快适应新变化,但可能对噪声更敏感。
数学公式

cv2.accumulateWeighted 的计算公式为:

KaTeX parse error: Expected 'EOF', got '_' at position 47: ...mes \text{frame_̲gray} + (1 - \a...

  • 初始化时background 需要先初始化为第一帧的灰度值(或全零)。
  • 效果
    每一帧的背景模型都会逐渐融合新帧的信息,但历史帧的贡献随时间衰减(呈指数衰减)。

2. background_uint8 = background.astype(np.uint8)

作用
  • 数据类型转换
    将背景模型 backgroundfloat32 类型)转换为 uint8 类型(0-255 的整数),以便后续显示或处理。

cv2.accumulateWeighted 函数是基于指数加权平均(Exponential Moving Average,EMA)的原理来更新背景模型,其核心公式如下:

公式表示

S t = α × X t + ( 1 − α ) × S t − 1 S_{t}=\alpha\times X_{t}+(1 - \alpha)\times S_{t - 1} St=α×Xt+(1−α)×St−1

公式参数解释

  • S t S_{t} St :表示第 t t t 时刻更新后的背景模型。在图像处理中,通常对应于经过加权平均后得到的新的背景图像。
  • α \alpha α :是加权系数,也被称为学习率,取值范围为 0 < α ≤ 1 0 < \alpha\leq1 0<α≤1。它控制着当前帧图像在更新背景模型时所占的权重。
    • 当 α \alpha α 接近 1 时,意味着当前帧图像在新的背景模型中占比很大,背景模型会快速适应图像的变化,能快速跟上场景的动态变化,但也可能会过于敏感,将前景物体误当作背景的一部分进行更新。
    • 当 α \alpha α 接近 0 时,当前帧图像在新背景模型中占比很小,背景模型更新缓慢,对场景变化的响应较为迟钝,不过这样可以减少因短期干扰(如快速移动的物体)对背景模型的影响。
  • X t X_{t} Xt :代表第 t t t 时刻的当前帧图像。在处理视频时,就是每一帧的图像数据。
  • S t − 1 S_{t - 1} St−1 :是第 t − 1 t - 1 t−1 时刻的背景模型,也就是上一次更新得到的背景图像。

cv2.accumulateWeighted(gray, background, alpha) 其中 gray 对应公式里的 X t X_{t} Xt,background 对应 S t − 1 S_{t - 1} St−1 和 S t S_{t} St(更新前后的背景模型),alpha 就是公式中的 α \alpha α。每次调用该函数时,就会按照上述公式更新背景模型。

虽然在原始的递推公式 S t = α × X t + ( 1 − α ) × S t − 1 S_{t}=\alpha\times X_{t}+(1 - \alpha)\times S_{t - 1} St=α×Xt+(1−α)×St−1 里没有直接呈现指数,但通过展开公式就能发现 ( 1 − α ) (1 - \alpha) (1−α) 的指数形式。

指数加权的体现

从该公式出发,若持续迭代展开这个式子,就能清晰看到指数的存在。

对于第 t t t 时刻的背景模型 S t S_{t} St,通过不断代入前一时刻的公式进行展开:

  • 当 t = 1 t = 1 t=1 时, S 1 = α × X 1 + ( 1 − α ) × S 0 S_{1}=\alpha\times X_{1}+(1 - \alpha)\times S_{0} S1=α×X1+(1−α)×S0。
  • 当 t = 2 t = 2 t=2 时, S 2 = α × X 2 + ( 1 − α ) × S 1 = α × X 2 + ( 1 − α ) ( α × X 1 + ( 1 − α ) × S 0 ) = α × X 2 + α ( 1 − α ) × X 1 + ( 1 − α ) 2 × S 0 S_{2}=\alpha\times X_{2}+(1 - \alpha)\times S_{1}=\alpha\times X_{2}+(1 - \alpha)(\alpha\times X_{1}+(1 - \alpha)\times S_{0})=\alpha\times X_{2}+\alpha(1 - \alpha)\times X_{1}+(1 - \alpha)^2\times S_{0} S2=α×X2+(1−α)×S1=α×X2+(1−α)(α×X1+(1−α)×S0)=α×X2+α(1−α)×X1+(1−α)2×S0。
  • 当 t = 3 t = 3 t=3 时, S 3 = α × X 3 + ( 1 − α ) × S 2 = α × X 3 + α ( 1 − α ) × X 2 + α ( 1 − α ) 2 × X 1 + ( 1 − α ) 3 × S 0 S_{3}=\alpha\times X_{3}+(1 - \alpha)\times S_{2}=\alpha\times X_{3}+\alpha(1 - \alpha)\times X_{2}+\alpha(1 - \alpha)^2\times X_{1}+(1 - \alpha)^3\times S_{0} S3=α×X3+(1−α)×S2=α×X3+α(1−α)×X2+α(1−α)2×X1+(1−α)3×S0。

以此类推,对于第 t t t 时刻的 S t S_{t} St,可以得到展开式:
S t = α ∑ i = 0 t − 1 ( 1 − α ) i X t − i + ( 1 − α ) t S 0 S_{t}=\alpha\sum_{i = 0}^{t - 1}(1 - \alpha)^iX_{t - i}+(1 - \alpha)^tS_{0} St=αi=0∑t−1(1−α)iXt−i+(1−α)tS0

指数的体现及意义

  • 指数形式 :从展开式中能看出,权重 ( 1 − α ) (1 - \alpha) (1−α) 以指数 i i i 的形式出现,也就是 ( 1 − α ) i (1 - \alpha)^i (1−α)i。
  • 意义 :离当前时刻越远的帧(即 i i i 越大),其对应的权重 ( 1 − α ) i (1 - \alpha)^i (1−α)i 就越小,呈指数级衰减。这表明在更新背景模型时,近期的帧对当前背景模型的影响更大,而较早的帧影响则会随着时间推移以指数形式快速减小。这种特性让算法能快速适应背景的变化,同时还能保留一定的历史信息。
相关推荐
天天进步201526 分钟前
Python项目--基于机器学习的股票预测分析系统
开发语言·python·机器学习
山海青风1 小时前
智能体(Intelligent Agents)入门自学教程 3 简单反射型智能体(Reactive Agents)
人工智能·python
独行soc1 小时前
2025年渗透测试面试题总结-拷打题库08(题目+回答)
java·linux·运维·服务器·python·面试·职场和发展
神奇侠20241 小时前
基于 PaddleOCR对pdf文件中的文字提取
python·opencv·paddleocr·pdf文件文本提取
愚公搬代码1 小时前
【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)
开发语言·爬虫·python
绝顶大聪明1 小时前
【绘制图像轮廓|凸包特征检测】图像处理(OpenCV) -part7
图像处理·人工智能·opencv
Niuguangshuo2 小时前
Python设计模式:对象池
开发语言·python·设计模式
卧式纯绿2 小时前
卷积神经网络基础(四)
人工智能·python·深度学习·神经网络·机器学习·cnn
向哆哆2 小时前
Java 性能优化:如何利用 APM 工具提升系统性能?
java·python·性能优化
cdg==吃蛋糕3 小时前
solr自动建议接口简单使用
后端·python·flask