文章目录
- 一、简介
- 二、实现方案
- 三、算法实现步骤
- 3.1 取出视频中间帧
- 3.2 帧差法形成运动蒙版:
- 四、代码整体实现
- 五:效果
一、简介
在智能交通系统中,车辆检测是一项重要的技术,而通常情况下一张图片中无用信息过多会带来额外的计算负担,这时我们就可以使用帧差法来对无用信息进行过滤,利用视频序列中的帧间差异来检测运动车辆,排除掉路面以及天空等信息。本文将介绍帧差法的基本原理,并探讨如何利用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()
五:效果
流视频中灰度图片:
生成蒙版图: