如何使用OpenCV和Python构建人员计数器


这篇文章主要介绍了如何使用OpenCV和Python构建人员计数器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用OpenCV和Python构建人员计数器文章都会有所收获,下面我们一起来看看吧。在继续本教程的其余部分之前,您必须了解对象检测和对象跟踪之间的根本区别。当我们应用对象检测时,我们是在确定一个对象在图像/帧中的位置。与目标跟踪算法相比,目标检测器通常在计算上更昂贵,因此也更慢。目标检测算法的例子包括Haar级联、HOG +线性支持向量机(HOG + Linear SVM)和基于深度学习的目标检测器,如Faster R-CNN、YOLO和Single Shot检测器(SSD)。另一方面,对象跟踪器将接受对象在图像中位置的输入 (x, y) 坐标,并将:1.为该特定对象分配唯一 ID2.在对象围绕视频流移动时跟踪对象,根据帧的各种属性(梯度、光流等)预测下一帧中的新对象位置对象跟踪算法的示例包括 MedianFlow、MOSSE、GOTURN、核化相关滤波器和判别相关滤波器等。高精度目标跟踪器将目标检测和目标跟踪的概念结合到一个算法中,通常分为两个阶段:1.阶段1 检测:在检测阶段,我们正在运行计算成本更高的对象跟踪器,以 (1) 检测是否有新对象进入我们的视野,以及 (2) 看看我们是否可以找到在跟踪阶段“丢失”的对象。对于每个检测到的对象,我们使用新的边界框坐标创建或更新对象跟踪器。由于我们的目标检测器的计算成本更高,我们每 N 帧只运行一次此阶段。2.阶段2 跟踪:当我们不处于“检测”阶段时,我们处于“跟踪”阶段。对于我们检测到的每个对象,我们创建一个对象跟踪器来跟踪对象在框架周围的移动。我们的目标跟踪器应该比目标检测器更快、更高效。我们将继续跟踪,直到我们到达第 N 帧,然后重新运行我们的目标检测器。然后重复整个过程。这种混合方法的好处是我们可以应用高度准确的对象检测方法,而无需太多的计算负担。我们将实施这样一个跟踪系统来建立我们的人员计数器。让我们回顾一下今天博客文章的项目结构。获取代码后,您可以使用 tree 命令检查目录结构:最重要的两个目录:1.pyimagesearch/:该模块包含质心跟踪算法。 “组合对象跟踪算法”部分介绍了质心跟踪算法。2.mobilenet_ssd/:包含 Caffe 深度学习模型文件。今天项目的核心包含在 people_counter.py 脚本中——这是我们将花费大部分时间的地方。今天我们还将回顾 trackableobject.py 脚本。为了实现我们的人员计数器,我们将同时使用 OpenCV 和 dlib。我们将 OpenCV 用于标准的计算机视觉/图像处理功能,以及用于人数统计的深度学习对象检测器。然后我们将使用 dlib 来实现相关过滤器。我们也可以在这里使用 OpenCV;但是,对于这个项目,dlib 对象跟踪实现更容易使用。除了 dlib 的对象跟踪实现,我们还将使用质心跟踪实现。回顾整个质心跟踪算法超出了这篇博文的范围,但我在下面提供了一个简短的概述。在步骤#1,我们接受一组边界框并计算它们对应的质心(即边界框的中心):要使用 Python 通过质心脚本构建简单的对象跟踪,第一步是接受边界框坐标并使用它们来计算质心。边界框本身可以由以下任一方式提供:1.目标检测器(如免费云主机域名 HOG + Linear SVM、Faster R-CNN、SSDs 等)2.或对象跟踪器(例如相关过滤器)在上图中,您可以看到我们在算法的初始迭代中有两个对象要跟踪。在步骤#2中,我们计算任何新质心(黄色)和现有质心(紫色)之间的欧几里得距离:此图像中存在三个对象。我们需要计算每对原始质心(紫色)和新质心(黄色)之间的欧几里得距离。质心跟踪算法假设它们之间具有最小欧几里德距离的质心对必须是相同的对象 ID。在上面的示例图像中,我们有两个现有的质心(紫色)和三个新的质心(黄色),这意味着已经检测到一个新对象(因为与旧质心相比,还有一个新质心)。然后箭头表示计算所有紫色质心和所有黄色质心之间的欧几里得距离。一旦我们有了欧几里得距离,我们就会在步骤#3 中尝试关联对象 ID:您可以看到我们的质心跟踪器已选择关联使它们各自的欧几里得距离最小化的质心。但是左下角的点呢?它没有与任何东西相关联——我们该怎么办? 要回答这个问题,我们需要执行步骤#4,注册新对象:注册意味着我们通过以下方式将新对象添加到我们的跟踪对象列表中:1.为其分配一个新的对象 ID2.存储新对象的边界框坐标的质心如果对象丢失或离开视野,我们可以简单地取消注册对象(步骤#5)。为了跟踪和计算视频流中的对象,我们需要一种简单的方法来存储有关对象本身的信息,包括:对象ID以前的质心(所以我们可以很容易地计算出物体移动的方向)对象是否已被计数为了实现所有这些目标,我们可以定义一个 TrackableObject 实例——打开 trackableobject.py 文件并插入以下代码:TrackableObject 构造函数接受 objectID + centroid 并存储它们。 centroids 变量是一个列表,因为它将包含对象的质心位置历史记录。 构造函数还将 counted 初始化为 False ,表示该对象还没有被计数。我们首先导入必要的包:从 pyimagesearch 模块,我们导入自定义的 CentroidTracker 和 TrackableObject 类。imutils.video 中的 VideoStream 和 FPS 模块将帮助我们使用网络摄像头并计算估计的每秒帧数 (FPS) 吞吐率。我们需要 imutils 的 OpenCV 便利功能。dlib 库将用于其相关跟踪器实现。OpenCV 将用于深度神经网络推理、打开视频文件、写入视频文件以及在我们的屏幕上显示输出帧。现在所有工具都触手可及,让我们解析命令行参数:我们有六个命令行参数,它们允许我们在运行时从终端将信息传递给我们的人员计数器脚本:–prototxt :Caffe 部署 prototxt 文件的路径。–model :Caffe 预训练 CNN 模型的路径。–input : 可选的输入视频文件路径。如果未指定路径,将使用您的网络摄像头。–output :可选的输出视频路径。如果未指定路径,则不会录制视频。–confidence :默认值为 0.4 ,这是有助于过滤掉弱检测的最小概率阈值。–skip-frames :在跟踪对象上再次运行我们的 DNN 检测器之前要跳过的帧数。请记住,对象检测的计算成本很高,但它确实有助于我们的跟踪器重新评估帧中的对象。默认情况下,我们在使用 OpenCV DNN 模块和我们的 CNN 单次检测器模型检测对象之间跳过 30 帧。现在我们的脚本可以在运行时动态处理命令行参数,让我们准备我们的 SSD:首先,我们将初始化 CLASSES——SSD 支持的类列表。我们只对“人”类感兴趣,但您也可以计算其他移动对象。我们加载用于检测对象的预训练 MobileNet SSD(但同样,我们只对检测和跟踪人感兴趣,而不是任何其他类)。我们可以初始化我们的视频流:首先,我们处理使用网络摄像头视频流的情况。否则,我们将从视频文件中捕获帧。在开始循环帧之前,我们还有一些初始化要执行:其余的初始化包括:writer:我们的视频写入器。如果我们正在写入视频,我们稍后会实例化这个对象。W 和 H:我们的帧尺寸。我们需要将这些插入到 cv2.VideoWriter 中。ct:我们的 CentroidTracker。trackers :存储 dlib 相关跟踪器的列表。trackableObjects :将 objectID 映射到 TrackableObject 的字典。totalFrames :处理的帧总数。totalDown 和 totalUp :向下或向上移动的对象/人的总数。fps :我们用于基准测试的每秒帧数估计器。现在我们所有的初始化都处理好了,让我们循环传入的帧:我们开始循环。在循环的顶部,我们抓取下一帧。如果我们已经到达视频的结尾,我们将跳出循环。帧进行预处理。这包括调整大小和交换颜色通道,因为 dlib 需要 rgb 图像。我们为视频编写器获取帧的尺寸。 如果通过命令行参数提供了输出路径,我们将从那里实例化视频编写器。现在让我们使用 SSD检测人:我们将状态初始化为Waiting。可能的状态包括:Waiting:在这种状态下,我们正在等待检测和跟踪人员。Detecting:我们正在使用 MobileNet SSD 检测人员。Tracking:人们在帧中被跟踪,我们正在计算 totalUp 和 totalDown 。我们的 rects 列表将通过检测或跟踪来填充。我们继续初始化rects 。重要的是要了解深度学习对象检测器的计算成本非常高,尤其是当您在 CPU 上运行它们时。为了避免在每一帧上运行我们的目标检测器,并加快我们的跟踪管道,我们将跳过 N 帧(由命令行参数设置 –skip-frames ,其中 30 是默认值)。只有每 N 帧,我们才会使用 SSD 进行对象检测。否则,我们将只是跟踪中间的移动对象。使用模运算符,我们确保每 N 帧执行一次 if 语句中的代码。 进入if语句后,我们会将状态更新为Detecting。 然后我们初始化新的跟踪器列表。接下来,我们将通过对象检测进行推理。我们首先从图像中创建一个 blob,然后将该 blob 通过网络传递以获得检测。 现在我们将遍历每个检测,希望找到属于person类的对象:循环检测,我们继续获取置信度并过滤掉那些不属于人类的结果。现在我们可以为每个人计算一个边界框并开始相关性跟踪:计算我们的box。 然后实例化我们的 dlib 相关跟踪器,然后将对象的边界框坐标传递给 dlib.rectangle,将结果存储为 rect。 随后,我们开始跟踪,并将跟踪器附加到跟踪器列表中。 这是我们每 N 个跳帧执行的所有操作的封装! 让我们处理在 else 块中进行跟踪的典型操作:大多数时候,并没有发生在跳帧倍数上。在此期间,我们将利用跟踪器来跟踪对象,而不是应用检测。 我们开始遍历可用跟踪器。 我们继续将状态更新为Tracking并获取对象位置。 我们提取位置坐标,然后在我们的 rects 列表中填充信息。 现在让我们画一条水平可视化线(人们必须穿过它才能被跟踪)并使用质心跟踪器来更新我们的对象质心:我们画一条水平线,我们将用它来可视化人们“越过”——一旦人们越过这条线,我们将增加各自的计数器 然后,我们利用 CentroidTracker 实例化来接受 rects 列/p>

相关推荐: ASP.NET MVC中自定义一个HtmlHelper方法

这篇文章主要为大家展示了“ASP.NETMVC中自定义一个HtmlHelper方法”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ASP.NETMVC中自定义一个HtmlHelper方法”这篇文章吧。以Label()…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/10 12:41
下一篇 01/10 12:42

相关推荐