基于YOLOv5的视频计数 — 汽车计数实现

在视频中计数对象可能看起来有挑战性,但借助Python和OpenCV的强大功能,变得令人意外地易于实现。在本文中,我们将探讨如何使用YOLO(You Only Look Once)目标检测模型在视频流或文件中计数对象。我们将该过程分解为简单的步骤,使初学者能够轻松跟随。

本文将分为以下几个部分:

  • 需求

  • 启发式:汽车计数

  • 检测过滤

  • 启发式:实现

  • 结论

需求

在我们深入了解该过程之前,让我们确保已安装所需的库。主要需要:

  • PyTorch:通过PyTorch Hub,我们将访问Ultralytics存储库以下载Yolov5模型。

  • OpenCV:用于加载、操作和显示视频的所有实用程序。

  • Matplotlib(可选):我们将使用此实用程序在多边形内进行点验证。

如代码片段1所示,requirements.txt文件中列出了这些要求。

opencv-python==4.8.1.78
torch==2.1.0
matplotlib==3.8.0
ultralytics==8.0.203
pandas==2.1.2
requests==2.31.0

一旦我们查看了主要要求,就该了解我们将开发用于从视频中计数对象的启发式的时间了。

启发式:汽车计数

在此示例中,我们将使用一个视频场景,其中将对汽车进行计数。图2显示了一个示例帧。

f8379ebc1b86d5af155fa36b51a8fa3c.jpeg用于计数汽车的视频帧

为了计数汽车,我们将使用Yolov5来检测视频中的对象。基于检测到的对象,我们将过滤与汽车、公共汽车和卡车有关的类别。由于检测基于边界框(具有坐标xmin、ymin、xmax、ymax的多边形),我们将需要获取每个边界框的中心点(xc, yc),该中心点将是我们对象的参考点。

最后,我们将绘制一个多边形,该多边形将是计数对象的参考,也就是说,如果对象的参考点在多边形内,我们将增加对象计数器,否则计数器不受影响。在下图中,我们可以看到多边形和多边形内的汽车数量的表示。

98207e5a249b966a7dc9247f3f7cc569.jpeg检测(绿色点)、多边形(红色线)和计数器

到此为止,我们已经知道了需求是什么,以及我们将实施用于计数对象的启发式的方法。现在可以加载模型:Yolov5 Nano

在本例中,我们将使用Yolov5的nano版本(即yolov5n),我们将通过PyTorch Hub从Ultralytics存储库中扩展它。同样,为了加载和在每一帧上生成迭代器,我们将使用OpenCV(即cv2),下述代码是具体的实现方式:

import cv2
import torch


VIDEO_PATH="data/traffic.mp4"
HUB="ultralytics/yolov5"
YOLO="yolov5n"


def count_cars(cap: cv2.VideoCapture):


    model = torch.hub.load(HUB, model=YOLO, pretrained=True)


    while cap.isOpened():
        status, frame = cap.read()


        if not status:
            break


        # Detection filtering and heuristic
        # will be implemented here.


        cv2.imshow("frame", frame)


        if cv2.waitKey(10) & 0xFF == ord('q'):
             break


    cap.release()




if __name__ == '__main__':


    cap = cv2.VideoCapture(VIDEO_PATH)
    count_cars(cap)

正如我们所看到的,我们已经定义了count_cars()函数,我们将在整个项目中对其进行更新。在4-6行,我们定义了视频所在路径、hub和模型名称的变量。从那里,让我们迅速跳到31-32行,在那里通过初始化cap对象加载视频,然后将其传递给count_cars()函数。

返回到第10行,通过PyTorch Hub,我们下载并初始化了yolov5n模型。随后,在第12行,我们生成一个迭代器,只要有要显示的帧,它就会保持活动状态。一旦帧完成,与迭代器相关的对象就会被释放(第26行)。

在第13行,我们读取帧,验证是否成功读取,并显示它们(第21行)。在这一部分,将出现一个窗口,用于查看从此迭代器显示的视频。最后,第23行是在按q键时删除弹出窗口。

检测过滤

过滤检测是指从Yolo预测中提取感兴趣的类别的过程。在这种情况下,我们将过滤掉分数大于0.5且类别为汽车、公共汽车或卡车的检测。同样,我们将需要找到边界框的中心点,我们将其用作对象的参考点。下面代码显示了这两个函数的实现。

import pandas as pd


def get_bboxes(preds: object):
    df = preds.pandas().xyxy[0]
    df = df[df["confidence"] >= 0.5]
    df = df[df["name"].isin(["car", "bus", "truck"])]


    return df[["xmin", "ymin", "xmax", "ymax"]].values.astype(int)


