基于YOLOv8与ByteTrack实现多目标跟踪——算法原理与代码实践

概述

在目标检测中,有许多经算法如Faster RCNN、SSD和YOLO的各种版本,这些算法利用深度学习技术,特别是卷积神经网络(CNN),能够高效地在图像中定位和识别不同类别的目标。Faster RCNN是一种基于区域提议的目标检测算法,通过引入区域建议网络(RPN)来生成候选框,然后使用分类器和回归器来识别和精确定位目标。SSD(Single Shot MultiBox Detector)是一种单阶段的目标检测算法,它在单个卷积网络中同时进行目标分类和定位,具有较快的速度和较高的准确性。而YOLO(You Only Look Once)则是一种端到端的目标检测算法,通过将图像分割为网格并预测每个网格中的目标类别和边界框来实现目标检测,具有实时性的优势。
但这里有一个问题是,在目标检测上,所检测到的目标是一帧帧的,同一个目标在帧与帧之间并没有关联起来,这个时候,如果要确定上一帧的A_1目标是不是下一帧的A_2目标,这里就要用到多目标跟踪。多目标追踪传输的是一个视频流,对于每一帧,需要检测目标并分配一个“对象 ID”,在下一帧中,如果检测到相同的对象,则需要分配相同的对象 ID。有许多算法用于 MOT,如 SORT(简单在线实时跟踪)、DeepSort、StrongSort 等。

  1. SORT(Simple Online and Realtime Tracking):这是一种简单而高效的在线多目标跟踪算法,它结合了卡尔曼滤波和匈牙利算法来实现目标跟踪。SORT适用于实时应用,并且在计算资源有限的情况下表现良好。

  2. DeepSort:这是在SORT基础上发展而来的算法,它引入了深度学习技术,特别是卷积神经网络(CNN),用于提取目标的特征表示。DeepSort在目标跟踪的准确性和鲁棒性方面相对于传统方法有所提升。

  3. StrongSort:这是另一种基于深度学习的多目标跟踪算法,它通过设计更强大的特征提取网络和更精细的跟踪策略来提高目标跟踪的性能。

目标跟踪可分为下面几种:

基于特征的跟踪:这涉及基于其特征(如颜色、形状、纹理等)进行跟踪。

模板匹配:顾名思义,这种方法使用预定义的模板在每个视频序列中进行匹配。

基于相关性的跟踪:这种方法用于计算目标对象与后续帧中候选区域之间的相似性。

基于深度学习的跟踪:这种方法使用在大型数据集上训练的神经网络实时检测和跟踪对象。

ByteSort

其他MOT算法中移除低置信度检测框的问题主要源于对检测框置信度的阈值设置以及对检测框的筛选策略。因为低置信度的检测框被认为可能是误检测或者不可靠的检测结果,因此会被丢弃以提高跟踪的准确性。然而,这种策略可能会带来一些问题:

  1. 遮挡目标: 低置信度的检测框有时确实可以指示目标的存在,尤其是在目标被部分遮挡或者遮挡物很大时。丢弃这些低置信度的检测框可能会导致漏检目标,因为算法无法正确地识别被遮挡的目标。

  2. 轨迹断裂: 移除低置信度的检测框可能导致轨迹的不连续性,因为目标在一帧中被识别出来,在另一帧中却被移除了。这可能会导致跟踪算法无法正确地维持目标的标识符,从而产生碎片化的轨迹,使跟踪结果不连贯。

ByteTrack考虑低置信度的检测框的原因在于:

  1. 避免漏检: ByteTrack意识到低置信度的检测框可能是有价值的目标信息,尤其是在目标被遮挡的情况下。因此,保留这些检测框有助于避免目标漏检的情况,提高跟踪的完整性。

  2. 减少轨迹断裂: 通过保留低置信度的检测框,ByteTrack可以减少轨迹的不连续性,从而提高了多目标跟踪的连贯性和准确性。这有助于跟踪算法更好地维持目标的标识符,减少碎片化轨迹的出现。

