在OpenCV Python中使用背景减法去除视频中的移动物体

822 阅读6分钟

简介

你有没有想过,在电影中,他们是如何从视频帧中移除移动的物体,同时赋予电影特殊的效果。这种效果需要很多东西来实现。然而,你可以在OpenCV Python中通过使用背景减法技术来创造类似的效果,以去除视频中的移动物体。在这篇文章中,我们将通过使用两种方法--i) 运行平均法和ii) 中位数滤波法,并通过几个例子向你展示如何实现这一点。

什么是背景减法?

背景减法是将背景和前景从一连串的图像/视频帧中分离出来的过程。它通常用于检测或去除静态摄像机视频中的移动物体。减法应该。

  1. 考虑到物体的空间尺度,应适应突然和逐渐的变化。
  2. 将像素分类为背景或前景,并对其进行分割。
  3. 适应几何、运动、光照。

Remove moving objects from video in OpenCV Python using Background Subtraction

背景减法

用OpenCV Python去除视频中的移动物体

安装所需的库

如果你的系统中还没有安装OpenCV Python和Numpy库,我们将首先安装它们。在终端运行以下命令。

pip install opencv-python
pip install numpy

导入所需的库

从这里开始,我们将开始写一些代码,所以在你最喜欢的代码编辑器中打开一个Python文件并导入我们所需的库,如下所示。

import cv2
import numpy as np

示例视频

我们将在OpenCV Python中应用我们的背景提取算法,从下图所示的视频中移除移动物体。这里的移动物体是道路上的车辆。

Example Video 1

示例视频1

Example video 2

例子视频2

技术1--运行平均

运行平均的概念是检测活动物体并将其移除,即区分那些似乎随时间变化的像素并将其移除。这里的 "运行 "是指在之前和当前的帧上反复计算平均值,直到帧数用完。简单地说,背景是视频中'n'个先前帧的平均值。

Running average formula

运行平均公式

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)

Remove moving objects from video in OpenCV Python using Background Subtraction - Running Average

应用的运行平均数

Remove moving objects from video in OpenCV Python using Background Subtraction - Running Average

应用的运行平均数

技术2 - 中位数过滤

时间中值滤波是一种背景减除方法,它将每个像素的中值近似为背景。我们可以假设,由于背景在视频中出现的时间最长,所以中位数像素就是背景。因此,我们也可以将这一逻辑应用于帧,并说背景帧等于之前'n'帧的平均值。然而,中值滤波是一个计算量大且耗时的过程,因此其应用受到限制。

Median filtering formula

中位数滤波公式

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)

Remove moving objects from video in OpenCV Python using Background Subtraction - Median Filter

应用中位数滤镜

Remove moving objects from video in OpenCV Python using Background Subtraction - Median Filter

应用中值滤镜

结论

我们的教程展示了我们如何使用OpenCV Python来使用背景减法去除视频中的移动物体。但你可能会看到,这些技术的结果并不总是很好。在深度学习方面有一些突破,这些突破正在帮助研究人员以比以往更高的精度实现物体移除。不过,这将是另一篇文章的主题。

The postRemove Moving Objects from Video in OpenCV Python using Background Subtractionappeared first onMLK - Machine Learning Knowledge.