YOLO8实战:yolov8实现行人跟踪计数

本文介绍了使用YOLOv8模型进行行人跟踪和计数的方法,探讨了YOLOv8的改进,包括Darknet-53骨干网络、Anchor-Free检测头和新的损失函数。通过目标检测和多目标跟踪算法ByteTracker,实现视频中的人流量统计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章首先介绍YOLOV8实现人流量跟踪计数的原理,文末附代码下载地址

yolo8人流量统计

引言:行人跟踪统计是智能监控系统中的重要功能,可以广泛应用于人流控制、安全监控等领域。传统的行人跟踪算法往往受到光照、遮挡等因素的干扰,难以实现准确跟踪。随着深度学习技术的发展,目标检测模型逐渐成为行人跟踪的主流方案。本文介绍使用 YOLOv8 目标检测模型实现行人跟踪统计的方法。

一、YOLOv8模型介绍

YOLOv8 是 ultralytics 公司在 2023 年开源的 YOLOv5 的下一个重大更新版本,按照官方描述,YOLOv8 是一个 SOTA 模型,它建立在以前 YOLO 版本的成功基础上,并引入了新的功能和改进,以进一步提升性能和灵活性。不过 ultralytics 并没有直接将开源库命名为 YOLOv8,而是直接使用 ultralytics 这个词,原因是 ultralytics 将这个库定位为算法框架,而非某一个特定算法,一个主要特点是可扩展性。其希望这个库不仅仅能够用于 YOLO 系列模型,而是能够支持非 YOLO 模型以及分类分割姿态估计等各类任务。因此,YOLO发展到如今的版本,已经不单单是目标检测的代名词,就像官方所解释的那样,YOLOv8 更应该更名为Ultralytics 。目前YOLO8算法框架(ultralytics库)全面支持图像分类、目标检测和实例分割、人体关键点检测等任务。在目标跟踪方面,YOLO8算法库内置了多目标跟踪领域的SOTA算法(Byte-tracker和Bot-tracker)。在实例分割方面,支持与SAM、Fast-SAM无缝集成.....未来,我们也期待着ultralytics库能够扩充更多的CV领域的SOTA算法。

与之前的YOLO版本相比,YOLOv8在以下几个方面有所不同:

  1. 骨干网络:YOLOv8采用了全新的骨干网络,以提高模型的性能和准确性。YOLOv8的骨干网络是Darknet-53。Darknet-53是一个深度卷积神经网络模型,它由53个卷积层和池化层组成,用于提取图像特征。其实Darknet-53在YOLOv3网络中就已经被广泛使用,并在YOLOv4和YOLOv5中也得到了应用。它具有较强的特征提取能力,能够在目标检测任务中提供较好的性能。

  2. 检测头:YOLOv8采用了Anchor-Free的检测头,这意味着它不再需要预先定义一组固定的先验框来检测目标,而是可以直接从原始图像中预测目标的边界框,这有助于提高模型的灵活性和准确性。

  3. 损失函数:YOLOv8采用了新的损失函数,以更好地优化模型的训练过程,进一步提高模型的性能。YOLOv8的损失函数由多个部分组成,包括分类损失(VFL Loss)、回归损失为CIOU Loss+DFL的形式。

限于文章的篇幅,详细分析YOLO8的网络结构并不是本篇文章的重点,我们单独在另外一篇文章中详细介绍。接下来,我们来介绍一下如何使用yolo8实现行人跟踪计数。

二、基于yolo8实现行人统计

统计行人必须先要检测到行人。这不得不提一下YOLO目标检测实现的基本原理:基于将输入图像分割成若干个网格,然后对每个网格进行目标检测。每个网格会预测出多个bounding box(包含物体的矩形区域)以及这些box中包含物体的概率和物体的类别信息。具体来说,YOLO首先将输入图像分成SxS个格子,如果某个物体的中心位置的坐标落入到某个格子,那么这个格子就负责检测出这个物体。每个网格会预测B个bounding box的信息和C个物体属于某种类别的概率信息。Bounding box信息包含5个数据值,分别是x,y,w,h,和confidence,其中x,y是指当前格子预测得到的物体的bounding box的中心位置的坐标,w,h是bounding box的宽度和高度,confidence代表该box中是否包含物体的置信度。