可以从下面的例子说明这个问题,如下图1:
在这里插入图片描述
在帧 t1 中,初始化了三个不同的轨迹,因为它们的置信度都高于 0.5。但在帧 t2 和 t3 中,置信度从 0.8 下降到 0.4,然后从 0.4 下降到 0.1。

图2:
在这里插入图片描述
这些检测框将被阈值机制消除,相应的红色轨迹也会相应消失,如上图所示。但如果考虑所有的检测框,更多的误报率将会被引入,例如图1中右most的框。这带来了第二个问题。

图3:
在这里插入图片描述
例如,如图3所示,两个低分检测框通过运动预测框(虚线)与轨迹匹配,因此对象被正确恢复。背景框被移除,因为它没有匹配的轨迹。

因此,使用高分到低分检测框在匹配过程中。这种简单而有效的关联方法称为 BYTE,因为每个检测框都是轨迹的基本单位。首先,它根据运动或外观相似性将高分检测框匹配到轨迹。然后,它采用卡尔曼滤波器来预测下一帧中轨迹的位置。然后可以使用 IoU 或 Re-ID 特征距离计算预测框和检测框之间的相似性。在第二次匹配步骤中,低分检测和未匹配的轨迹,即红色框中的轨迹,使用相同的运动相似性进行匹配。

数据关联

数据关联是多目标跟踪的核心之一,它涉及计算轨迹和检测框之间的相似性,并根据相似性应用不同的策略进行匹配。

在相似性度量方面,位置、运动和外观是三个重要的线索。SORT算法通常简单地利用位置和运动线索。它使用卡尔曼滤波器来预测下一帧中的轨迹,并计算检测框和预测框之间的IoU作为相似性度量。然而,位置和运动线索更适用于短距离匹配。对于长距离匹配,外观相似性则变得更加重要。例如,长时间被遮挡的对象可能会通过外观相似性进行识别。外观相似性通常通过计算Re-ID特征的余弦相似性来衡量。与此类似,DeepSort采用了独立的深度学习模型来处理外观相似性。

在匹配策略方面,不同的算法使用不同的方法为对象分配ID。SORT通常通过一次匹配将检测框与轨迹匹配,而DeepSort则采用级联匹配策略。这种策略首先将检测框与最近的跟踪器匹配,然后与丢失的跟踪器进行匹配。

BYTE 算法

BYTE算法的输入是视频序列和检测器,以及一个检测阈值值。该算法的输出是视频的每一帧中的轨迹T,其中包含对象的边界框和ID。

对于视频中的每一帧,首先使用检测器(Det)预测检测框和相应的预测分数。然后,根据设定的检测分数阈值,将检测框分为高分(Det(high))和低分(Det(low))两部分。

分离检测框后,BYTE算法将卡尔曼滤波器应用于预测当前帧中每个轨迹T的新位置。首先对高分检测框进行关联,然后再处理剩余的低分检测框。

BYTE算法的主要亮点在于其非常灵活,能够与不同的关联方法兼容。这意味着它可以根据特定的应用场景选择最合适的关联方法,从而提高多目标跟踪的性能和效果。

性能测试

在同一个数据集上的表现,ByteTrack算法的性能优于SORT和DeepSORT算法,这表明它在多目标跟踪任务上具有较好的表现。,ByteTrack的MOTA达到了76.6,而SORT和DeepSORT的性能分别为74.6和75.4。

ByteTrack在算法架构上相对简单,但其性能却十分可观。这种性能提升可能源于它在关联过程中的灵活性以及对外观相似性的更好处理。

ByteTrack 与 YOLOv8 示例

多目标追踪场景中,大部分遮挡物体的检测结果都是低分框,ByteTrack 非常简洁地从低分检测框中寻找遮挡的物体,对遮挡非常鲁棒。ByteTrack 同时也为如何最大程度利用检测结果来帮助 MOT 提供了启发,下面提供了 ByteTrack 的部署代码和模型:

import supervision as sv
from ultralytics import YOLO 
from tqdm import tqdm
import argparse
import numpy as np

