1. 磐创AI首页
  2. Medium

与OpenCV相结合的运动检测

运动检测是检测对象相对于其周围位置的变化的能力。这在许多应用中可能是一个非常有用的概念,特别是在智能闭路电视摄像机中,它在检测到运动时开始记录。

为了检测摄像机™的视图内是否有任何物体移动,我们可以使用差分图像技术来实现我们的目标。首先,也是最重要的一点,我应该提到,我是从这个博客中了解到这项技术的,在这个博客中,作者使用OpenCV用C#实现了这项技术。this

我要做的是使用相同的技术(以及同一博客中的一些代码)统一实现运动检测。在这里,我们将检测运动并点亮一个红色灯泡(只需更改图像😅的颜色和Alpha值)根据运动的强度。如果您想查看我们的最终结果应用程序,请跳到本文的末尾。

微分图像概念

差分图像概念的思想是,当对象移动时,其位置在两个连续的帧中将不同,但周围环境将保持不变。因此,通过减去这两个帧,我们可以使对象的运动可见。

在这里,我们将使用3个连续的帧来完成此任务,因为使用3个帧的优势是可以消除静止的周围。我也是从我之前提到的同一篇文章中获得这个想法的。参考它可以更好地理解这个概念。post

执行上述步骤后获得的帧将如下所示:

实施

因此,让我们从创建一个统一项目(2D或3D都无关紧要)开始,然后导入™资源来实现统一。

此资产可在以下位置找到:

OpenCV for Unity|集成|Unity Asset StoreOpenCV for Unity | Integration | Unity Asset Store

然后创建一个画布,并在画布中创建三个RawImages,分别将它们命名为CameraView、DetectionView和bulb,然后保存场景。我已经在游戏窗口中将画布大小从自由纵横比改为4:3。

CameraViewâuro“显示原始摄像机视频源

DetectionViewâuro“显示运动检测馈送

用“灯泡欧元”来显示运动的强度

(要创建画布/RawImage:右键单击层次结构部分->UI->Canvas/RawImage)

另外,创建一个空的游戏对象,并将其命名为-uroœScriptHandlerâuro�。(我们可以使用此游戏对象附加脚本,这样会很方便)。

接下来,下载任何图像,并将其导入Unity Assets部分。(我从这里下载了一个剪贴画。)之后,选择灯泡RawImage,在检查器窗口中,您将在Raw Image部分下看到-uroœTexture-uro�。从那里,打开选择窗口并选择刚刚导入的图像的纹理。here

然后,您可以根据需要调整对象的大小和位置。

完成后,您的项目结构应如下所示:

接下来,让-euro™s创建一个名为-euroœ检测-euro�(或任何名称)的C#脚本来开始编码。

