简介
你有没有想过,在电影中,他们是如何从视频帧中移除移动的物体,同时赋予电影特殊的效果。这种效果需要很多东西来实现。然而,你可以在OpenCV Python中通过使用背景减法技术来创造类似的效果,以去除视频中的移动物体。在这篇文章中,我们将通过使用两种方法--i) 运行平均法和ii) 中位数滤波法,并通过几个例子向你展示如何实现这一点。
什么是背景减法?
背景减法是将背景和前景从一连串的图像/视频帧中分离出来的过程。它通常用于检测或去除静态摄像机视频中的移动物体。减法应该。
- 考虑到物体的空间尺度,应适应突然和逐渐的变化。
- 将像素分类为背景或前景,并对其进行分割。
- 适应几何、运动、光照。
用OpenCV Python去除视频中的移动物体
安装所需的库
如果你的系统中还没有安装OpenCV Python和Numpy库,我们将首先安装它们。在终端运行以下命令。
pip install opencv-python
pip install numpy
导入所需的库
从这里开始,我们将开始写一些代码,所以在你最喜欢的代码编辑器中打开一个Python文件并导入我们所需的库,如下所示。
import cv2
import numpy as np
示例视频
我们将在OpenCV Python中应用我们的背景提取算法,从下图所示的视频中移除移动物体。这里的移动物体是道路上的车辆。

示例视频1

例子视频2
技术1--运行平均
运行平均的概念是检测活动物体并将其移除,即区分那些似乎随时间变化的像素并将其移除。这里的 "运行 "是指在之前和当前的帧上反复计算平均值,直到帧数用完。简单地说,背景是视频中'n'个先前帧的平均值。
运行平均公式
Python实现
file_path = 'video.mp4'
cap = cv2.VideoCapture(file_path)
first_iter = True
result1 = None
while True:
ret, frame = cap.read()
if frame is None:
break
if first_iter:
avg = np.float32(frame)
first_iter = False
cv2.accumulateWeighted(frame, avg, 0.005)
result1 = cv2.convertScaleAbs(avg)
第1-2行:使用'cv2.VideoCapture'方法初始化一个视频对象。
第3-4行:我们定义一些变量,1)是'first_iter'(值为'True'),它将帮助我们在以后获取视频的第一帧(所以敬请关注!)。2) 'result1'将保存我们的最终结果,所以我们事先初始化它。
第5行。初始化一个while循环,它无限期地运行,或者直到它循环了视频的所有帧(第5行),并且下一帧是'无'。(第7-8行)
第10-11行:对于循环的第一次迭代,'first_iter'的值为真,因此第9行的'if'语句中的代码将被执行。视频的第一帧将被转换为Numpy数组并保存在一个名为'avg'的变量中,'first_iter'将被设置为false。
第14行:我们调用'cv2.accumulateWeighted'函数来计算每次迭代的连续帧的平均值。第一个参数是要计算平均值的图像。第二个参数是目标图像,计算出的平均值将应用于该图像。第三,"alpha "决定更新输入图像权重的速度。(例如。一个较低的值会导致在更多的先前帧上执行运行平均,反之亦然)。)
第15行:顾名思义,这个函数('cv2.convertScaleAbs')计算了每个像素值的绝对值。(具体过程是缩放,计算绝对值,然后转换为uint8类型)。)
result "的值将随着循环的每次迭代而更新,直到所有的帧都被循环完。
结果
在你的python文件中加入以下代码,以显示代码的输出。
cv2.imshow("Running average result", result1) cv2.waitKey(0)
cv2.imshow("Running average result", result1)
cv2.waitKey(0)
应用的运行平均数
应用的运行平均数
技术2 - 中位数过滤
时间中值滤波是一种背景减除方法,它将每个像素的中值近似为背景。我们可以假设,由于背景在视频中出现的时间最长,所以中位数像素就是背景。因此,我们也可以将这一逻辑应用于帧,并说背景帧等于之前'n'帧的平均值。然而,中值滤波是一个计算量大且耗时的过程,因此其应用受到限制。
中位数滤波公式
Python实现
file_path = 'video.mp4'
video = cv2.VideoCapture(file_path)
FOI = video.get(cv2.CAP_PROP_FRAME_COUNT) * np.random.uniform(size=30)
frames = []
for frameOI in FOI:
video.set(cv2.CAP_PROP_POS_FRAMES, frameOI)
ret, frame = video.read()
frames.append(frame)
result2 = np.median(frames, axis=0).astype(dtype=np.uint8)
第1-2行。定义视频的路径,并使用'cv.VideoCapture'将其加载到内存。
第4行。稍后我们将在视频的帧上应用中值函数。不幸的是,这个过程将我们的帧转换为一个一维数组,而不是保持三个维度(宽度、高度、通道)。因此,我们需要用随机值来增加我们的帧,在这一步,我们通过将视频中的帧数(cv2.CAP_PROP_POS_FRAMES获取帧数)乘以一个充满随机值的(30,1)大小的数组来实现。
第6行。定义一个空数组('frames'),在我们循环播放上一步创建的视频帧后,它将保存这些视频帧。
第7-8行:初始化一个 "for "循环,以循环浏览在第4行创建的修改后的帧。在for循环里面,我们使用'set()'函数(在'VideoCapture'对象上调用)访问我们原始视频的当前帧(cv2.CAP_PROP_POS_FRAMES指的是接下来要解码/捕获的帧的0基索引)属性,并将其改为相应的修改帧(即'frameOI')。然后获取该帧并将其追加到我们的'frames'数组中。
第12行:调用numpy的'median'函数来计算帧数组的中位数。因为我们要计算中位数,所以这个函数会返回一个恰好位于数组中间的单一图像(因为是'uint8'类型)。(pixel-wise middle)
结果
为了看到计算出的背景图像,在代码的末尾添加以下代码。
cv2.imshow("Median filtering result",result2)
cv2.waitKey(0)
应用中位数滤镜
应用中值滤镜
- 同时阅读 - YOLOv5物体检测教程
- 还可以阅读 - YOLOv4物体检测教程与图片和视频。初学者指南
结论
我们的教程展示了我们如何使用OpenCV Python来使用背景减法去除视频中的移动物体。但你可能会看到,这些技术的结果并不总是很好。在深度学习方面有一些突破,这些突破正在帮助研究人员以比以往更高的精度实现物体移除。不过,这将是另一篇文章的主题。
The postRemove Moving Objects from Video in OpenCV Python using Background Subtractionappeared first onMLK - Machine Learning Knowledge.