tracker = sv.ByteTrack() 
def process_video(
        source_weights_path: str, 
        source_video_path: str,
        target_video_path: str, 
        confidence_threshold: float = 0.3,
        iou_threshold: float = 0.7
) -> None:
    model = YOLO(source_weights_path)       # Load YOLO model 
    classes = list(model.names.values())    # Class names 
    LINE_STARTS = sv.Point(0,500)           # Line start point for count in/out vehicle
    LINE_END = sv.Point(1280, 500)          # Line end point for count in/out vehicle
    tracker = sv.ByteTrack()                # Bytetracker instance 
    box_annotator = sv.BoundingBoxAnnotator()     # BondingBox annotator instance 
    label_annotator = sv.LabelAnnotator()         # Label annotator instance 
    frame_generator = sv.get_video_frames_generator(source_path=source_video_path) # for generating frames from video
    video_info = sv.VideoInfo.from_video_path(video_path=source_video_path)
    line_counter = sv.LineZone(start=LINE_STARTS, end = LINE_END)
    line_annotator = sv.LineZoneAnnotator(thickness=2, text_thickness=2, text_scale= 0.5)

    with sv.VideoSink(target_path=target_video_path, video_info=video_info) as sink:
        for frame in tqdm(frame_generator, total= video_info.total_frames):
            # Getting result from model
            results = model(frame, verbose=False, conf= confidence_threshold, iou = iou_threshold)[0] 
            detections = sv.Detections.from_ultralytics(results)    # Getting detections
            #Filtering classes for car and truck only instead of all COCO classes.
            detections = detections[np.where((detections.class_id==2)|(detections.class_id==7))]
            detections = tracker.update_with_detections(detections)  # Updating detection to Bytetracker
            # Annotating detection boxes
            annotated_frame = box_annotator.annotate(scene = frame.copy(), detections= detections) 

            #Prepare labels
            labels = []
            for index in range(len(detections.class_id)):
                # creating labels as per required.
                labels.append("#" + str(detections.tracker_id[index]) + " " + classes[detections.class_id[index]] + " "+ str(round(detections.confidence[index],2)) )
            
            # Line counter in/out trigger
            line_counter.trigger(detections=detections)
            # Annotating labels
            annotated_label_frame = label_annotator.annotate(scene=annotated_frame, detections=detections, labels=labels)
            # Annotating line labels
            line_annotate_frame = line_annotator.annotate(frame=annotated_label_frame, line_counter=line_counter)
            sink.write_frame(frame = line_annotate_frame)

if __name__ == "__main__":
    parser = argparse.ArgumentParser("video processing with YOLO and ByteTrack") 
    parser.add_argument(
        "--source_weights_path",
        required=True,
        help="Path to the source weights file",
        type=str
    )
    parser.add_argument(
        "--source_video_path",
        required=True, 
        help="Path to the source video file",
        type = str
    )
    parser.add_argument(
        "--target_video_path",
        required=True,
        help="Path to the target video file",
        type= str
    )
    parser.add_argument(
        "--confidence_threshold",
        default = 0.3,
        help= "Confidence threshold for the model",
        type=float
    )
    parser.add_argument(
        "--iou_threshold",
        default=0.7,
        help="Iou threshold for the model",
        type= float
    )
    args = parser.parse_args() 
    process_video(
        source_weights_path=args.source_weights_path, 
        source_video_path= args.source_video_path,
        target_video_path=args.target_video_path, 
        confidence_threshold=args.confidence_threshold,
        iou_threshold=args.iou_threshold
    )

在这里插入图片描述
完整代码带GUI界面代码和代码部署可参考《YOLOv8项目实践——目标检测、实例分割、姿态估计、目标追踪算法原理及模型部署(Python实现带界面)
源码下载地址:https://download.csdn.net/download/matt45m/89036361?spm=1001.2014.3001.5503
模型下载地址链接:https://pan.baidu.com/s/1-t5TwKzdRuHF3dL7POk1dA
提取码:3r1v

