热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python教程分享基于OpenCV目标跟踪实现人员计数器

在本教程中,您将学习如何使用opencv和python构建人员计数器。使用opencv,我们将实时计算进或出百货商店的人数。在今天博客文章的第一部分,我们将讨论如何利用两者来创建更

在本教程中,您将学习如何使用 opencv 和 python 构建人员计数器。使用 opencv,我们将实时计算进或出百货商店的人数。

在今天博客文章的第一部分,我们将讨论如何利用两者来创建更准确的人员计数器。之后,我们将查看项目的目录结构,然后实施整个人员计数项目。最后,我们将检查将 opencv 的人数统计应用到实际视频中的结果。

1.了解对象检测与对象跟踪

在继续本教程的其余部分之前,您必须了解对象检测和对象跟踪之间的根本区别。

当我们应用对象检测时,我们是在确定一个对象在图像/帧中的位置。与目标跟踪算法相比,目标检测器通常在计算上更昂贵,因此也更慢。目标检测算法的例子包括haar级联、hog +线性支持向量机(hog + linear svm)和基于深度学习的目标检测器,如faster r-cnn、yolo和single shot检测器(ssd)。

另一方面,对象跟踪器将接受对象在图像中位置的输入 (x, y) 坐标,并将:

1.为该特定对象分配唯一 id

2.在对象围绕视频流移动时跟踪对象,根据帧的各种属性(梯度、光流等)预测下一帧中的新对象位置

对象跟踪算法的示例包括 medianflow、mosse、goturn、核化相关滤波器和判别相关滤波器等。

2.结合对象检测和对象跟踪

高精度目标跟踪器将目标检测和目标跟踪的概念结合到一个算法中,通常分为两个阶段:

1.阶段1 检测:在检测阶段,我们正在运行计算成本更高的对象跟踪器,以 (1) 检测是否有新对象进入我们的视野,以及 (2) 看看我们是否可以找到在跟踪阶段“丢失”的对象。对于每个检测到的对象,我们使用新的边界框坐标创建或更新对象跟踪器。由于我们的目标检测器的计算成本更高,我们每 n 帧只运行一次此阶段。

2.阶段2 跟踪:当我们不处于“检测”阶段时,我们处于“跟踪”阶段。对于我们检测到的每个对象,我们创建一个对象跟踪器来跟踪对象在框架周围的移动。我们的目标跟踪器应该比目标检测器更快、更高效。我们将继续跟踪,直到我们到达第 n 帧,然后重新运行我们的目标检测器。然后重复整个过程。

这种混合方法的好处是我们可以应用高度准确的对象检测方法,而无需太多的计算负担。我们将实施这样一个跟踪系统来建立我们的人员计数器。

3.项目结构

让我们回顾一下今天博客文章的项目结构。获取代码后,您可以使用 tree 命令检查目录结构:

基于OpenCV目标跟踪实现人员计数器

最重要的两个目录:

1.pyimagesearch/:该模块包含质心跟踪算法。 “组合对象跟踪算法”部分介绍了质心跟踪算法。

2.mobilenet_ssd/:包含 caffe 深度学习模型文件。

今天项目的核心包含在 people_counter.py 脚本中——这是我们将花费大部分时间的地方。今天我们还将回顾 trackableobject.py 脚本。

4.结合对象跟踪算法

为了实现我们的人员计数器,我们将同时使用 opencv 和 dlib。我们将 opencv 用于标准的计算机视觉/图像处理功能,以及用于人数统计的深度学习对象检测器。

然后我们将使用 dlib 来实现相关过滤器。我们也可以在这里使用 opencv;但是,对于这个项目,dlib 对象跟踪实现更容易使用。

除了 dlib 的对象跟踪实现,我们还将使用质心跟踪实现。回顾整个质心跟踪算法超出了这篇博文的范围,但我在下面提供了一个简短的概述。

在步骤#1,我们接受一组边界框并计算它们对应的质心(即边界框的中心):

