多目标跟踪框架boxmot介绍

引言

boxmot由mikel brostrom开发,用于目标检测,分割和姿态估计模型的SOTA(state of art)跟踪模块,现已加入python第三方库 PYPI,可用pip包管理器进行安装。
boxmot所支持的跟踪器采用外观特征识别方法,如重型ReID(CLIRdID)和轻型ReID(LightMBN, OSNet等),来识别不同图像帧中同一个目标。这些ReID权文件在运行boxmot时自动下载,无需事先下载checkpoint文件。
boxmot目前支持的对象检测模型有:yolov8, yolo-NAS和YOLOX。支持的跟踪器:BoTSORT, DeepOCSORT, OCSORT, HybridSORT, ByteTrack, StrongSORT。之前常用的DeepSort由增强型的StrongSORT取代。
boxmot可以看作一个软件封装器,将多种对象检测模型与不同的目标跟踪器组合,实现多目标跟踪。

boxmot安装

安装以linux系统为例,假定该系统已经安装有python >=3.8,且建立好虚拟环境。

将boxmot安装到yolo_tracking目录:

git clone https://github.com/mikel-brostrom/yolo_tracking.git
cd yolo_tracking
pip install -v -e .

以上命令操作过程,即基本完成所需运行的python语言,pytorch模块运行环境。需要说明,这里还需要安装ultralytics相关模块。不过,在yolo_tracking/examples/track.py中,程序自动检查是否安装ultralytics。若没有,则自动安装mikel-brosrom github目录中保存的ultralytics v8.0.146到虚拟环境。需要注意:boxmot v10.0.43仅与ultralytics v8.0.146兼容,若安装ultralytics最新版本将出现莫名错误。
利用examples/track.py安装ultralytics与boxmot现有版本兼容。这里有个问题,track程序将ultralytics安装到虚拟环境,而不在工作目录yolo_tracking下,这样调试程序时,不能跟踪到ultralytics相关的程序模块。当然可以对python调试器做一些相应的配置,就更沟跟踪到虚拟环境的模块,但是操作很麻烦。
把ultralytics安装到yolo_tracking的目录,操作如下:
先删除虚拟环境下和系统中可能安装的ultralytics模块:

pip uninstall ultralytics

克隆ultralytics v8.0.146

git clone https://github.com/mikel-brostrom/ultralytics.git

此操作在home目录下产生ultralytics目录。我们需要将ultralytics二级目录:~/ultralytics/ultralytics移动到yolo_tracking目录下,完成安装ultralytics到工作目录yolo_tracking,这样在python程序调试时,可以跟踪到ultralytics模块。为了防止混淆,将examples/track.py中安装ultralytics语句注释掉:

#__tr = TestRequirements()
#__tr.check_packages(('ultralytics @ git+https://github.com/mikel-brostrom/ultralytics.git', ))  # install  ultralytics

运行示例

运行yolov8s+strongsort对输入视频进行车辆跟踪示例:

python examples/track.py  \
   --yolo-model yolov8s    \
   --reid-mode  osnet_x0_25_market1501.pt   \
   --source     ~/yolo_tracking/MOT16-13-h264.mp4  \ 
   --save         \
   --show         \
   --classes 2     \
   --tracking-method strongsort 

运行 yolo_nas + strongsort 示例:

python examples/track.py  \
   --yolo-model yolo_nas_s    \
   --reid-mode  osnet_x0_25_market1501.pt   \
   --source     ~/yolo_tracking/MOT16-13-h264.mp4  \ 
   --save         \
   --show         \
   --classes 2     \
   --tracking-method strongsort 

track.py程序运行解析

examples/track.py中,经繁琐的模型初始化后,每帧图像的检测-跟踪处理开始于循环:

for frame_idx, r in enumerate(results)

即,每帧产生一个results,对每帧results写入MOT跟踪文件,而实际的处理看跟踪results的跳转。这里跳转至
ultralytics.engine.predictor.py 中的 stream_inference()函数,略过某些初始化,看函数中的循环:

for batch in self.dataset

其中重要的处理在:

# Preprocess              
with profilers[0]:
    im = self.preprocess(im0s)       #1 图像格式处理,提取帧内容到数组。
# Inference
with profilers[1]
    preds = self.inference(im, *args, **kwargs)   #2 对象检测器,提取帧内目标。

# Postprocess
            with profilers[2]:                                 # 3  对所提取目标的后处理,即对跟踪器的目标输入,进行某种处理。
                if isinstance(self.model, AutoBackend):                           
                    self.results = self.postprocess(preds, im, im0s)           # ultralytics内定义的检测器处理方法,  如 yolov8
                else:
                    self.results = self.model.postprocess(path, preds, im, im0s)   # ultralytics之外的检测器处理, 如 yolo_nas, yolox
            with profilers[3]:
                self.run_callbacks('on_predict_postprocess_end')         # 4  构造跟踪器 tracker, 对检测目标的跟踪
  1. preprocess, 输入图像处理。
  2. inference, 推理,目标检测器提取图像帧中的目标。
  3. postprocess, 目标检测器输出preds的处理, yolov8用 non_max_suppression(); 非ultralytics的目标检测器(yolo_nas, yolox)则貌似没有处理。
  4. postprocess_end,跟踪器处理,输出跟踪结果results。
    yolov8以及之前的版本,yolov3, yolov5等采用non_max_suppression(preds, …)来去除不可信的多余目标,且可根据classes来筛选需要保留的目标类别,从而减少目标数量,为后续的跟踪器创造较好的工作环境,减少跟踪器运行时间。因为跟踪器按照目标数量逐一迭代产生跟踪轨迹tracks,迭代为串行运算,目标越多跟踪时间越长。Postprocess执行non_max_supperssion。
    对于yolo-nas,由Deci AI公司开发,目前尚未公开,boxmot无法筛选目标类别,所以,postprocess对preds基本没有处理,直接送到跟踪器tracker。
    最后,on_predict_postprocess_end执行跟踪器操作,输入preds,输出results。