BoT-SORT是发表于2022年的先进的多目标跟踪算法,它结合了运动和外观信息、相机运动补偿和更准确的卡尔曼滤波状态向量,并把这些改进集成到ByteTrack,从而在MOTA、IDF1和HOTA性能指标上超过了ByteTrack,增强了目标跟踪的鲁棒性,比较适用于存在相机运动的场景。YOLOv8代码中已集成了BoT-SORT。本课程使用YOLOv8和BoT-SORT对视频中的行人、车辆做多目标跟踪计数与越界识别,开展YOLOv8目标检测和BoT-SORT多目标跟踪强强联手的应用。课程分别在Windows和Ubuntu系统上做项目演示,并对BoT-SORT原理代码做详细解读(使用PyCharm单步调试讲解)。课程包括:基础篇、实践篇、原理篇和代码解析篇。Ÿ  基础篇包括多目标跟踪任务介绍、常用数据集和评估指标;Ÿ  实践篇包括Win10和Ubuntu系统上的YOLOv8+BoT-SORT的多目标跟踪计数与越界识别具体的实践操作步骤演示;Ÿ  原理篇中讲解了马氏距离、匈牙利算法、卡尔曼滤波器、SORT、DeepSORT和BoT-SORT多目标跟踪算法原理,并解读了BoT-SORT论文;Ÿ  代码解析篇中使用PyCharm单步调试对BoT-SORT的代码逐个文件进行讲解。课程提供代码解析文档。相关课程:《YOLOv8+ByteTrack多目标跟踪(行人车辆计数与越界识别)》https://edu.csdn.net/course/detail/38901《YOLOv8+DeepSORT多目标跟踪(行人车辆计数与越界识别)》 https://edu.csdn.net/course/detail/38870《YOLOv5+DeepSORT多目标跟踪与计数精讲》https://edu.csdn.net/course/detail/32669 
以下是基于 YOLOv5 和 ByteTrack 算法实现计数的 Python 代码: ```python import cv2 import torch import argparse from models.experimental import attempt_load from utils.general import non_max_suppression from utils.torch_utils import select_device from trackers.byte_tracker import ByteTracker def detect(source, weights, conf_thres, iou_thres, device): model = attempt_load(weights, map_location=device) # load FP32 model stride = int(model.stride.max()) # model stride imgsz = check_img_size(640, s=stride) # check image size if device.type != 'cpu': model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) # run once cap = cv2.VideoCapture(source) # ByteTrack 初始化 byte_tracker = ByteTracker() while cap.isOpened(): ret, img0 = cap.read() if not ret: break img = letterbox(img0, new_shape=imgsz)[0] img = img[:, :, ::-1].transpose(2, 0, 1) img = np.ascontiguousarray(img) img = torch.from_numpy(img).to(device) img = img.float() # uint8 to fp16/32 img /= 255.0 # 0 - 255 to 0.0 - 1.0 if img.ndimension() == 3: img = img.unsqueeze(0) # YOLOv5 推理 pred = model(img, augment=False)[0] pred = non_max_suppression(pred, conf_thres, iou_thres, classes=None, agnostic=False) # ByteTrack 计数 byte_tracker.track(img0, pred[0], 0.5) cv2.destroyAllWindows() cap.release() if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--source', type=str, default='0', help='source') # file/folder, 0 for webcam parser.add_argument('--weights', type=str, default='yolov5s.pt', help='model.pt path') parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold') parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS') parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') args = parser.parse_args() detect(args.source, args.weights, args.conf_thres, args.iou_thres, args.device) ``` 其中,`ByteTracker` 是一个基于 ByteTrack 算法的目标跟踪器,可以参考 [这个链接](https://github.com/STVIR/pysot/tree/master/pysot/tracker) 获取代码。`detect()` 函数中,首先加载 YOLOv5 模型,并对视频帧进行预处理,然后进行 YOLOv5 的目标检测。接着,将检测结果传递给 `ByteTracker` 进行目标跟踪,并进行计数。最后,关闭视频流并释放资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知来者逆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值