From 697dd72e1ea653b3d9e218a1aab47aef4209e575 Mon Sep 17 00:00:00 2001 From: Feng Ni Date: Sat, 19 Nov 2022 13:55:39 +0800 Subject: [PATCH] [MOT] add multi-class bytetrack and fix doc (#7364) --- configs/mot/bytetrack/README_cn.md | 37 +++++++++++--- .../bytetrack_ppyoloe_ppvehicle9cls.yml | 49 +++++++++++++++++++ ppdet/engine/tracker.py | 18 +++++-- ppdet/modeling/mot/utils.py | 9 ++-- 4 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 configs/mot/bytetrack/bytetrack_ppyoloe_ppvehicle9cls.yml diff --git a/configs/mot/bytetrack/README_cn.md b/configs/mot/bytetrack/README_cn.md index ece152f53..2a3f8c50d 100644 --- a/configs/mot/bytetrack/README_cn.md +++ b/configs/mot/bytetrack/README_cn.md @@ -24,7 +24,11 @@ | **mix_det** | YOLOX-x | 800x1440| - | 65.4 | 84.5 | 77.4 | - |[配置文件](./bytetrack_yolox.yml) | **注意:** - - 检测任务相关配置和文档请查看[detector](detector/) + - 检测任务相关配置和文档请查看[detector](detector/)。 + - 模型权重下载链接在配置文件中的```det_weights```和```reid_weights```,运行```tools/eval_mot.py```评估的命令即可自动下载,```reid_weights```若为None则表示不需要使用。 + - **ByteTrack默认不使用ReID权重**,如需使用ReID权重,可以参考 [bytetrack_ppyoloe_pplcnet.yml](./bytetrack_ppyoloe_pplcnet.yml),如需**更换ReID权重,可改动其中的`reid_weights: `为自己的权重路径**。 + - **MOT17-half train**是MOT17的train序列(共7个)每个视频的前一半帧的图片和标注组成的数据集,而为了验证精度可以都用**MOT17-half val**数据集去评估,它是每个视频的后一半帧组成的,数据集可以从[此链接](https://bj.bcebos.com/v1/paddledet/data/mot/MOT17.zip)下载,并解压放在`dataset/mot/`文件夹下。 + - **mix_mot_ch**数据集,是MOT17、CrowdHuman组成的联合数据集,**mix_det**数据集是MOT17、CrowdHuman、Cityscapes、ETHZ组成的联合数据集,数据集整理的格式和目录可以参考[此链接](https://github.com/ifzhang/ByteTrack#data-preparation),最终放置于`dataset/mot/`目录下。为了验证精度可以都用**MOT17-half val**数据集去评估。 ### YOLOX-x ByteTrack(mix_det) @@ -34,19 +38,40 @@ | 网络 | 测试集 | MOTA | IDF1 | IDS | FP | FN | FPS | 下载链接 | 配置文件 | | :---------: | :-------: | :----: | :----: | :----: | :----: | :----: | :------: | :----: |:-----: | | ByteTrack-x| MOT-17 Train | 84.4 | 72.8 | 837 | 5653 | 10985 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | -| ByteTrack-x| MOT-17 Test | 78.4 | 69.7 | 4974 | 37551 | 79524 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | +| ByteTrack-x| **MOT-17 Test** | **78.4** | 69.7 | 4974 | 37551 | 79524 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | | ByteTrack-x| MOT-16 Train | 83.5 | 72.7 | 800 | 6973 | 10419 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | -| ByteTrack-x| MOT-16 Test | 77.7 | 70.1 | 1570 | 15695 | 23304 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | +| ByteTrack-x| **MOT-16 Test** | **77.7** | 70.1 | 1570 | 15695 | 23304 | - |[下载链接](https://paddledet.bj.bcebos.com/models/mot/yolox_x_24e_800x1440_mix_det.pdparams) | [配置文件](./bytetrack_yolox.yml) | **注意:** - - 模型权重下载链接在配置文件中的```det_weights```和```reid_weights```,运行```tools/eval_mot.py```评估的命令即可自动下载,```reid_weights```若为None则表示不需要使用,ByteTrack默认不使用ReID权重。 - - **MOT17-half train**是MOT17的train序列(共7个)每个视频的前一半帧的图片和标注组成的数据集,而为了验证精度可以都用**MOT17-half val**数据集去评估,它是每个视频的后一半帧组成的,数据集可以从[此链接](https://bj.bcebos.com/v1/paddledet/data/mot/MOT17.zip)下载,并解压放在`dataset/mot/`文件夹下。 - - **mix_mot_ch**数据集,是MOT17、CrowdHuman组成的联合数据集,**mix_det**是MOT17、CrowdHuman、Cityscapes、ETHZ组成的联合数据集,数据集整理的格式和目录可以参考[此链接](https://github.com/ifzhang/ByteTrack#data-preparation),最终放置于`dataset/mot/`目录下。为了验证精度可以都用**MOT17-half val**数据集去评估。 + - **mix_det**数据集是MOT17、CrowdHuman、Cityscapes、ETHZ组成的联合数据集,数据集整理的格式和目录可以参考[此链接](https://github.com/ifzhang/ByteTrack#data-preparation),最终放置于`dataset/mot/`目录下。 + - MOT-17 Train 和 MOT-16 Train 的指标均为本地评估该数据后的指标,由于Train集包括在了训练集中,此MOTA指标不代表模型的检测跟踪能力,只是因为MOT-17和MOT-16无验证集而它们的Train集有ground truth,是为了方便验证精度。 + - MOT-17 Test 和 MOT-16 Test 的指标均为交到 [MOTChallenge](https://motchallenge.net)官网评测后的指标,因为MOT-17和MOT-16的Test集未开放ground truth,此MOTA指标可以代表模型的检测跟踪能力。 - ByteTrack的训练是单独的检测器训练MOT数据集,推理是组装跟踪器去评估MOT指标,单独的检测模型也可以评估检测指标。 - ByteTrack的导出部署,是单独导出检测模型,再组装跟踪器运行的,参照[PP-Tracking](../../../deploy/pptracking/python/README.md)。 +## 多类别适配 + +多类别ByteTrack,可以参考 [bytetrack_ppyoloe_ppvehicle9cls.yml](./bytetrack_ppyoloe_ppvehicle9cls.yml),表示使用 [PP-Vehicle](../../ppvehicle/) 中的PPVehicle9cls数据集训好的模型权重去做多类别车辆跟踪。由于没有跟踪的ground truth标签无法做评估,故只做跟踪预测,只需修改`TestMOTDataset`确保路径存在,且其中的`anno_path`表示指定在一个`label_list.txt`中记录具体类别,需要自己手写,一行表示一个种类,注意路径`anno_path`如果写错或找不到则将默认使用COCO数据集80类的类别。 + +如需**更换检测器权重,可改动其中的`det_weights: `为自己的权重路径**,并注意**数据集路径、`label_list.txt`和类别数**做出相应更改。 + +预测多类别车辆跟踪: +```bash +# 下载demo视频 +wget https://bj.bcebos.com/v1/paddledet/data/mot/demo/bdd100k_demo.mp4 + +# 使用PPYOLOE 多类别车辆检测模型 +CUDA_VISIBLE_DEVICES=1 python tools/infer_mot.py -c configs/mot/bytetrack/bytetrack_ppyoloe_ppvehicle9cls.yml --video_file=bdd100k_demo.mp4 --scaled=True --save_videos +``` + +**注意:** + - 请先确保已经安装了[ffmpeg](https://ffmpeg.org/ffmpeg.html), Linux(Ubuntu)平台可以直接用以下命令安装:`apt-get update && apt-get install -y ffmpeg`。 + - `--scaled`表示在模型输出结果的坐标是否已经是缩放回原图的,如果使用的检测模型是JDE的YOLOv3则为False,如果使用通用检测模型则为True。 + - `--save_videos`表示保存可视化视频,同时会保存可视化的图片在`{output_dir}/mot_outputs/`中,`{output_dir}`可通过`--output_dir`设置,默认文件夹名为`output`。 + + ## 快速开始 ### 1. 训练 diff --git a/configs/mot/bytetrack/bytetrack_ppyoloe_ppvehicle9cls.yml b/configs/mot/bytetrack/bytetrack_ppyoloe_ppvehicle9cls.yml new file mode 100644 index 000000000..f847a34d1 --- /dev/null +++ b/configs/mot/bytetrack/bytetrack_ppyoloe_ppvehicle9cls.yml @@ -0,0 +1,49 @@ +# This config is an assembled config for ByteTrack MOT, used as eval/infer mode for MOT. +_BASE_: [ + 'bytetrack_ppyoloe.yml', + '_base_/ppyoloe_mot_reader_640x640.yml' +] +weights: output/bytetrack_ppyoloe_ppvehicle9cls/model_final + +metric: MCMOT # multi-class, `MOT` for single class +num_classes: 9 +# pedestrian(1), rider(2), car(3), truck(4), bus(5), van(6), motorcycle(7), bicycle(8), others(9) +TestMOTDataset: + !MOTImageFolder + dataset_dir: dataset/mot + keep_ori_im: True # set True if save visualization images or video + anno_path: dataset/mot/label_list.txt # absolute path + +### write in label_list.txt each line: +# pedestrian +# rider +# car +# truck +# bus +# van +# motorcycle +# bicycle +# others +### + +det_weights: https://paddledet.bj.bcebos.com/models/mot_ppyoloe_l_36e_ppvehicle9cls.pdparams +depth_mult: 1.0 +width_mult: 1.0 + +# Tracking requires higher quality boxes, so NMS score_threshold will be higher +PPYOLOEHead: + nms: + name: MultiClassNMS + nms_top_k: 1000 + keep_top_k: 100 + score_threshold: 0.1 # 0.01 in original detector + nms_threshold: 0.4 # 0.6 in original detector + +# BYTETracker +JDETracker: + use_byte: True + match_thres: 0.9 + conf_thres: 0.2 + low_conf_thres: 0.1 + min_box_area: 0 + vertical_ratio: 0 # only use 1.6 in MOT17 pedestrian diff --git a/ppdet/engine/tracker.py b/ppdet/engine/tracker.py index 090c72c7e..52195356d 100644 --- a/ppdet/engine/tracker.py +++ b/ppdet/engine/tracker.py @@ -32,6 +32,7 @@ from ppdet.modeling.mot.utils import MOTTimer, load_det_results, write_mot_resul from ppdet.modeling.mot.tracker import JDETracker, DeepSORTTracker, OCSORTTracker from ppdet.modeling.architectures import YOLOX from ppdet.metrics import Metric, MOTMetric, KITTIMOTMetric, MCMOTMetric +from ppdet.data.source.category import get_categories import ppdet.utils.stats as stats from .callbacks import Callback, ComposeCallback @@ -67,6 +68,13 @@ class Tracker(object): m._epsilon = 1e-3 # for amp(fp16) m._momentum = 0.97 # 0.03 in pytorch + anno_file = self.dataset.get_anno() + clsid2catid, catid2name = get_categories( + self.cfg.metric, anno_file=anno_file) + self.ids2names = [] + for k, v in catid2name.items(): + self.ids2names.append(v) + self.status = {} self.start_epoch = 0 @@ -180,7 +188,7 @@ class Tracker(object): timer.toc() save_vis_results(data, frame_id, online_ids, online_tlwhs, online_scores, timer.average_time, show_image, - save_dir, self.cfg.num_classes) + save_dir, self.cfg.num_classes, self.ids2names) frame_id += 1 return results, frame_id, timer.average_time, timer.calls @@ -290,7 +298,7 @@ class Tracker(object): online_ids, online_tlwhs, online_scores = None, None, None save_vis_results(data, frame_id, online_ids, online_tlwhs, online_scores, timer.average_time, show_image, - save_dir, self.cfg.num_classes) + save_dir, self.cfg.num_classes, self.ids2names) frame_id += 1 # thus will not inference reid model continue @@ -338,7 +346,7 @@ class Tracker(object): (frame_id + 1, online_tlwhs, online_scores, online_ids)) save_vis_results(data, frame_id, online_ids, online_tlwhs, online_scores, timer.average_time, show_image, - save_dir, self.cfg.num_classes) + save_dir, self.cfg.num_classes, self.ids2names) elif isinstance(tracker, JDETracker): # trick hyperparams only used for MOTChallenge (MOT17, MOT20) Test-set @@ -369,7 +377,7 @@ class Tracker(object): timer.toc() save_vis_results(data, frame_id, online_ids, online_tlwhs, online_scores, timer.average_time, show_image, - save_dir, self.cfg.num_classes) + save_dir, self.cfg.num_classes, self.ids2names) elif isinstance(tracker, OCSORTTracker): # OC_SORT Tracker online_targets = tracker.update(pred_dets_old, pred_embs) @@ -390,7 +398,7 @@ class Tracker(object): (frame_id + 1, online_tlwhs, online_scores, online_ids)) save_vis_results(data, frame_id, online_ids, online_tlwhs, online_scores, timer.average_time, show_image, - save_dir, self.cfg.num_classes) + save_dir, self.cfg.num_classes, self.ids2names) else: raise ValueError(tracker) frame_id += 1 diff --git a/ppdet/modeling/mot/utils.py b/ppdet/modeling/mot/utils.py index b3657d257..f19b0d96b 100644 --- a/ppdet/modeling/mot/utils.py +++ b/ppdet/modeling/mot/utils.py @@ -152,7 +152,8 @@ def save_vis_results(data, average_time, show_image, save_dir, - num_classes=1): + num_classes=1, + ids2names=[]): if show_image or save_dir is not None: assert 'ori_image' in data img0 = data['ori_image'].numpy()[0] @@ -167,7 +168,8 @@ def save_vis_results(data, online_ids, online_scores, frame_id=frame_id, - fps=1. / average_time) + fps=1. / average_time, + ids2names=ids2names) else: online_im = plot_tracking( img0, @@ -175,7 +177,8 @@ def save_vis_results(data, online_ids, online_scores, frame_id=frame_id, - fps=1. / average_time) + fps=1. / average_time, + ids2names=ids2names) if show_image: cv2.imshow('online_im', online_im) if save_dir is not None: -- GitLab