def get_center(bbox):
    center = ((bbox[0] + bbox[2]) // 2, (bbox[1] + bbox[3]) // 2)
    return center

正如我们所看到的,我们定义了两个函数get_bboxes()和get_center()。get_bboxes()函数(第3行)旨在提取所有分数大于0.5并过滤掉已经提到的类别的预测,返回一个坐标形式的边界框的numpy数组[xmin, ymin, xmax, ymax]。

get_center()函数(第10行)接收一个带有边界框坐标的numpy数组,并使用方程xc, yc = (xmin + xmax) // 2, (ymin + ymax) // 2分别计算中心点。

在这一点上,我们已经下载了模型,过滤了预测,并获得了每个对象的中心点。现在,我们唯一需要的是生成决定启发式区域的多边形。因此,让我们继续下一节!

启发式:实现

我们将定义的多边形可能会因视频、透视等而有所不同。在这种情况下,例如此示例,我们将使用8个点,如下图所示:

4e2525de21aa8977c4f9b28aee5fa756.jpeg 具有坐标的多边形 

一旦我们定义了多边形,我们唯一需要做的就是验证每个对象的参考点是否在多边形内。如果在多边形内,我们就会增加一个计数器,如果不在,我们就继续。

import cv2
import numpy as np
import matplotlib.path as mplPath


POLYGON = np.array([
    [333, 374],
    [403, 470],
    [476, 655],
    [498, 710],
    [1237, 714],
    [1217, 523],
    [1139, 469],
    [1009, 393],
])




def is_valid_detection(xc, yc):
    return mplPath.Path(POLYGON).contains_point((xc, yc))


def count_cars(cap: object):


    model = torch.hub.load(HUB, model=YOLO, pretrained=True)


    while cap.isOpened():
        status, frame = cap.read()


        if not status:
            break


        preds = model(frame)
        bboxes = get_bboxes(preds)


        detections = 0
        for box in bboxes:
            xc, yc = get_center(box)


            if is_valid_detection(xc, yc):
                detections += 1

让我们注意到在第5行,我们定义了多边形。在第17行,我们定义了关键函数:is_valid_detection(),它旨在验证参考点(xc, yc)是否在多边形内。这个函数在第37行调用,如果为真,它会增加有效检测计数器,否则什么也不做。

最后,为了可视化,我们将添加一些OpenCV行来显示计数器、每辆检测到的汽车的参考点和多边形。

def count_cars(cap: object):


    model = torch.hub.load(HUB, model=YOLO, pretrained=True)
    
    while cap.isOpened():
        status, frame = cap.read()


        if not status:
            break


        preds = model(frame)
        bboxes = get_bboxes(preds)


        detections = 0
        for box in bboxes:
            xc, yc = get_center(box)
            
            if is_valid_detection(xc, yc):
                detections += 1
                
            # Draw poit of reference for each detection
            cv2.circle(img=frame, center=(xc, yc), radius=5, color=(0,255,0), thickness=-1)
            # Draw bounding boxes for each detection
            cv2.rectangle(img=frame, pt1=(box[0], box[1]), pt2=(box[2], box[3]), color=(255, 0, 0), thickness=1)
        # Draw the counter
        cv2.putText(img=frame, text=f"Cars: {detections}", org=(100, 100), fontFace=cv2.FONT_HERSHEY_PLAIN, fontScale=3, color=(0,0,0), thickness=3)
        # Draw the polygon
        cv2.polylines(img=frame, pts=[POLYGON], isClosed=True, color=(0,0,255), thickness=4)
        # Display frame
        cv2.imshow("frame", frame)

结论

在本文中,我们看到了如何从视频中实现一个对象计数器。我们开发了一种计算汽车、卡车和公共汽车的实现,基于一个定义的多边形,即如果对象在多边形内,计数器就会增加。

·  END  ·

HAPPY LIFE

fe360590b56be8b1fbe76535ccf5bc97.png

本文仅供学习交流使用,如有侵权请联系作者删除

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/189234.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIA题目解析(1)

1、【多选题】关于动态 MAC 地址表说法正确的是? A、通过报文中的源MAC地址学习获得的动态MAC表项会老化 B、通过查看指定动态MAC地址表项的个数,可以获取接口下通信的用户数 C、在设备重启后,之前的动态表项会丢失 D、在设备重启后&…

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都…

C#,《小白学程序》第十九课:随机数(Random)第六,随机生成任意长度的大数(BigInteger)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// 除法运算为 Truffer…

【腾讯云云上实验室】向量数据库相亲社交应用实践

快速入口 &#x1f449;向量数据库_大模型知识库_向量数据存储_向量数据检索- 腾讯云 (tencent.com) 文章目录 前言1. 向量数据库概念及原理1.1 向量数据库概念1.2 向量数据库核心原理1.3 向量数据库优缺点1.4 向量数据库与传统数据库的区别 2. 腾讯云向量数据库的基本特性及优…

[数据结构]-红黑树

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、红黑树的…

可观测性建设实践之 - 日志分析的权衡取舍

指标、日志、链路是服务可观测性的三大支柱&#xff0c;在服务稳定性保障中&#xff0c;通常指标侧重于发现故障和问题&#xff0c;日志和链路分析侧重于定位和分析问题&#xff0c;其中日志实际上是串联这三大维度的一个良好桥梁。 但日志分析往往面临成本和效果之间的权衡问…

css加载会造成阻塞吗??

前言 前几天面试问到了这个问题&#xff0c;当时这个答得不敢确定哈哈&#xff0c;虽然一面还是过了 现在再分析下这个&#xff0c;总结下&#xff0c;等下次遇到就能自信得回答&#xff0c;666 准备工作 为了完成本次测试&#xff0c;先来科普一下&#xff0c;如何利用chr…

【UnLua】在 Lua 中定义 UE 反射类型

【UnLua】在 Lua 中定义 UE 反射类型 UEnum C UENUM(BlueprintType) enum class ETest : uint8 {Walking,Running,Sprinting,ALS_MAX UMETA(DisplayName"ALS MAX") };Test.generated.h #include "UObject/ObjectMacros.h" #include "UObject/Scri…

人工智能-注意力机制之Transformer

Transformer 比较了卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;和自注意力&#xff08;self-attention&#xff09;。值得注意的是&#xff0c;自注意力同时具有并行计算和最短的最大路径长度这两个优势。因此&#xff0c;使用自注意力…

红队攻防实战系列一之metasploit

百目无她&#xff0c;百书质华&#xff0c;君当醒悟&#xff0c;建我中华 本文首发于先知社区&#xff0c;原创作者即是本人 前言 在红队攻防中&#xff0c;我们主要在外网进行信息收集&#xff0c;通过cms或者其他漏洞拿到shell&#xff0c;之后通过免杀木马将windows或lin…

学习.NET验证模块FluentValidation的基本用法(续2:其它常见用法)

FluentValidation模块支持调用When和Unless函数设置验证规则的执行条件&#xff0c;其中when函数设置的是满足条件时执行&#xff0c;而Unless函数则是满足条件时不执行&#xff0c;这两个函数的使用示例如及效果如下所示&#xff1a; public AppInfoalidator() {RuleFor(x>…

C#,《小白学程序》第八课:列表(List)其二,编制《高铁列车时刻表》与时间DateTime

1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary&g…

C# APS.NET CORE 6.0 WEB API IIS部署

1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码&#xff1a; 项目文件展开&#xff1a; launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…

STM32_8(DMA)

一、DMA DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&#xff0c;节省了CPU的资源12个独立可配置的通道&#xff1a; DMA1&#xff08;7个通道&#xff09;&#xff…

RedLock底层源码分析

RedLock底层源码分析 一、Redlock红锁算法 https://redis.io/docs/manual/patterns/distributed-locks/官网说明 1、为什么要学习这个&#xff1f;怎么产生的&#xff1f; ​ 一个很直接的问题&#xff0c;当我使用redis锁的那台机器挂了&#xff0c;出现了单点故障了&#…

hdlbits系列verilog解答(exams/m2014_q4i)-45

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 实现以下电路&#xff1a; 二、verilog源码 module top_module (output out);assign out 1b0;endmodule三、仿真结果 转载请注明出处&#xff01;

计算机网络常考计算题之循环冗余校验(宝典教学)

文章目录 奇偶效验循环冗余校验例题四步走另一种题型 本文讲述了计算机考研中易出现的循环冗余校验&#xff0c;点赞关注收藏不迷路哦 我是一名双非计算机本科生&#xff0c;希望我的文章可以帮助到你。 奇偶效验 奇偶校验&#xff1a;也可以检测数据在传输过程中是否出现错误…

聚簇索引和非聚簇索引的区别;什么是回表

聚簇索引和非聚簇索引的区别 什么是聚簇索引&#xff1f;&#xff08;重点&#xff09; 聚簇索引就是将数据(一行一行的数据)跟索引结构放到一块&#xff0c;InnoDB存储引擎使用的就是聚簇索引&#xff1b; 注意点&#xff1a; 1、InnoDB使用的是聚簇索引&#xff08;聚簇索…

MySQL日期函数sysdate()与now()的区别,获取当前时间,日期相关函数

select sleep(2) as datetime union all select sysdate() -- sysdate() 返回的时间是当前的系统时间&#xff0c;而 now() 返回的是当前的会话时间。 union all select now() -- 等价于 localtime,localtime(),localtimestamp,localtimestamp(),current_timestamp,curre…