由于yolo官方已经在COCO数据集上训练过yolov8,分别有yolo8n、yolo8m、yolo8s、yolo8l、yolo8x五种不同尺寸的模型。因此,使用yolov8的这五种预训练模型,可以识别COCO数据集上已有的80种物体。接下来,我们使用yolo官方提供的预训练模型YOLO8n,识别并统计一张图片中有多少个人。首先看下面的代码:

from ultralytics import YOLOmodel=YOLO('./yolov8n.pt')#加载本地的yolo8n模型# results=model.predict('./people.jpeg')results=model('./people.jpeg')#推理本地图片print(type(results))print(type(results[0]))

上面的代码我们使用model('./people.jpeg')和model.predict('./people.jpeg)两种方式对图片进行推理预测

图片来源于网络

我们输出模型推理的结果,发现推理结果results是一个保存Results类的List数组,由于我们是一张一张图片推理的,因此List数组中仅有一个Results对象。

那么这个Results对象是干什么的呢?其实,这对象包含了YOLO8模型的所有预测信息,包括目标检测任务、图片分类任务、实例分割任务、人体关键点检测任务、多目标跟踪任务的所有预测信息都可以在这个对象中找到。因此,使用yolo8很简单,第一步配置好环境、第二步下载好模型、第三步写两行预测代码,后续的事情就是处理预测结果Results对象的事情了。下面我们来看一下Results对象中究竟都有什么属性。首先看一下YOLO官方对这个对象的注释:

"""
    A class for storing and manipulating inference results.

    Args:
        orig_img (numpy.ndarray): The original image as a numpy array.
        path (str): The path to the image file.
        names (dict): A dictionary of class names.
        boxes (torch.tensor, optional): A 2D tensor of bounding box coordinates for each detection.
        masks (torch.tensor, optional): A 3D tensor of detection masks, where each mask is a binary image.
        probs (torch.tensor, optional): A 1D tensor of probabilities of each class for classification task.
        keypoints (List[List[float]], optional): A list of detected keypoints for each object.

    Attributes:
        orig_img (numpy.ndarray): The original image as a numpy array.
        orig_shape (tuple): The original image shape in (height, width) format.
        boxes (Boxes, optional): A Boxes object containing the detection bounding boxes.
        masks (Masks, optional): A Masks object containing the detection masks.
        probs (Probs, optional): A Probs object containing probabilities of each class for classification task.
        keypoints (Keypoints, optional): A Keypoints object containing detected keypoints for each object.
        speed (dict): A dictionary of preprocess, inference, and postprocess speeds in milliseconds per image.
        names (dict): A dictionary of class names.
        path (str): The path to the image file.
        _keys (tuple): A tuple of attribute names for non-empty attributes.
    """

Results对象主要包含下列重要的属性:

boxes:该对象保存了目标检测的结果。

masks:该对象保存了实例分割的结果

probs:该对象保存了图像分类的结果

keypoints: 关键点检测的结果

names: 模型的类别

speed:  检测速度相关信息

orig_img:加载在内存中的原始图像

path:包含输入图像的路径

result对象默认是torch.Tensor对象,也可以转为其他对象

这里我们主要来看一下boxes对象的属性:

"""
    A class for storing and manipulating detection boxes.

    Args:
        boxes (torch.Tensor | numpy.ndarray): A tensor or numpy array containing the detection boxes,
            with shape (num_boxes, 6) or (num_boxes, 7). The last two columns contain confidence and class values.
            If present, the third last column contains track IDs.
        orig_shape (tuple): Original image size, in the format (height, width).

    Attributes:
        xyxy (torch.Tensor | numpy.ndarray): The boxes in xyxy format.
        conf (torch.Tensor | numpy.ndarray): The confidence values of the boxes.
        cls (torch.Tensor | numpy.ndarray): The class values of the boxes.
        id (torch.Tensor | numpy.ndarray): The track IDs of the boxes (if available).
        xywh (torch.Tensor | numpy.ndarray): The boxes in xywh format.
        xyxyn (torch.Tensor | numpy.ndarray): The boxes in xyxy format normalized by original image size.
        xywhn (torch.Tensor | numpy.ndarray): The boxes in xywh format normalized by original image size.
        data (torch.Tensor): The raw bboxes tensor (alias for `boxes`).

    Methods:
        cpu(): Move the object to CPU memory.
        numpy(): Convert the object to a numpy array.
        cuda(): Move the object to CUDA memory.
        to(*args, **kwargs): Move the object to the specified device.
    """

 因此我们要统计一张图像的行人数,就非常容易了,见如下代码:

上面的代码中我们先统计模型检测到的所有的物体的数量,然后进一步筛序出person的个数。就完成了一张图片下的行人统计。

那么如果不是一张图片而是一段视频呢?我们知道,视频本质上是由一张张图片按照时间序列组成的,如果把一段视频拆成一张张图片然后再按照上面的方法,能不能统计出一段视频有多少人呢?答案是不行的,比如一段10帧的视频,但是整个视频只有一个人,试想如果把这段视频分成10张图片然后单独统计,最后是不是把一个人算成了10个人?这里涉及到了目标跟踪,目标跟踪是指在给定第一帧图像中的目标位置后,根据跟踪算法预测出后续帧中目标的位置。其基本原理包括特征提取、运动模型、外观模型、在线更新机制等部分。其中,特征提取用于提取图像目标的特征,运动模型用于描述帧与帧之间的目标运动状态关系,预测下一帧中目标的可能位置。在目标跟踪中,会为同一个被跟踪的物体赋予一个ID,以区别其他物体。因此,要想统计一段视频中有多少行人,势必要求我们使用目标跟踪技术手段。限于文章的篇幅,在这里,我们就不详细介绍目标跟踪领域的知识了。下面直接介绍Byte-Tracker多目标追踪算法,这也是YOLO8内置的一种多目标追踪算法。

ByteTracker是一种用于多目标跟踪的算法,它是基于深度学习的目标检测算法和跟踪算法的结合。ByteTracker算法的核心思想是在目标检测的基础上,利用目标之间的相似性和连续性,通过对目标进行跟踪,实现多目标跟踪。

ByteTracker算法的流程如下:

  1. 目标检测:首先使用目标检测算法对视频序列中的每一帧进行目标检测,获取每个目标的位置和大小。

  2. 特征提取:对于每个检测到的目标,利用深度学习网络提取其特征,这些特征将被用于后续的跟踪过程。

  3. 目标跟踪:在连续帧之间,利用目标的特征相似性和运动连续性,建立目标之间的对应关系,实现目标的跟踪。

  4. 数据关联:将不同帧中的目标进行跟踪,需要解决数据关联问题,即确定哪些目标属于同一个轨迹。ByteTracker采用了一种基于匈牙利算法的数据关联方法。

  5. 轨迹管理:对于每个目标轨迹,需要对其进行起始、终止、更新等操作,以便实现多目标跟踪。

下面我们来看,如何在yolo8中使用这种多目标追踪算法,实现视频人流量追踪统计。

实现起来非常简单,也仅仅只需要一行代码。

model.track(source=source)即可调用yolo8内置的跟踪模式,但是默认使用的是BotTracker跟踪算法,这是yolo8内置的另外一种算法,在具有遮挡的情况下,效果非常好,比Byte-tracker、DeepSort、Sort等算法准确许多。但是速度却比这些算法慢,我们这里使用byte-tracker跟踪算法,需要在track()中指定tracker="bytetrack.yaml"即可。上图代码中,classes=[0]表示只检测行人,忽略其他物体。

还记得yolo8返回的Results对象的boxes属性吗,在使用track模式后,boxes对象的id就不再像是在目标检测任务那样为None,它现在有了唯一的值,只要跟踪算法没有丢失目标,这个id值就一直不会变,因此这个值就可以用来区分不同的物体。比如,同一个人一直都是一个id值,除非跟踪算法丢失了这个人。

我们可以一边遍历Results的结果一边把id值放在一个set()中,最后统计set()的长度,这样就实现了统计一个视频中的人数。

我们在视频中划定两个区域,如本篇文章的第一个视频所示,线的上方和下方其实各有一个不可见的区域。如果一个人的出现在上面的区域,之后又出现下面的区域,说明这个人是从视频的上方向下方行走,这样就可以知道一个人的轨迹方向了,就可以按照方向统计人流量了。比如本篇文章的第一个视频,人物从视频下方向上方走,视为‘出’,而从上方移动到下方,视为‘进’。

另外,限于本篇文章的篇幅,更细致的逻辑讲解、代码实现将在源码注释中体现,需要源码的小伙伴记得给文章点赞收藏哦。源码资源放在公众号中了,微信公众号搜索 ‘编程学习园地’,关注公众号,在聊天窗口回复关键字“yolo8实战”即可获得下载链接。

### 使用YOLO实现区域计数预测或目标数量统计 要使用YOLO进行目标检测中的区域计数预测或目标数量统计,可以通过以下方法完成: #### 1. 加载预训练模型 通过加载官方提供的预训练模型 `yolov8n` 或其他版本(如 `yolov8s`, `yolov8m`),可以直接用于识别图像中的对象。这些模型已经经过充分训练,能够识别 COCO 数据集上的 80 种常见类别[^1]。 ```python from ultralytics import YOLO # 加载本地的 yolo8n 预训练模型 model = YOLO('yolov8n.pt') ``` #### 2. 推理过程 对于给定的一张图片,调用模型的 `predict` 方法或者直接传入路径即可获得检测结果。返回的结果是一个列表,其中每个元素代表一次推理的结果。 ```python # 对指定图片进行推理 results = model('./people.jpeg') # 打印结果类型以便进一步处理 print(type(results)) # 输出:<class 'list'> print(type(results[0])) # 输出:<class 'ultralytics.engine.results.Results'> ``` #### 3. 提取感兴趣的目标 在 COCO 数据集中,“person” 类别的索引为 0。为了统计图片中的人数或其他特定类别的数量,可以从检测结果中提取对应的框信息。 ```python for result in results: boxes = result.boxes.cpu().numpy() # 获取所有的边界框 class_ids = boxes.cls.astype(int) # 获取分类 ID # 统计 person 的数量 (COCO 数据集中 person 的 id 是 0) num_people = sum(class_id == 0 for class_id in class_ids) print(f'图片中共有 {num_people} 个人.') ``` #### 4. 区域划分与计数 如果需要对图片的不同区域分别进行目标计数,则可以先手动定义多个子区域,再筛选落在该区域内的目标。 假设我们将图片划分为左半部分和右半部分: ```python def count_in_region(boxes, region_bounds): """ 计算落入某个区域的目标数量 """ count = 0 for box in boxes.xyxy: # xyxy 表示 [xmin, ymin, xmax, ymax] cx = (box[0] + box[2]) / 2 # 目标的中心点横坐标 cy = (box[1] + box[3]) / 2 # 目标的中心点纵坐标 if region_bounds[0] <= cx <= region_bounds[2] and \ region_bounds[1] <= cy <= region_bounds[3]: count += 1 return count image_width = 640 # 图片宽度 image_height = 480 # 图片高度 left_region = [0, 0, image_width // 2, image_height] # 左半区 right_region = [image_width // 2, 0, image_width, image_height] # 右半区 num_left = count_in_region(result.boxes, left_region) num_right = count_in_region(result.boxes, right_region) print(f'左半区共有 {num_left} 个人.') print(f'右半区共有 {num_right} 个人.') ``` #### 5. 跟踪目标 当涉及到视频流时,除了简单的静态图片计数外,还可以引入目标跟踪技术来持续追踪移动的对象。这通常依赖于特征匹配以及运动连续性的原则[^3]。 例如,在每一帧中记录目标的位置,并将其关联到前一帧中的同一目标。 --- ### 总结 上述流程展示了如何基于 YOLO 模型实现目标检测、区域划分以及动态场景下的目标跟踪功能。具体应用可以根据实际需求调整参数设置和逻辑判断条件。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城南皮卡丘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值