OpenCV 运动检测

Salman Mehmood 2022年6月7日
OpenCV 运动检测

在本文中,我们将学习如何在 OpenCV 和 Python 的帮助下创建运动检测项目。

使用 OpenCV 和 Python 创建运动检测项目

首先说一下这个项目的需求。显然,第一个要求是安装 Python,我们还需要安装一个名为 opencv 的外部包。

我们需要打开命令提示符并运行此命令以在你的 PC 上安装此软件包。让我们跳到我们的编辑器并开始编写我们的代码。

我们将导入的第一件事是我们需要的库,cv2time,接下来我们将使用 OpenCV 的 VideoCapture() 方法从我们的网络摄像头获取数据。

让我们创建一个名为 Video 的对象,我们必须将 0 传递给 VideoCapture(),因为我们正在为网络摄像头使用 0 通道。

import cv2,time

Video=cv2.VideoCapture(0)
First_Frame=None

现在我们将创建一个 while True 循环或无限循环,因为我们将提取视频,而视频是图像幻灯片上的连续移动。

现在我们将在 while 循环中定义几条指令,在第一行中,我们将创建两个变量 Checkframe,并读取 VideoCapture() 方法提取的数据。在下一条指令中,我们将把这个提取的图像转换成灰度图。

但是为什么我们要把它转换成灰度呢?我们这样做是因为我们想提高特征检测的准确性。

我们使用 cvtColor() 方法来改变灰度并且有两个参数。首先是或我们要转换为灰度的图像,然后是 COLOR_BGR2GRAY,它将图像转换为灰度。

现在我们将使图像模糊或平滑,这就是为什么物体检测或物体运动会容易得多的原因。我们使用 GaussianBlur() 方法来应用平滑并将灰度图像、内核大小和 sigma 传递给它。

while True:
    Check,frame=Video.read()
    gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    gray=cv2.GaussianBlur(gray,(21,21),0)

我们将创建一个 if 语句来检查帧是否到来,我们这样做是因为我们希望 First_Frame 作为我们的参考帧。

让我们来看看物理学对运动的看法?运动是从一个参考点识别出来的,我们用一个例子来解释这一点。

假设你坐在火车上,对你来说,树木在移动,但它们并没有移动;它们仍然是,但你正在从你的参考点移动。在这种情况下,树是参考点,但在我们的例子中,框架是参考。

我们将 First_Frame 固定为我们的参考框架;如果参考系发生任何变化,那么我们可以说运动存在。

现在我们将设置一个语句,如果 First_Frame 变量为 None(在第一种情况下为 true),那么我们将使 First_Frame 变量等于作为 gray 变量的灰度图像。

if First_Frame is None:
	First_Frame=gray
		continue

我们将使用 absdiff() 方法来查找帧之间的差异。让我们创建一个增量帧变量并将两个参数传递给 absdiff() 方法进行比较。

我们需要设置一个阈值或限制,我们希望检测到运动,因为我们不希望噪声被检测为运动。

为此,我们使用 threshold() 方法,它有几个参数,第一个是 delta_frame,第二个是强度,第三个是颜色阴影,在这种情况下是白色,然后是下一个是 THRESH_BINARY,因为它是一个元组,所以我们需要选择第一个元素。

我们还需要在下一条指令中再应用一个平滑层。为此,我们需要使用另一个称为 dilate() 的平滑函数,它接受三个参数,第一个是 threshold,第二个是 None,第三个参数是 iterations

iterations 参数定义了平滑的精确度;如果你增加此参数值,你的程序也会捕获噪声。

这次我们将创建轮廓,那么轮廓是什么?轮廓是运动发生的点。

如果框架静止并且手在移动,那么手的部分就是轮廓。

findContours() 方法有助于查找轮廓,它接受三个参数,第一个是帧,我们使用 copy() 方法创建帧数组的副本。

delta_frame=cv2.absdiff(First_Frame,gray)
    Threshold_frame=cv2.threshold(delta_frame,50,255,cv2.THRESH_BINARY)[1]
    Threshold_frame=cv2.dilate(Threshold_frame,None,iterations=2)
    (cntr,_)=cv2.findContours(Threshold_frame.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

现在我们将通过迭代获得轮廓并将近似区域定义为运动。如果我们不定义区域,我们将得到一个非常嘈杂的运动检测。

首先我们会检查,如果轮廓区域小于一千,那么我们不认为这是一个运动区域,我们会继续迭代,如果大于一千,那么我们就画一个三角形。

for contour in cntr:
	if cv2.contourArea(contour)<1000:
		continue

findContours() 方法给出了四个值(x、y、高度、宽度),我们将使用 boundingRect() 方法提取这些点,该方法将绑定矩形的区域。现在我们将在 rectangle() 方法的帮助下创建矩形。

第一个参数是我们要在其上绘制矩形的 frame 或图像。接下来是 (x,y) 坐标点,接下来是高度和宽度,接下来是边框的颜色,最后一个参数是选择画矩形的笔的大小。

(x,y,w,h)=cv2.boundingRect(contour)
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),3)

完整的源代码:

import cv2,time

Video=cv2.VideoCapture(0)
First_Frame=None

while True:
    Check,frame=Video.read()
    gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    gray=cv2.GaussianBlur(gray,(21,21),0)
    if First_Frame is None:
        First_Frame=gray
        continue
    delta_frame=cv2.absdiff(First_Frame,gray)
    Threshold_frame=cv2.threshold(delta_frame,50,255,cv2.THRESH_BINARY)[1]
    Threshold_frame=cv2.dilate(Threshold_frame,None,iterations=2)
    (cntr,_)=cv2.findContours(Threshold_frame.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    for contour in cntr:
        if cv2.contourArea(contour)<1000:
            continue
        (x,y,w,h)=cv2.boundingRect(contour)
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),3)
    cv2.imshow('Frame',frame)
    Key=cv2.waitKey(1)
    if Key == ord('q'):
        break

Video.release()
cv2.destroyAllWindows()

现在我们可以看到运动检测发生在手移动时。

使用 OpenCV 和 Python 创建运动检测项目

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

相关文章 - OpenCV Video