基于OpenCV目标跟踪实现人员计数器

要使用 python 通过质心脚本构建简单的对象跟踪,第一步是接受边界框坐标并使用它们来计算质心。

边界框本身可以由以下任一方式提供:

1.目标检测器(如 hog + linear svm、faster r-cnn、ssds 等)

2.或对象跟踪器(例如相关过滤器)

在上图中,您可以看到我们在算法的初始迭代中有两个对象要跟踪。

在步骤#2中,我们计算任何新质心(黄色)和现有质心(紫色)之间的欧几里得距离:

基于OpenCV目标跟踪实现人员计数器

此图像中存在三个对象。我们需要计算每对原始质心(紫色)和新质心(黄色)之间的欧几里得距离。

质心跟踪算法假设它们之间具有最小欧几里德距离的质心对必须是相同的对象 id。

在上面的示例图像中,我们有两个现有的质心(紫色)和三个新的质心(黄色),这意味着已经检测到一个新对象(因为与旧质心相比,还有一个新质心)。

然后箭头表示计算所有紫色质心和所有黄色质心之间的欧几里得距离。一旦我们有了欧几里得距离,我们就会在步骤#3 中尝试关联对象 id:

基于OpenCV目标跟踪实现人员计数器

您可以看到我们的质心跟踪器已选择关联使它们各自的欧几里得距离最小化的质心。但是左下角的点呢?它没有与任何东西相关联——我们该怎么办? 要回答这个问题,我们需要执行步骤#4,注册新对象:

基于OpenCV目标跟踪实现人员计数器

注册意味着我们通过以下方式将新对象添加到我们的跟踪对象列表中:

1.为其分配一个新的对象 id

2.存储新对象的边界框坐标的质心