图1
图1 yolov8 postprocess,经non_max_suppression(),筛选出小车对象(classes=2)。

在这里插入图片描述
图2 yolo_nas postprocess, boxmot目前不能通过筛选classes目标,跟踪输出多个类型目标。

ultralytics.trackers.track.py执行函数 on_predict_postprocess_end, boxmot所支持的跟踪器定义在 boxmot.trackers目录中。
完成 Preprocess, Inference, Postprocess后,得到跟踪输出results,进入可视化过程,在输入视频上绘制跟踪框;标注目标id、类型、置信度等参数等。
由此,完成一帧图像的检测-跟踪-可视化。predictor.py函数stream_inference对一帧图像处理,track.py中的循环体(for frame_idx, r in enumerate(results))对输入视频逐帧处理。

examples目录下还有两个可执行文件val.py, evolve.py
val.py 根据选定的benchmark(MOT16, MOT17, MOT20),对检测器+跟踪器组合做性能评估,跟踪类型为persons。
以下benchmark = MOT17, yolov8s + strongsort的评估结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看来MOT-17指标与mikel brostrom提供的评估指标还有相当差距,原因不明。此外,本人运行得到的MOT-16各项指标与MOT-17倒是相差很小。

evolve.py 对跟踪器进行配置参数优化,就是在val.py过程提供评估指标,采用NSGA-II多目标遗传算法调整跟踪器配置参数,迭代运行,实现配置参数优化。显然,这是耗时较多的计算过程,尚未尝试。

跟踪框可视化

此处记录跟踪框可视化过程,便于对跟踪框所标注的目标信息进行修改显示。对此部分内容不感兴趣的读者可忽略。
从一帧图像的处理着手,见predictor.py 中函数stream_inference(), 其中看注释Visualize, save, write results下面的循环:

for i in range(n):
    if self.args.verbose or self.args.save or self.args.save_txt or self.args.show:   ###############
                    s += self.write_results(i, self.results, (p, im, im0))   # 此处进入跟踪框可视化

函数write_results部分:

def write_results(self, idx, results, batch):

    if self.args.save or self.args.show:  # Add bbox to image
            plot_args = {
                'line_width': self.args.line_width,
                'boxes': self.args.boxes,
                'conf': self.args.show_conf,
                'labels': self.args.show_labels}
            if not self.args.retina_masks:
                plot_args['im_gpu'] = im[idx]
            self.plotted_img = result.plot(**plot_args)     ####进入plot

result.plot在 ultralytics.engine.results.py定义,模块引用

from ultralytics.utils.plotting import Annotator

下面是result.plot函数使用类Anootator

annotator = Annotator(                                       #定义实例annotator
            deepcopy(self.orig_img if img is None else img),
            line_width,
            font_size,
            font,
            pil or (pred_probs is not None and show_probs),  # Classify tasks default to pil=True
            example=names)
            ...
# Plot Detect results
if pred_boxes and show_boxes:
            for d in reversed(pred_boxes):
                c, conf, id = int(d.cls), float(d.conf) if conf else None, None if d.id is None else int(d.id.item())
                name = ('' if id is None else f' {id} ')    
                label = (f'{name} {conf:.2f}' if conf else name) if labels else None
                annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True))     # 进入annotator.box_label , 绘制bbox框。

实际的跟踪框bbox绘制在函数 annotator.box_label(), 这个可视化与mikel brostrom之前的版本(v3, v4, v5, v6)一致,都用ultralytics.utils.plotting.py。找到这个annotator.box_label,可以更改跟踪框显示方式,因为默认的label参数太多(id, class_name, conf),当图像帧中目标很多时,显示label一团糟,根本看不清。找到修改地方就主动。见图1,图2的简洁label显示。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
deepsort是一个基于PyTorch框架多目标跟踪算法。它结合了深度学习和排序方法,可以对视频中的多个目标进行准确且稳定的跟踪。 Deepsort主要分为三个步骤:特征提取、目标识别和轨迹管理。 首先,特征提取阶段使用预训练的深度卷积神经网络(如YOLO或ResNet)来提取每个检测到的目标的特征向量。这些特征向量是用来描述目标外观和位置的重要特征。 接下来,目标识别阶段使用线性支持向量机(linear support vector machine,简称SVM)来分配一个唯一的ID给每个目标。SVM会根据目标的特征向量进行分类,将相似的目标归为同一类别。 最后,在轨迹管理阶段,使用卡尔曼滤波(Kalman filter)对目标的位置进行预测,并计算目标之间的相似度。根据预测位置和相似度,使用匈牙利算法(Hungarian algorithm)对目标进行关联,从而形成准确的目标轨迹。 Deepsort算法具有高准确性和鲁棒性,可以在复杂的场景中实现准确的多目标跟踪。它在行人跟踪、交通监控等领域有广泛应用。由于基于PyTorch框架开发,Deepsort还可以和其他深度学习模型进行结合,提高目标检测和跟踪的性能。 总的来说,Deepsort是一个基于PyTorch框架多目标跟踪算法,通过特征提取、目标识别和轨迹管理三个阶段,实现准确且稳定的目标跟踪。它在实际应用中展现了很高的性能和效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值