opencv-python实战项目七:帧差法获取运动车辆蒙版


一、简介

在智能交通系统中,车辆检测是一项重要的技术,而通常情况下一张图片中无用信息过多会带来额外的计算负担,这时我们就可以使用帧差法来对无用信息进行过滤,利用视频序列中的帧间差异来检测运动车辆,排除掉路面以及天空等信息。本文将介绍帧差法的基本原理,并探讨如何利用OpenCV库实现帧差法获取运动车辆蒙版的过程。

二、实现方案

本方法通过处理视频帧,提取运动车辆的关键信息。首先,我们将视频帧转换为灰度图,以减少数据量并提高后续处理的效率。接着,我们从视频中取出中间的视频帧作为参考帧,即中位帧。然后,我们将视频中的每帧与中位帧相减,以计算出每帧与中位帧之间的差异,这些差异反映了车辆在视频中的运动情况。最后,我们对计算出的图像差异进行二值化处理,以突出显示运动车辆。通过设定合适的阈值,我们可以将差异图转换为黑白蒙版,其中白色区域表示运动车辆,黑色区域表示静止背景。通过以上步骤,我们利用帧差法获取运动车辆蒙版,并在实际应用中进行车辆检测。

三、算法实现步骤

3.1 取出视频中间帧

我们首先获取视频的总帧数。接着,我们创建一个包含25个帧索引的数组,这些索引按照时间轴顺序排列,从0到视频总帧数减1。然后,我们遍历这些帧索引,将视频流的当前位置设置到对应的帧索引,读取帧,并检查是否成功读取。如果成功,我们将帧添加到列表中。完成帧的读取和添加后,我们释放视频捕捉对象,释放资源。最后,我们计算所有帧的中值帧,作为视频的背景参考。
实现代码:

# 打开视频文件
cap = cv2.VideoCapture(r'F:\learnopencv-master\VideoBackgroundEstimation/video.mp4')
# 获取视频的总帧数
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 生成一个按照时间轴顺序排列的帧索引数组
frameIds = np.linspace(0, total_frames-1, num=25, dtype=np.int32)
# 存储选中的帧
frames = []
# 遍历帧索引,并按照顺序存储帧
for fid in frameIds:
    cap.set(cv2.CAP_PROP_POS_FRAMES, fid)
    ret, frame = cap.read()
    if ret:
        frames.append(frame)
# 释放视频捕捉对象
# 计算中值帧
medianFrame = np.median(frames, axis=0).astype(dtype=np.uint8)

3.2 帧差法形成运动蒙版:

帧差法依赖于这样一个事实:在连续的视频帧中,静态背景在短时间内保持不变,而运动对象则会在这段时间内改变其在图像中的位置。因此,通过计算连续两帧或几帧图像之间的差异,可以检测出这些变化,从而识别出运动对象。
我们首先将计算得到的中值帧从BGR颜色空间转换为灰度图,以便后续处理。接着,我们进入一个循环,该循环会持续读取视频中的每一帧,直到视频结束。在循环中,我们首先读取当前帧,并将其从BGR颜色空间转换为灰度图。然后,我们计算当前帧与灰度中值帧的绝对差值,这个差值反映了当前帧与视频背景之间的差异。接下来,我们对差值图进行阈值处理,将差值图转换为二值图像,其中高于阈值的部分保持为白色,低于阈值的部分变为黑色。通过这个循环,我们可以实时地处理视频中的每一帧,计算出与背景的差异,并生成运动车辆的蒙版。
实现方法:

grayMedianFrame = cv2.cvtColor(medianFrame, cv2.COLOR_BGR2GRAY)

# 遍历所有帧
ret = True
while(ret):

  # 读取当前帧
  ret, frame = cap.read()
  # 将当前帧转换为灰度图
  frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  # 计算当前帧与中值帧的绝对差值
  dframe = cv2.absdiff(frame, grayMedianFrame)
  # 进行阈值处理,将差值图二值化
  th, dframe = cv2.threshold(dframe, 30, 255, cv2.THRESH_BINARY)

四、代码整体实现

import numpy as np
import cv2


# 打开视频文件
cap = cv2.VideoCapture(r'F:\learnopencv-master\VideoBackgroundEstimation/video.mp4')
# 获取视频的总帧数
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 生成一个按照时间轴顺序排列的帧索引数组
frameIds = np.linspace(0, total_frames-1, num=25, dtype=np.int32)
# 存储选中的帧
frames = []

# 遍历帧索引,并按照顺序存储帧
for fid in frameIds:
    cap.set(cv2.CAP_PROP_POS_FRAMES, fid)
    ret, frame = cap.read()
    if ret:
        frames.append(frame)

# 释放视频捕捉对象

# 计算中值帧
medianFrame = np.median(frames, axis=0).astype(dtype=np.uint8)

# 将中值帧的背景重置为0
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

# 将中值帧转换为灰度图
grayMedianFrame = cv2.cvtColor(medianFrame, cv2.COLOR_BGR2GRAY)

# 遍历所有帧
ret = True
while(ret):

  # 读取当前帧
  ret, frame = cap.read()
  # 将当前帧转换为灰度图
  frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  # 计算当前帧与中值帧的绝对差值
  dframe = cv2.absdiff(frame, grayMedianFrame)
  # 进行阈值处理,将差值图二值化
  th, dframe = cv2.threshold(dframe, 30, 255, cv2.THRESH_BINARY)
  # 显示差值图
  cv2.imshow('dframe', dframe)
  # 等待10毫秒
  cv2.waitKey(10)

# 释放视频对象
cap.release()

# 销毁所有窗口
cv2.destroyAllWindows()

五:效果

流视频中灰度图片:
在这里插入图片描述
生成蒙版图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值