如果对象丢失或离开视野,我们可以简单地取消注册对象(步骤#5)。

5.创建可追踪对象

为了跟踪和计算视频流中的对象,我们需要一种简单的方法来存储有关对象本身的信息,包括:

  • 对象id
  • 以前的质心(所以我们可以很容易地计算出物体移动的方向)
  • 对象是否已被计数

为了实现所有这些目标,我们可以定义一个 trackableobject 实例——打开 trackableobject.py 文件并插入以下代码:

trackableobject 构造函数接受 objectid + centroid 并存储它们。 centroids 变量是一个列表,因为它将包含对象的质心位置历史记录。 构造函数还将 counted 初始化为 false ,表示该对象还没有被计数。

6.使用 opencv + python 实现我们的人员计数器

我们首先导入必要的包:

  • 从 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 列表,无论它们是通过对象检测还是对象跟踪生成的。我们的质心跟踪器会将对象 id 与对象位置相关联。 在下一个代码块中,我们将回顾一个人在帧中向上或向下移动的逻辑:

我们首先遍历更新后的对象id的边界框坐标。我们尝试为当前的objectid获取trackableobject。如果objectid的trackableobject不存在,我们就创建一个。否则,已经存在一个 trackableobject ,所以我们需要弄清楚对象(人)是向上还是向下移动。

为此,我们获取给定对象之前所有质心位置的y坐标值。然后,通过取当前质心位置与之前所有质心位置的平均值之间的差来计算方向。

我们取均值的原因是为了确保我们的方向跟踪更稳定。如果我们只存储这个人之前的质心位置,我们就有可能出现错误的方向计数。记住,目标检测和目标跟踪算法不是“魔术”——有时它们会预测出可能稍微偏离你预期的边界盒;因此,通过取均值,我们可以让我们的人计算得更准确。

如果trackableobject还没有被计数,我们需要确定它是否已经准备好被计数,通过:

1.检查direction是否为负(表示对象向上移动)并且质心在中心线上方。在这种情况下,我们增加 totalup。

2.或者检查direction是否为正(表示物体正在向下移动)且质心在中心线以下。如果这是真的,我们增加totaldown。

最后,我们将trackableobject存储在trackableobjects字典中,这样我们就可以在捕获下一帧时获取并更新它。

接下来的三个代码块处理:

  • 显示(绘图并向帧写入文本)
  • 将帧写入磁盘上的视频文件(如果存在–output命令行参数)
  • 捕获按键
  • 清理

首先,我们将在框架上绘制一些信息以进行可视化:

在这里,我们在帧上覆盖以下数据:

  • objectid :每个对象的id。
  • centroid :对象的中心将由一个点表示,该点是通过填充一个圆圈而创建的。
  • info : 包括 totalup 、 totaldown 和 status

然后我们将把帧写入视频文件(如果需要的话)并处理按键:

在这个代码块中我们:

  • 如果需要,将帧写入输出视频文件
  • 显示帧并处理按键。如果q被按下,我们将跳出帧处理循环。
  • 更新我们的fps计数器

现在是时候清理了:

为了完成脚本,我们向终端显示 fps 信息,释放所有指针,并关闭所有打开的窗口。

7.完整代码

people_counter.py

centroidtracker.py

(1)质心跟踪器是最可靠的跟踪器之一。

(2)为了简单起见,质心跟踪器计算包围框的质心。

(3)也就是说,边界框是图像中对象的(x, y)坐标。

(4)一旦我们的ssd获得了坐标,跟踪器就会计算包围框的质心(中心)。换句话说,就是物体的中心。

(5)然后为每一个被检测到的特定对象分配一个唯一的id,用于跟踪帧序列。

trackableobject.py

8.运行结果

打开终端,执行以下命令:

我们的人员计数正在计算以下人数:

  • 正进入百货商店(下)
  • 离开的人数(上)

在第一个视频的最后,你会看到有7个人进入,3个人离开。

此外,检查终端输出,你会发现我们的人计数器能够实时运行,达到34帧每秒。尽管我们正在使用深度学习对象检测器来更准确地检测人。

我们的 34 fps 帧率是通过我们的两个阶段过程实现的: 每 30 帧检测一次人 然后在其间的所有帧中应用更快、更有效的对象跟踪算法。

9.改进我们的人员计数器应用程序

为了构建我们的 opencv 人员计数器,我们使用了 dlib 的相关性跟踪器。此方法易于使用,并且只需要很少的代码。

然而,我们的实现有点低效——为了跟踪多个对象,我们需要创建关联跟踪器对象的多个实例。然后当我们需要在后续帧中计算对象的位置时,我们需要遍历所有 n 个对象跟踪器并获取更新的位置。

所有这些计算都将发生在我们脚本的主执行线程中,从而降低了我们的 fps 速率。

因此,提高性能的一种简单方法是使用dlib的多对象跟踪器,以使我们的 fps 速率提高 45%! 注意:opencv 也实现了多对象跟踪,但不是多进程(至少在撰写python教程分享基于OpenCV目标跟踪实现人员计数器时)。 opencv 的多对象方法当然更容易使用,但如果没有多处理能力,在这种情况下它并没有多大帮助。

最后,为了获得更高的跟踪精度(但在没有快速 gpu 的情况下会牺牲速度),您可以研究基于深度学习的对象跟踪器,例如 deep sort。

bonus

前几天在github上看见一个改进版:

主要目标是将项目用作业务视角,随时可以扩展。

用例:实时统计商店/大楼/购物中心等的人数。

如果人数超过上限就会向工作人员发出警报。

自动化特性并优化实时流以获得更好的性能(使用线程)。

作为一项措施,以进行足迹分析,并在某种程度上应对covid-19。

到此这篇关于基于opencv目标跟踪实现人员计数器的文章就介绍到这了,更多相关opencv人员计数内容请搜索<编程笔记>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<编程笔记>!

需要了解更多python教程分享基于OpenCV目标跟踪实现人员计数器,都可以关注python教程分享栏目&#8212;编程笔记


推荐阅读
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
author-avatar
婧氏橙奂
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有