(右键单击项目窗口中的Assets部分->Create->C#Script)

让™在Visual Studio中打开C#脚本。

首先添加以下导入。

using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

现在,我们需要创建4个成员变量,如下所示:

[SerializeField] private RawImage cameraView;

在此之后,让-euro™初始化Start方法以显示摄像机提要。

首先,我们需要获取可用的摄像设备,并将?˜CameraView?™RawImage?™的纹理设置为webcamTexture,然后启动网络摄像头提要。

如果您的设备有多个摄像头(例如移动电话),则可以通过更改cam_device[]数组中的值来更改要访问的摄像头。

下面是start()方法:

void Start()

最后一行代码是启动motionDetection()Coroutine方法,我们将在稍后实现该方法。

接下来,我们来创建™方法,该方法将计算三个连续帧之间的差值。我从前面提到的同一个博客中获得了这个方法,并且我修改了代码以适合Unity的OpenCV。the same blog

Mat DiffImage(Mat t0, Mat t1, Mat t2)

我们在这里主要做的是获得帧t1,t0和t2,t1之间像素的绝对差,并将值分别存储在D2和D1 Matsâuro™中。(MAT是用于存储图像值的OpenCV类)。接下来,我们得到D2和D1的逐位与运算。

现在,让-eulomotionDetection()实现™()方法。这是一个处理我们大部分工作的协程方法。此方法包含一个循环,该循环将不会结束地运行,以便将运动检测的摄影机视频源连续渲染到Raw Image视图。

private IEnumerator motionDetection()

从现在开始,将提供的所有代码添加到上述方法(motionDetection()方法)的While循环中。

首先,我们需要创建三个OpenCV Mat来存储3个连续的帧。

当获得一帧又一帧时,我增加了0.04s的延迟,这样我们看到的提要就更逼真了。您可以根据需要更改此值。

我们使用webcamTexture的大小初始化MAT,并使用˜的-EuroOpenCamTextureToMat-euro™方法将像素值加载到MAT。

下面给出的是设置三个垫子的代码。

  Mat t0 = new Mat(webcamTexture.height, webcamTexture.width, CvType.CV_8UC4);
Utils.webCamTextureToMat(webcamTexture, t0); //obtain fram from webcam
yield return new WaitForSeconds(0.04F);// wait for 0.04s
yield return new WaitForEndOfFrame();// wait till end of frame

下一步,我们将把帧转换成灰度,因为我们在检测运动时不需要颜色信息。要执行此操作,请将以下代码添加到motionDetection()方法中。

Imgproc.cvtColor(t0, t0, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(t1, t1, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(t2, t2, Imgproc.COLOR_RGBA2GRAY);

接下来,创建一个新的Mat,并将三个Mat帧传递给我们之前创建的DiffImage()方法,并将结果存储在新的Mat中。

Mat final = new Mat();
final = DiffImage(t0, t1, t2);

在此之后,我们需要创建一个与?EUROU˜Final?EURO™Mat相同大小的新纹理,然后使用OpenCV的?EURO˜matToTexure2D?EURO™方法将Mat的值指定给纹理,并将DetectionView纹理设置为这个新纹理。

Texture2D texture = new Texture2D(final.cols(), final.rows(), TextureFormat.RGBA32, false);

最后,我们需要设置灯泡的颜色。在这里,我使用了一种相当不可靠的方法来更改Alpha和颜色值,但它只是为了给人一个运动的印象,所以我认为它-™™很好。

我在这里所做的是,我已经获得了“EUROURE˜Final”EUROURE™Mat中的非零值的计数。这是因为,在-EUROU˜Final-EURO™Mat中,在没有移动的区域和检测到移动的其他灰度值中,我们将使用全零(黑色)。因此,首先我使用Debug.Log检查通常作为非零值出现的值范围。(当然,要做到这一点,我们需要在unity Editor中配置其他内容,然后再运行这个脚本,我们还没有这样做)。我发现,通常情况下,该计数小于250000(即使没有运动,该值的范围也在80000左右。我想是因为摄像机的噪音)。所以我决定将这个值除以1000,这样我们就可以得到一个介于1和255之间的值,该值可以用作颜色(红色)和Alpha值。

这是做这件事的代码。

Byte value = 0;

在这里,我添加了一个try-catch挡路来捕捉任何溢出(以防Byte值超过255),如果有溢出,我已经将值设置为可能的最大值255。

最终的motionDetection()方法应该如下所示:

private IEnumerator motionDetection()

现在打开unity编辑器,并将Detection.cs脚本作为组件添加到ScriptHandler游戏对象中。然后您将看到它需要3个原始图像。将我们先前创建的RawImages拖放到相关框中。

您的设置应该如下所示:

现在保存场景并在编辑器中运行它。

你应该买这样的东西。

如果您想在此基础上构建Android应用程序,请转到构建设置并将平台切换到Android,根据需要调整画布上对象的大小和位置,然后构建项目以获取apk文件。(您可能还需要从游戏窗口调整画布的大小)。另外,将CameraView和DetectionView的Rotation z值更改为?EUROU˜-90?EURE™,因为出于某些原因,摄像机提要在默认情况下是旋转的。

以下是它在我的安卓手机上是如何工作的–Euro™。

这个项目就到此为止了。请让我知道您的反馈。谢谢!干杯!ğŸ˜欧元

原创文章,作者:fendouai,如若转载,请注明出处:https://panchuang.net/2021/08/04/%e4%b8%8eopencv%e7%9b%b8%e7%bb%93%e5%90%88%e7%9a%84%e8%bf%90%e5%8a%a8%e6%a3%80%e6%b5%8b-2/

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息