未验证 提交 c643eeab 编写于 作者: F Feng Ni 提交者: GitHub

[MOT] Upgrade pptracking deploy (#5358)

* add bytetrack yolov3 engine and deploy baseline

* fix bytetrack yolov3 configs

* fix cfgs tools

* fix tracker pred_dets

* fit pptracking jde sde infer

* rename cfgs, fix mot_sde_infer

* fix mot sde single class infer

* remove byte cfgs

* fix mtmct

* clean code
上级 cff6841a
...@@ -58,11 +58,12 @@ python deploy/pptracking/python/mot_jde_infer.py --model_dir=output_inference/fa ...@@ -58,11 +58,12 @@ python deploy/pptracking/python/mot_jde_infer.py --model_dir=output_inference/fa
### 2.1 导出预测模型 ### 2.1 导出预测模型
Step 1:导出检测模型 Step 1:导出检测模型
```bash ```bash
# 导出JDE YOLOv3行人检测模型 # 导出PPYOLOv2行人检测模型
CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/detector/jde_yolov3_darknet53_30e_1088x608_mix.yml -o weights=https://paddledet.bj.bcebos.com/models/mot/deepsort/jde_yolov3_darknet53_30e_1088x608_mix.pdparams
# 或导出PPYOLOv2行人检测模型
CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/detector/ppyolov2_r50vd_dcn_365e_640x640_mot17half.yml -o weights=https://paddledet.bj.bcebos.com/models/mot/deepsort/ppyolov2_r50vd_dcn_365e_640x640_mot17half.pdparams CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/detector/ppyolov2_r50vd_dcn_365e_640x640_mot17half.yml -o weights=https://paddledet.bj.bcebos.com/models/mot/deepsort/ppyolov2_r50vd_dcn_365e_640x640_mot17half.pdparams
# 或导出PPYOLOe行人检测模型
CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/detector/ppyoloe_crn_l_36e_640x640_mot17half.yml -o weights=https://paddledet.bj.bcebos.com/models/mot/deepsort/ppyoloe_crn_l_36e_640x640_mot17half.pdparams
``` ```
Step 2:导出行人ReID模型 Step 2:导出行人ReID模型
```bash ```bash
# 导出PCB Pyramid ReID模型 # 导出PCB Pyramid ReID模型
...@@ -76,11 +77,10 @@ CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/reid ...@@ -76,11 +77,10 @@ CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/mot/deepsort/reid
# 下载行人跟踪demo视频: # 下载行人跟踪demo视频:
wget https://bj.bcebos.com/v1/paddledet/data/mot/demo/mot17_demo.mp4 wget https://bj.bcebos.com/v1/paddledet/data/mot/demo/mot17_demo.mp4
# 用导出的JDE YOLOv3行人检测模型和PCB Pyramid ReID模型 # 用导出的PPYOLOv2行人检测模型和PPLCNet ReID模型
python deploy/pptracking/python/mot_sde_infer.py --model_dir=output_inference/jde_yolov3_darknet53_30e_1088x608_mix/ --reid_model_dir=output_inference/deepsort_pcb_pyramid_r101/ --video_file=mot17_demo.mp4 --device=GPU --threshold=0.5 --save_mot_txts --save_images python deploy/pptracking/python/mot_sde_infer.py --model_dir=output_inference/ppyolov2_r50vd_dcn_365e_640x640_mot17half/ --reid_model_dir=output_inference/deepsort_pplcnet/ --video_file=mot17_demo.mp4 --device=GPU --threshold=0.5 --save_mot_txts --save_images
# 或用导出的PPYOLOe行人检测模型和PPLCNet ReID模型
# 或用导出的PPYOLOv2行人检测模型和PPLCNet ReID模型 python deploy/pptracking/python/mot_sde_infer.py --model_dir=output_inference/ppyoloe_crn_l_36e_640x640_mot17half/ --reid_model_dir=output_inference/deepsort_pplcnet/ --video_file=mot17_demo.mp4 --device=GPU --threshold=0.5 --save_mot_txts --save_images
python deploy/pptracking/python/mot_sde_infer.py --model_dir=output_inference/ppyolov2_r50vd_dcn_365e_640x640_mot17half/ --reid_model_dir=output_inference/deepsort_pplcnet/ --video_file=mot17_demo.mp4 --device=GPU --threshold=0.5 --scaled=True --save_mot_txts --save_images
``` ```
### 2.3 用导出的模型基于Python去预测车辆跟踪 ### 2.3 用导出的模型基于Python去预测车辆跟踪
...@@ -97,17 +97,16 @@ wget https://paddledet.bj.bcebos.com/models/mot/deepsort/deepsort_pplcnet_vehicl ...@@ -97,17 +97,16 @@ wget https://paddledet.bj.bcebos.com/models/mot/deepsort/deepsort_pplcnet_vehicl
tar -xvf deepsort_pplcnet_vehicle.tar tar -xvf deepsort_pplcnet_vehicle.tar
# 用导出的PicoDet车辆检测模型和PPLCNet车辆ReID模型 # 用导出的PicoDet车辆检测模型和PPLCNet车辆ReID模型
python deploy/pptracking/python/mot_sde_infer.py --model_dir=picodet_l_640_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --device=GPU --scaled=True --threshold=0.5 --video_file={your video}.mp4 --save_mot_txts --save_images python deploy/pptracking/python/mot_sde_infer.py --model_dir=picodet_l_640_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --device=GPU --threshold=0.5 --video_file={your video}.mp4 --save_mot_txts --save_images
# 用导出的PP-YOLOv2车辆检测模型和PPLCNet车辆ReID模型 # 用导出的PP-YOLOv2车辆检测模型和PPLCNet车辆ReID模型
python deploy/pptracking/python/mot_sde_infer.py --model_dir=ppyolov2_r50vd_dcn_365e_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --device=GPU --scaled=True --threshold=0.5 --video_file={your video}.mp4 --save_mot_txts --save_images python deploy/pptracking/python/mot_sde_infer.py --model_dir=ppyolov2_r50vd_dcn_365e_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --device=GPU --threshold=0.5 --video_file={your video}.mp4 --save_mot_txts --save_images
``` ```
**注意:** **注意:**
- 跟踪模型是对视频进行预测,不支持单张图的预测,默认保存跟踪结果可视化后的视频,可添加`--save_mot_txts`(对每个视频保存一个txt)或`--save_images`表示保存跟踪结果可视化图片。 - 跟踪模型是对视频进行预测,不支持单张图的预测,默认保存跟踪结果可视化后的视频,可添加`--save_mot_txts`(对每个视频保存一个txt)或`--save_images`表示保存跟踪结果可视化图片。
- 跟踪结果txt文件每行信息是`frame,id,x1,y1,w,h,score,-1,-1,-1` - 跟踪结果txt文件每行信息是`frame,id,x1,y1,w,h,score,-1,-1,-1`
- `--threshold`表示结果可视化的置信度阈值,默认为0.5,低于该阈值的结果会被过滤掉,为了可视化效果更佳,可根据实际情况自行修改。 - `--threshold`表示结果可视化的置信度阈值,默认为0.5,低于该阈值的结果会被过滤掉,为了可视化效果更佳,可根据实际情况自行修改。
- `--scaled`表示在模型输出结果的坐标是否已经是缩放回原图的,如果使用的检测模型是JDE的YOLOv3则为False,如果使用通用检测模型则为True。
- DeepSORT算法不支持多类别跟踪,只支持单类别跟踪,且ReID模型最好是与检测模型同一类别的物体训练过的,比如行人跟踪最好使用行人ReID模型,车辆跟踪最好使用车辆ReID模型。 - DeepSORT算法不支持多类别跟踪,只支持单类别跟踪,且ReID模型最好是与检测模型同一类别的物体训练过的,比如行人跟踪最好使用行人ReID模型,车辆跟踪最好使用车辆ReID模型。
...@@ -135,94 +134,22 @@ wget https://paddledet.bj.bcebos.com/data/mot/demo/mtmct-demo.tar ...@@ -135,94 +134,22 @@ wget https://paddledet.bj.bcebos.com/data/mot/demo/mtmct-demo.tar
tar -xvf mtmct-demo.tar tar -xvf mtmct-demo.tar
# 用导出的PicoDet车辆检测模型和PPLCNet车辆ReID模型 # 用导出的PicoDet车辆检测模型和PPLCNet车辆ReID模型
python deploy/pptracking/python/mot_sde_infer.py --model_dir=picodet_l_640_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --mtmct_dir=mtmct-demo --mtmct_cfg=mtmct_cfg --device=GPU --scaled=True --threshold=0.5 --save_mot_txts --save_images python deploy/pptracking/python/mot_sde_infer.py --model_dir=picodet_l_640_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --mtmct_dir=mtmct-demo --mtmct_cfg=mtmct_cfg.yml --device=GPU --threshold=0.5 --save_mot_txts --save_images
# 用导出的PP-YOLOv2车辆检测模型和PPLCNet车辆ReID模型 # 用导出的PP-YOLOv2车辆检测模型和PPLCNet车辆ReID模型
python deploy/pptracking/python/mot_sde_infer.py --model_dir=ppyolov2_r50vd_dcn_365e_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --mtmct_dir=mtmct-demo --mtmct_cfg=mtmct_cfg --device=GPU --scaled=True --threshold=0.5 --save_mot_txts --save_images python deploy/pptracking/python/mot_sde_infer.py --model_dir=ppyolov2_r50vd_dcn_365e_aic21mtmct_vehicle/ --reid_model_dir=deepsort_pplcnet_vehicle/ --mtmct_dir=mtmct-demo --mtmct_cfg=mtmct_cfg.yml --device=GPU --threshold=0.5 --save_mot_txts --save_images
``` ```
**注意:** **注意:**
- 跟踪模型是对视频进行预测,不支持单张图的预测,默认保存跟踪结果可视化后的视频,可添加`--save_mot_txts`(对每个视频保存一个txt),或`--save_images`表示保存跟踪结果可视化图片。 - 跟踪模型是对视频进行预测,不支持单张图的预测,默认保存跟踪结果可视化后的视频,可添加`--save_mot_txts`(对每个视频保存一个txt),或`--save_images`表示保存跟踪结果可视化图片。
- 跨镜头跟踪结果txt文件每行信息是`camera_id,frame,id,x1,y1,w,h,-1,-1` - 跨镜头跟踪结果txt文件每行信息是`camera_id,frame,id,x1,y1,w,h,-1,-1`
- `--threshold`表示结果可视化的置信度阈值,默认为0.5,低于该阈值的结果会被过滤掉,为了可视化效果更佳,可根据实际情况自行修改。 - `--threshold`表示结果可视化的置信度阈值,默认为0.5,低于该阈值的结果会被过滤掉,为了可视化效果更佳,可根据实际情况自行修改。
- `--scaled`表示在模型输出结果的坐标是否已经是缩放回原图的,如果使用的检测模型是JDE的YOLOv3则为False,如果使用通用检测模型则为True。
- DeepSORT算法不支持多类别跟踪,只支持单类别跟踪,且ReID模型最好是与检测模型同一类别的物体训练过的,比如行人跟踪最好使用行人ReID模型,车辆跟踪最好使用车辆ReID模型。 - DeepSORT算法不支持多类别跟踪,只支持单类别跟踪,且ReID模型最好是与检测模型同一类别的物体训练过的,比如行人跟踪最好使用行人ReID模型,车辆跟踪最好使用车辆ReID模型。
- `--mtmct_dir`是MTMCT预测的某个场景的文件夹名字,里面包含该场景不同摄像头拍摄视频的图片文件夹,其数量至少为两个。 - `--mtmct_dir`是MTMCT预测的某个场景的文件夹名字,里面包含该场景不同摄像头拍摄视频的图片文件夹,其数量至少为两个。
- `--mtmct_cfg`是MTMCT预测的某个场景的配置文件,里面包含该一些trick操作的开关和该场景摄像头相关设置的文件路径,用户可以自行更改相关路径以及设置某些操作是否启用。 - `--mtmct_cfg`是MTMCT预测的某个场景的配置文件,里面包含该一些trick操作的开关和该场景摄像头相关设置的文件路径,用户可以自行更改相关路径以及设置某些操作是否启用。
## 4. API调用方式: ## 4. 参数说明:
### 4.1 FairMOT模型API调用
```
import mot_jde_infer
# 1.model config and weights
model_dir = 'fairmot_hrnetv2_w18_dlafpn_30e_576x320/'
# 2.inference data
video_file = 'test.mp4'
image_dir = None
# 3.other settings
device = 'CPU' # device should be CPU, GPU or XPU
threshold = 0.3
output_dir = 'output'
# mot predict
mot_jde_infer.predict_naive(model_dir, video_file, image_dir, device, threshold, output_dir)
```
**注意:**
- 以上代码必须进入目录`PaddleDetection/deploy/pptracking/python`下执行。
- 支持对视频和图片文件夹进行预测,不支持单张图的预测,`video_file``image_dir`不能同时为None,推荐使用`video_file`,而`image_dir`需直接存放命名顺序规范的图片。
- 默认会保存跟踪结果可视化后的图片和视频,以及跟踪结果txt文件,默认不会进行轨迹可视化和流量统计。
### 4.2 DeepSORT模型API调用
```
import mot_sde_infer
# 1.model config and weights
model_dir = 'ppyolov2_r50vd_dcn_365e_aic21mtmct_vehicle/'
reid_model_dir = 'deepsort_pplcnet_vehicle/'
# 2.inference data
video_file = 'test.mp4'
image_dir = None
# 3.other settings
scaled = True # set False only when use JDE YOLOv3
device = 'CPU' # device should be CPU, GPU or XPU
threshold = 0.3
output_dir = 'output'
# 4. MTMCT settings, default None
mtmct_dir = None
mtmct_cfg = None
# mot predict
mot_sde_infer.predict_naive(model_dir,
reid_model_dir,
video_file,
image_dir,
mtmct_dir,
mtmct_cfg,
scaled,
device,
threshold,
output_dir)
```
**注意:**
- 以上代码必须进入目录`PaddleDetection/deploy/pptracking/python`下执行。
- 支持对视频和图片文件夹进行预测,不支持单张图的预测,`video_file``image_dir``--mtmct_dir`不能同时为None,推荐使用`video_file`,而`image_dir`需直接存放命名顺序规范的图片,`--mtmct_dir`不为None表示是进行的MTMCT跨镜头跟踪任务。
- 默认会保存跟踪结果可视化后的图片和视频,以及跟踪结果txt文件,默认不会进行轨迹可视化和流量统计。
- `--scaled`表示在模型输出结果的坐标是否已经是缩放回原图的,如果使用的检测模型是JDE的YOLOv3则为False,如果使用通用检测模型则为True。
- `--mtmct_dir`是MTMCT预测的某个场景的文件夹名字,里面包含该场景不同摄像头拍摄视频的图片文件夹,其数量至少为两个。
- `--mtmct_cfg`是MTMCT预测的某个场景的配置文件,里面包含该一些trick操作的开关和该场景摄像头相关设置的文件路径,用户可以自行更改相关路径以及设置某些操作是否启用。
- 开启MTMCT预测必须将`video_file``image_dir`同时设置为None,且`--mtmct_dir``--mtmct_cfg`都必须不为None。
## 5. 参数说明:
| 参数 | 是否必须|含义 | | 参数 | 是否必须|含义 |
|-------|-------|----------| |-------|-------|----------|
......
...@@ -89,6 +89,8 @@ class PaddleInferBenchmark(object): ...@@ -89,6 +89,8 @@ class PaddleInferBenchmark(object):
self.preprocess_time_s = perf_info.get('preprocess_time_s', 0) self.preprocess_time_s = perf_info.get('preprocess_time_s', 0)
self.postprocess_time_s = perf_info.get('postprocess_time_s', 0) self.postprocess_time_s = perf_info.get('postprocess_time_s', 0)
self.with_tracker = True if 'tracking_time_s' in perf_info else False
self.tracking_time_s = perf_info.get('tracking_time_s', 0)
self.total_time_s = perf_info.get('total_time_s', 0) self.total_time_s = perf_info.get('total_time_s', 0)
self.inference_time_s_90 = perf_info.get("inference_time_s_90", "") self.inference_time_s_90 = perf_info.get("inference_time_s_90", "")
...@@ -235,9 +237,19 @@ class PaddleInferBenchmark(object): ...@@ -235,9 +237,19 @@ class PaddleInferBenchmark(object):
) )
self.logger.info( self.logger.info(
f"{identifier} total time spent(s): {self.total_time_s}") f"{identifier} total time spent(s): {self.total_time_s}")
self.logger.info(
f"{identifier} preprocess_time(ms): {round(self.preprocess_time_s*1000, 1)}, inference_time(ms): {round(self.inference_time_s*1000, 1)}, postprocess_time(ms): {round(self.postprocess_time_s*1000, 1)}" if self.with_tracker:
) self.logger.info(
f"{identifier} preprocess_time(ms): {round(self.preprocess_time_s*1000, 1)}, "
f"inference_time(ms): {round(self.inference_time_s*1000, 1)}, "
f"postprocess_time(ms): {round(self.postprocess_time_s*1000, 1)}, "
f"tracking_time(ms): {round(self.tracking_time_s*1000, 1)}")
else:
self.logger.info(
f"{identifier} preprocess_time(ms): {round(self.preprocess_time_s*1000, 1)}, "
f"inference_time(ms): {round(self.inference_time_s*1000, 1)}, "
f"postprocess_time(ms): {round(self.postprocess_time_s*1000, 1)}"
)
if self.inference_time_s_90: if self.inference_time_s_90:
self.looger.info( self.looger.info(
f"{identifier} 90%_cost: {self.inference_time_s_90}, 99%_cost: {self.inference_time_s_99}, succ_rate: {self.succ_rate}" f"{identifier} 90%_cost: {self.inference_time_s_90}, 99%_cost: {self.inference_time_s_99}, succ_rate: {self.succ_rate}"
......
...@@ -96,7 +96,8 @@ class DeepSORTTracker(object): ...@@ -96,7 +96,8 @@ class DeepSORTTracker(object):
""" """
pred_cls_ids = pred_dets[:, 0:1] pred_cls_ids = pred_dets[:, 0:1]
pred_scores = pred_dets[:, 1:2] pred_scores = pred_dets[:, 1:2]
pred_tlwhs = pred_dets[:, 2:6] pred_xyxys = pred_dets[:, 2:6]
pred_tlwhs = np.concatenate((pred_xyxys[:, 0:2], pred_xyxys[:, 2:4] - pred_xyxys[:, 0:2] + 1), axis=1)
detections = [ detections = [
Detection(tlwh, score, feat, cls_id) Detection(tlwh, score, feat, cls_id)
......
...@@ -182,8 +182,7 @@ def clip_box(xyxy, ori_image_shape): ...@@ -182,8 +182,7 @@ def clip_box(xyxy, ori_image_shape):
def get_crops(xyxy, ori_img, w, h): def get_crops(xyxy, ori_img, w, h):
crops = [] crops = []
xyxy = xyxy.astype(np.int64) xyxy = xyxy.astype(np.int64)
ori_img = ori_img.numpy() ori_img = ori_img.transpose(1, 0, 2) # [h,w,3]->[w,h,3]
ori_img = np.squeeze(ori_img, axis=0).transpose(1, 0, 2) # [h,w,3]->[w,h,3]
for i, bbox in enumerate(xyxy): for i, bbox in enumerate(xyxy):
crop = ori_img[bbox[0]:bbox[2], bbox[1]:bbox[3], :] crop = ori_img[bbox[0]:bbox[2], bbox[1]:bbox[3], :]
crops.append(crop) crops.append(crop)
...@@ -198,7 +197,10 @@ def preprocess_reid(imgs, ...@@ -198,7 +197,10 @@ def preprocess_reid(imgs,
std=[0.229, 0.224, 0.225]): std=[0.229, 0.224, 0.225]):
im_batch = [] im_batch = []
for img in imgs: for img in imgs:
img = cv2.resize(img, (w, h)) try:
img = cv2.resize(img, (w, h))
except:
embed()
img = img[:, :, ::-1].astype('float32').transpose((2, 0, 1)) / 255 img = img[:, :, ::-1].astype('float32').transpose((2, 0, 1)) / 255
img_mean = np.array(mean).reshape((3, 1, 1)) img_mean = np.array(mean).reshape((3, 1, 1))
img_std = np.array(std).reshape((3, 1, 1)) img_std = np.array(std).reshape((3, 1, 1))
......
# config of tracker for MOT SDE Detector, use ByteTracker as default.
# The tracker of MOT JDE Detector is exported together with the model.
# Here 'min_box_area' and 'vertical_ratio' are set for pedestrian, you can modify for other objects tracking.
tracker:
use_byte: true
conf_thres: 0.6
low_conf_thres: 0.1
match_thres: 0.9
min_box_area: 100
vertical_ratio: 1.6
...@@ -66,6 +66,11 @@ def argsparser(): ...@@ -66,6 +66,11 @@ def argsparser():
default='cpu', default='cpu',
help="Choose the device you want to run, it can be: CPU/GPU/XPU, default is CPU." help="Choose the device you want to run, it can be: CPU/GPU/XPU, default is CPU."
) )
parser.add_argument(
"--use_gpu",
type=ast.literal_eval,
default=False,
help="Deprecated, please use `--device`.")
parser.add_argument( parser.add_argument(
"--run_benchmark", "--run_benchmark",
type=ast.literal_eval, type=ast.literal_eval,
...@@ -104,12 +109,18 @@ def argsparser(): ...@@ -104,12 +109,18 @@ def argsparser():
'--save_mot_txts', '--save_mot_txts',
action='store_true', action='store_true',
help='Save tracking results (txt).') help='Save tracking results (txt).')
parser.add_argument(
'--save_mot_txt_per_img',
action='store_true',
help='Save tracking results (txt) for each image.')
parser.add_argument( parser.add_argument(
'--scaled', '--scaled',
type=bool, type=bool,
default=False, default=False,
help="Whether coords after detector outputs are scaled, False in JDE YOLOv3 " help="Whether coords after detector outputs are scaled, False in JDE YOLOv3 "
"True in general detector.") "True in general detector.")
parser.add_argument(
"--tracker_config", type=str, default=None, help=("tracker donfig"))
parser.add_argument( parser.add_argument(
"--reid_model_dir", "--reid_model_dir",
type=str, type=str,
...@@ -122,20 +133,10 @@ def argsparser(): ...@@ -122,20 +133,10 @@ def argsparser():
default=50, default=50,
help="max batch_size for reid model inference.") help="max batch_size for reid model inference.")
parser.add_argument( parser.add_argument(
"--do_entrance_counting", '--use_dark',
action='store_true', type=ast.literal_eval,
help="Whether counting the numbers of identifiers entering " default=True,
"or getting out from the entrance. Note that only support one-class" help='whether to use darkpose to get better keypoint position predict ')
"counting, multi-class counting is coming soon.")
parser.add_argument(
"--secs_interval",
type=int,
default=2,
help="The seconds interval to count after tracking")
parser.add_argument(
"--draw_center_traj",
action='store_true',
help="Whether drawing the trajectory of center")
parser.add_argument( parser.add_argument(
"--mtmct_dir", "--mtmct_dir",
type=str, type=str,
...@@ -146,6 +147,7 @@ def argsparser(): ...@@ -146,6 +147,7 @@ def argsparser():
return parser return parser
class Times(object): class Times(object):
def __init__(self): def __init__(self):
self.time = 0. self.time = 0.
...@@ -174,29 +176,36 @@ class Times(object): ...@@ -174,29 +176,36 @@ class Times(object):
class Timer(Times): class Timer(Times):
def __init__(self): def __init__(self, with_tracker=False):
super(Timer, self).__init__() super(Timer, self).__init__()
self.with_tracker = with_tracker
self.preprocess_time_s = Times() self.preprocess_time_s = Times()
self.inference_time_s = Times() self.inference_time_s = Times()
self.postprocess_time_s = Times() self.postprocess_time_s = Times()
self.tracking_time_s = Times()
self.img_num = 0 self.img_num = 0
def info(self, average=False): def info(self, average=False):
total_time = self.preprocess_time_s.value( pre_time = self.preprocess_time_s.value()
) + self.inference_time_s.value() + self.postprocess_time_s.value() infer_time = self.inference_time_s.value()
post_time = self.postprocess_time_s.value()
track_time = self.tracking_time_s.value()
total_time = pre_time + infer_time + post_time
if self.with_tracker:
total_time = total_time + track_time
total_time = round(total_time, 4) total_time = round(total_time, 4)
print("------------------ Inference Time Info ----------------------") print("------------------ Inference Time Info ----------------------")
print("total_time(ms): {}, img_num: {}".format(total_time * 1000, print("total_time(ms): {}, img_num: {}".format(total_time * 1000,
self.img_num)) self.img_num))
preprocess_time = round( preprocess_time = round(pre_time / max(1, self.img_num),
self.preprocess_time_s.value() / max(1, self.img_num), 4) if average else pre_time
4) if average else self.preprocess_time_s.value() postprocess_time = round(post_time / max(1, self.img_num),
postprocess_time = round( 4) if average else post_time
self.postprocess_time_s.value() / max(1, self.img_num), inference_time = round(infer_time / max(1, self.img_num),
4) if average else self.postprocess_time_s.value() 4) if average else infer_time
inference_time = round(self.inference_time_s.value() / tracking_time = round(track_time / max(1, self.img_num),
max(1, self.img_num), 4) if average else track_time
4) if average else self.inference_time_s.value()
average_latency = total_time / max(1, self.img_num) average_latency = total_time / max(1, self.img_num)
qps = 0 qps = 0
...@@ -204,25 +213,36 @@ class Timer(Times): ...@@ -204,25 +213,36 @@ class Timer(Times):
qps = 1 / average_latency qps = 1 / average_latency
print("average latency time(ms): {:.2f}, QPS: {:2f}".format( print("average latency time(ms): {:.2f}, QPS: {:2f}".format(
average_latency * 1000, qps)) average_latency * 1000, qps))
print( if self.with_tracker:
"preprocess_time(ms): {:.2f}, inference_time(ms): {:.2f}, postprocess_time(ms): {:.2f}". print(
format(preprocess_time * 1000, inference_time * 1000, "preprocess_time(ms): {:.2f}, inference_time(ms): {:.2f}, postprocess_time(ms): {:.2f}, tracking_time(ms): {:.2f}".
postprocess_time * 1000)) format(preprocess_time * 1000, inference_time * 1000,
postprocess_time * 1000, tracking_time * 1000))
else:
print(
"preprocess_time(ms): {:.2f}, inference_time(ms): {:.2f}, postprocess_time(ms): {:.2f}".
format(preprocess_time * 1000, inference_time * 1000,
postprocess_time * 1000))
def report(self, average=False): def report(self, average=False):
dic = {} dic = {}
dic['preprocess_time_s'] = round( pre_time = self.preprocess_time_s.value()
self.preprocess_time_s.value() / max(1, self.img_num), infer_time = self.inference_time_s.value()
4) if average else self.preprocess_time_s.value() post_time = self.postprocess_time_s.value()
dic['postprocess_time_s'] = round( track_time = self.tracking_time_s.value()
self.postprocess_time_s.value() / max(1, self.img_num),
4) if average else self.postprocess_time_s.value() dic['preprocess_time_s'] = round(pre_time / max(1, self.img_num),
dic['inference_time_s'] = round( 4) if average else pre_time
self.inference_time_s.value() / max(1, self.img_num), dic['inference_time_s'] = round(infer_time / max(1, self.img_num),
4) if average else self.inference_time_s.value() 4) if average else infer_time
dic['postprocess_time_s'] = round(post_time / max(1, self.img_num),
4) if average else post_time
dic['img_num'] = self.img_num dic['img_num'] = self.img_num
total_time = self.preprocess_time_s.value( total_time = pre_time + infer_time + post_time
) + self.inference_time_s.value() + self.postprocess_time_s.value() if self.with_tracker:
dic['tracking_time_s'] = round(track_time / max(1, self.img_num),
4) if average else track_time
total_time = total_time + track_time
dic['total_time_s'] = round(total_time, 4) dic['total_time_s'] = round(total_time, 4)
return dic return dic
......
...@@ -31,7 +31,7 @@ sys.path.insert(0, parent_path) ...@@ -31,7 +31,7 @@ sys.path.insert(0, parent_path)
from benchmark_utils import PaddleInferBenchmark from benchmark_utils import PaddleInferBenchmark
from picodet_postprocess import PicoDetPostProcess from picodet_postprocess import PicoDetPostProcess
from preprocess import preprocess, Resize, NormalizeImage, Permute, PadStride, LetterBoxResize, WarpAffine from preprocess import preprocess, Resize, NormalizeImage, Permute, PadStride, LetterBoxResize, WarpAffine, decode_image
from keypoint_preprocess import EvalAffine, TopDownEvalAffine, expand_crop from keypoint_preprocess import EvalAffine, TopDownEvalAffine, expand_crop
from visualize import visualize_box_mask from visualize import visualize_box_mask
from utils import argsparser, Timer, get_current_memory_mb from utils import argsparser, Timer, get_current_memory_mb
......
...@@ -25,7 +25,7 @@ from collections import defaultdict ...@@ -25,7 +25,7 @@ from collections import defaultdict
from mot_keypoint_unite_utils import argsparser from mot_keypoint_unite_utils import argsparser
from preprocess import decode_image from preprocess import decode_image
from infer import print_arguments, get_test_images from infer import print_arguments, get_test_images
from mot_sde_infer import SDE_Detector, MOT_SDE_SUPPORT_MODELS from mot_sde_infer import SDE_Detector
from mot_jde_infer import JDE_Detector, MOT_JDE_SUPPORT_MODELS from mot_jde_infer import JDE_Detector, MOT_JDE_SUPPORT_MODELS
from keypoint_infer import KeyPointDetector, KEYPOINT_SUPPORT_MODELS from keypoint_infer import KeyPointDetector, KEYPOINT_SUPPORT_MODELS
from det_keypoint_unite_infer import predict_with_given_det from det_keypoint_unite_infer import predict_with_given_det
......
...@@ -34,13 +34,6 @@ from pptracking.python.mot import JDETracker ...@@ -34,13 +34,6 @@ from pptracking.python.mot import JDETracker
from pptracking.python.mot.utils import MOTTimer, write_mot_results from pptracking.python.mot.utils import MOTTimer, write_mot_results
from pptracking.python.visualize import plot_tracking, plot_tracking_dict from pptracking.python.visualize import plot_tracking, plot_tracking_dict
# Global dictionary
MOT_SDE_SUPPORT_MODELS = {
'DeepSORT',
'ByteTrack',
'YOLO',
}
class SDE_Detector(Detector): class SDE_Detector(Detector):
""" """
...@@ -287,7 +280,6 @@ def main(): ...@@ -287,7 +280,6 @@ def main():
with open(deploy_file) as f: with open(deploy_file) as f:
yml_conf = yaml.safe_load(f) yml_conf = yaml.safe_load(f)
arch = yml_conf['arch'] arch = yml_conf['arch']
assert arch in MOT_SDE_SUPPORT_MODELS, '{} is not supported.'.format(arch)
detector = SDE_Detector( detector = SDE_Detector(
FLAGS.model_dir, FLAGS.model_dir,
FLAGS.tracker_config, FLAGS.tracker_config,
......
...@@ -228,11 +228,11 @@ class Timer(Times): ...@@ -228,11 +228,11 @@ class Timer(Times):
4) if average else infer_time 4) if average else infer_time
dic['postprocess_time_s'] = round(post_time / max(1, self.img_num), dic['postprocess_time_s'] = round(post_time / max(1, self.img_num),
4) if average else post_time 4) if average else post_time
dic['tracking_time_s'] = round(post_time / max(1, self.img_num),
4) if average else track_time
dic['img_num'] = self.img_num dic['img_num'] = self.img_num
total_time = pre_time + infer_time + post_time total_time = pre_time + infer_time + post_time
if self.with_tracker: if self.with_tracker:
dic['tracking_time_s'] = round(track_time / max(1, self.img_num),
4) if average else track_time
total_time = total_time + track_time total_time = total_time + track_time
dic['total_time_s'] = round(total_time, 4) dic['total_time_s'] = round(total_time, 4)
return dic return dic
......
# coding: utf-8 # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
......
...@@ -41,6 +41,7 @@ TRT_MIN_SUBGRAPH = { ...@@ -41,6 +41,7 @@ TRT_MIN_SUBGRAPH = {
'HigherHRNet': 3, 'HigherHRNet': 3,
'HRNet': 3, 'HRNet': 3,
'DeepSORT': 3, 'DeepSORT': 3,
'ByteTrack':10,
'JDE': 10, 'JDE': 10,
'FairMOT': 5, 'FairMOT': 5,
'GFL': 16, 'GFL': 16,
...@@ -50,7 +51,7 @@ TRT_MIN_SUBGRAPH = { ...@@ -50,7 +51,7 @@ TRT_MIN_SUBGRAPH = {
} }
KEYPOINT_ARCH = ['HigherHRNet', 'TopDownHRNet'] KEYPOINT_ARCH = ['HigherHRNet', 'TopDownHRNet']
MOT_ARCH = ['DeepSORT', 'JDE', 'FairMOT'] MOT_ARCH = ['DeepSORT', 'JDE', 'FairMOT', 'ByteTrack']
def _prune_input_spec(input_spec, program, targets): def _prune_input_spec(input_spec, program, targets):
......
...@@ -29,6 +29,7 @@ from ppdet.core.workspace import create ...@@ -29,6 +29,7 @@ from ppdet.core.workspace import create
from ppdet.utils.checkpoint import load_weight, load_pretrain_weight from ppdet.utils.checkpoint import load_weight, load_pretrain_weight
from ppdet.modeling.mot.utils import Detection, get_crops, scale_coords, clip_box from ppdet.modeling.mot.utils import Detection, get_crops, scale_coords, clip_box
from ppdet.modeling.mot.utils import MOTTimer, load_det_results, write_mot_results, save_vis_results from ppdet.modeling.mot.utils import MOTTimer, load_det_results, write_mot_results, save_vis_results
from ppdet.modeling.mot.tracker import JDETracker, DeepSORTTracker
from ppdet.metrics import Metric, MOTMetric, KITTIMOTMetric from ppdet.metrics import Metric, MOTMetric, KITTIMOTMetric
from ppdet.metrics import MCMOTMetric from ppdet.metrics import MCMOTMetric
...@@ -39,6 +40,11 @@ from .callbacks import Callback, ComposeCallback ...@@ -39,6 +40,11 @@ from .callbacks import Callback, ComposeCallback
from ppdet.utils.logger import setup_logger from ppdet.utils.logger import setup_logger
logger = setup_logger(__name__) logger = setup_logger(__name__)
MOT_ARCH = ['DeepSORT', 'JDE', 'FairMOT', 'ByteTrack']
MOT_ARCH_JDE = ['JDE', 'FairMOT']
MOT_ARCH_SDE = ['DeepSORT', 'ByteTrack']
MOT_DATA_TYPE = ['mot', 'mcmot', 'kitti']
__all__ = ['Tracker'] __all__ = ['Tracker']
...@@ -109,11 +115,15 @@ class Tracker(object): ...@@ -109,11 +115,15 @@ class Tracker(object):
load_weight(self.model, weights, self.optimizer) load_weight(self.model, weights, self.optimizer)
def load_weights_sde(self, det_weights, reid_weights): def load_weights_sde(self, det_weights, reid_weights):
if self.model.detector: with_detector = self.model.detector is not None
load_weight(self.model.detector, det_weights) with_reid = self.model.reid is not None
load_weight(self.model.reid, reid_weights)
if with_detector:
load_weight(self.model.detector, det_weights, self.optimizer)
if with_reid:
load_weight(self.model.reid, reid_weights)
else: else:
load_weight(self.model.reid, reid_weights, self.optimizer) load_weight(self.model.reid, reid_weights)
def _eval_seq_jde(self, def _eval_seq_jde(self,
dataloader, dataloader,
...@@ -185,18 +195,21 @@ class Tracker(object): ...@@ -185,18 +195,21 @@ class Tracker(object):
if save_dir: if save_dir:
if not os.path.exists(save_dir): os.makedirs(save_dir) if not os.path.exists(save_dir): os.makedirs(save_dir)
use_detector = False if not self.model.detector else True use_detector = False if not self.model.detector else True
use_reid = False if not self.model.reid else True
timer = MOTTimer() timer = MOTTimer()
results = defaultdict(list) results = defaultdict(list)
frame_id = 0 frame_id = 0
self.status['mode'] = 'track' self.status['mode'] = 'track'
self.model.eval() self.model.eval()
self.model.reid.eval() if use_reid:
self.model.reid.eval()
if not use_detector: if not use_detector:
dets_list = load_det_results(det_file, len(dataloader)) dets_list = load_det_results(det_file, len(dataloader))
logger.info('Finish loading detection results file {}.'.format( logger.info('Finish loading detection results file {}.'.format(
det_file)) det_file))
tracker = self.model.tracker
for step_id, data in enumerate(dataloader): for step_id, data in enumerate(dataloader):
self.status['step_id'] = step_id self.status['step_id'] = step_id
if frame_id % 40 == 0: if frame_id % 40 == 0:
...@@ -257,6 +270,8 @@ class Tracker(object): ...@@ -257,6 +270,8 @@ class Tracker(object):
scale_factor) scale_factor)
else: else:
pred_bboxes = outs['bbox'][:, 2:] pred_bboxes = outs['bbox'][:, 2:]
pred_dets_old = np.concatenate(
(pred_cls_ids, pred_scores, pred_bboxes), axis=1)
else: else:
logger.warning( logger.warning(
'Frame {} has not detected object, try to modify score threshold.'. 'Frame {} has not detected object, try to modify score threshold.'.
...@@ -284,50 +299,80 @@ class Tracker(object): ...@@ -284,50 +299,80 @@ class Tracker(object):
pred_cls_ids = pred_cls_ids[keep_idx[0]] pred_cls_ids = pred_cls_ids[keep_idx[0]]
pred_scores = pred_scores[keep_idx[0]] pred_scores = pred_scores[keep_idx[0]]
pred_tlwhs = np.concatenate(
(pred_xyxys[:, 0:2],
pred_xyxys[:, 2:4] - pred_xyxys[:, 0:2] + 1),
axis=1)
pred_dets = np.concatenate( pred_dets = np.concatenate(
(pred_cls_ids, pred_scores, pred_tlwhs), axis=1) (pred_cls_ids, pred_scores, pred_xyxys), axis=1)
tracker = self.model.tracker if use_reid:
crops = get_crops( crops = get_crops(
pred_xyxys, pred_xyxys,
ori_image, ori_image,
w=tracker.input_size[0], w=tracker.input_size[0],
h=tracker.input_size[1]) h=tracker.input_size[1])
crops = paddle.to_tensor(crops) crops = paddle.to_tensor(crops)
data.update({'crops': crops}) data.update({'crops': crops})
pred_embs = self.model(data).numpy() pred_embs = self.model(data).numpy()
else:
tracker.predict() pred_embs = None
online_targets = tracker.update(pred_dets, pred_embs)
if isinstance(tracker, DeepSORTTracker):
online_tlwhs, online_scores, online_ids = [], [], [] online_tlwhs, online_scores, online_ids = [], [], []
for t in online_targets: tracker.predict()
if not t.is_confirmed() or t.time_since_update > 1: online_targets = tracker.update(pred_dets, pred_embs)
continue for t in online_targets:
tlwh = t.to_tlwh() if not t.is_confirmed() or t.time_since_update > 1:
tscore = t.score continue
tid = t.track_id tlwh = t.to_tlwh()
if tscore < draw_threshold: continue tscore = t.score
if tlwh[2] * tlwh[3] <= tracker.min_box_area: continue tid = t.track_id
if tracker.vertical_ratio > 0 and tlwh[2] / tlwh[ if tscore < draw_threshold: continue
3] > tracker.vertical_ratio: if tlwh[2] * tlwh[3] <= tracker.min_box_area: continue
continue if tracker.vertical_ratio > 0 and tlwh[2] / tlwh[
online_tlwhs.append(tlwh) 3] > tracker.vertical_ratio:
online_scores.append(tscore) continue
online_ids.append(tid) online_tlwhs.append(tlwh)
timer.toc() online_scores.append(tscore)
online_ids.append(tid)
timer.toc()
# save results
results[0].append(
(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)
elif isinstance(tracker, JDETracker):
# trick hyperparams only used for MOTChallenge (MOT17, MOT20) Test-set
tracker.track_buffer, tracker.conf_thres = get_trick_hyperparams(
seq_name, tracker.track_buffer, tracker.conf_thres)
online_targets_dict = tracker.update(pred_dets_old, pred_embs)
online_tlwhs = defaultdict(list)
online_scores = defaultdict(list)
online_ids = defaultdict(list)
for cls_id in range(self.cfg.num_classes):
online_targets = online_targets_dict[cls_id]
for t in online_targets:
tlwh = t.tlwh
tid = t.track_id
tscore = t.score
if tlwh[2] * tlwh[3] <= tracker.min_box_area: continue
if tracker.vertical_ratio > 0 and tlwh[2] / tlwh[
3] > tracker.vertical_ratio:
continue
online_tlwhs[cls_id].append(tlwh)
online_ids[cls_id].append(tid)
online_scores[cls_id].append(tscore)
# save results
results[cls_id].append(
(frame_id + 1, online_tlwhs[cls_id], online_scores[cls_id],
online_ids[cls_id]))
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 results
results[0].append(
(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)
frame_id += 1 frame_id += 1
return results, frame_id, timer.average_time, timer.calls return results, frame_id, timer.average_time, timer.calls
...@@ -346,10 +391,10 @@ class Tracker(object): ...@@ -346,10 +391,10 @@ class Tracker(object):
if not os.path.exists(output_dir): os.makedirs(output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir)
result_root = os.path.join(output_dir, 'mot_results') result_root = os.path.join(output_dir, 'mot_results')
if not os.path.exists(result_root): os.makedirs(result_root) if not os.path.exists(result_root): os.makedirs(result_root)
assert data_type in ['mot', 'mcmot', 'kitti'], \ assert data_type in MOT_DATA_TYPE, \
"data_type should be 'mot', 'mcmot' or 'kitti'" "data_type should be 'mot', 'mcmot' or 'kitti'"
assert model_type in ['JDE', 'DeepSORT', 'FairMOT'], \ assert model_type in MOT_ARCH, \
"model_type should be 'JDE', 'DeepSORT' or 'FairMOT'" "model_type should be 'JDE', 'DeepSORT', 'FairMOT' or 'ByteTrack'"
# run tracking # run tracking
n_frame = 0 n_frame = 0
...@@ -380,13 +425,13 @@ class Tracker(object): ...@@ -380,13 +425,13 @@ class Tracker(object):
result_filename = os.path.join(result_root, '{}.txt'.format(seq)) result_filename = os.path.join(result_root, '{}.txt'.format(seq))
with paddle.no_grad(): with paddle.no_grad():
if model_type in ['JDE', 'FairMOT']: if model_type in MOT_ARCH_JDE:
results, nf, ta, tc = self._eval_seq_jde( results, nf, ta, tc = self._eval_seq_jde(
dataloader, dataloader,
save_dir=save_dir, save_dir=save_dir,
show_image=show_image, show_image=show_image,
frame_rate=frame_rate) frame_rate=frame_rate)
elif model_type in ['DeepSORT']: elif model_type in MOT_ARCH_SDE:
results, nf, ta, tc = self._eval_seq_sde( results, nf, ta, tc = self._eval_seq_sde(
dataloader, dataloader,
save_dir=save_dir, save_dir=save_dir,
...@@ -472,10 +517,10 @@ class Tracker(object): ...@@ -472,10 +517,10 @@ class Tracker(object):
if not os.path.exists(output_dir): os.makedirs(output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir)
result_root = os.path.join(output_dir, 'mot_results') result_root = os.path.join(output_dir, 'mot_results')
if not os.path.exists(result_root): os.makedirs(result_root) if not os.path.exists(result_root): os.makedirs(result_root)
assert data_type in ['mot', 'mcmot', 'kitti'], \ assert data_type in MOT_DATA_TYPE, \
"data_type should be 'mot', 'mcmot' or 'kitti'" "data_type should be 'mot', 'mcmot' or 'kitti'"
assert model_type in ['JDE', 'DeepSORT', 'FairMOT'], \ assert model_type in MOT_ARCH, \
"model_type should be 'JDE', 'DeepSORT' or 'FairMOT'" "model_type should be 'JDE', 'DeepSORT', 'FairMOT' or 'ByteTrack'"
# run tracking # run tracking
if video_file: if video_file:
...@@ -505,14 +550,14 @@ class Tracker(object): ...@@ -505,14 +550,14 @@ class Tracker(object):
frame_rate = self.dataset.frame_rate frame_rate = self.dataset.frame_rate
with paddle.no_grad(): with paddle.no_grad():
if model_type in ['JDE', 'FairMOT']: if model_type in MOT_ARCH_JDE:
results, nf, ta, tc = self._eval_seq_jde( results, nf, ta, tc = self._eval_seq_jde(
dataloader, dataloader,
save_dir=save_dir, save_dir=save_dir,
show_image=show_image, show_image=show_image,
frame_rate=frame_rate, frame_rate=frame_rate,
draw_threshold=draw_threshold) draw_threshold=draw_threshold)
elif model_type in ['DeepSORT']: elif model_type in MOT_ARCH_SDE:
results, nf, ta, tc = self._eval_seq_sde( results, nf, ta, tc = self._eval_seq_sde(
dataloader, dataloader,
save_dir=save_dir, save_dir=save_dir,
...@@ -536,3 +581,34 @@ class Tracker(object): ...@@ -536,3 +581,34 @@ class Tracker(object):
write_mot_results(result_filename, results, data_type, write_mot_results(result_filename, results, data_type,
self.cfg.num_classes) self.cfg.num_classes)
def get_trick_hyperparams(video_name, ori_buffer, ori_thresh):
if video_name[:3] != 'MOT':
# only used for MOTChallenge (MOT17, MOT20) Test-set
return ori_buffer, ori_thresh
video_name = video_name[:8]
if 'MOT17-05' in video_name:
track_buffer = 14
elif 'MOT17-13' in video_name:
track_buffer = 25
else:
track_buffer = ori_buffer
if 'MOT17-01' in video_name:
track_thresh = 0.65
elif 'MOT17-06' in video_name:
track_thresh = 0.65
elif 'MOT17-12' in video_name:
track_thresh = 0.7
elif 'MOT17-14' in video_name:
track_thresh = 0.67
else:
track_thresh = ori_thresh
if 'MOT20-06' in video_name or 'MOT20-08' in video_name:
track_thresh = 0.3
else:
track_thresh = ori_thresh
return track_buffer, ori_thresh
...@@ -51,7 +51,7 @@ logger = setup_logger('ppdet.engine') ...@@ -51,7 +51,7 @@ logger = setup_logger('ppdet.engine')
__all__ = ['Trainer'] __all__ = ['Trainer']
MOT_ARCH = ['DeepSORT', 'JDE', 'FairMOT'] MOT_ARCH = ['DeepSORT', 'JDE', 'FairMOT', 'ByteTrack']
class Trainer(object): class Trainer(object):
......
...@@ -308,10 +308,10 @@ class MCMOTEvaluator(object): ...@@ -308,10 +308,10 @@ class MCMOTEvaluator(object):
def load_annotations(self): def load_annotations(self):
assert self.data_type == 'mcmot' assert self.data_type == 'mcmot'
self.gt_filename = os.path.join(self.data_root, '../', '../', self.gt_filename = os.path.join(self.data_root, '../',
'sequences', 'sequences',
'{}.txt'.format(self.seq_name)) '{}.txt'.format(self.seq_name))
def reset_accumulator(self): def reset_accumulator(self):
import motmetrics as mm import motmetrics as mm
mm.lap.default_solver = 'lap' mm.lap.default_solver = 'lap'
......
...@@ -27,6 +27,7 @@ from . import detr ...@@ -27,6 +27,7 @@ from . import detr
from . import sparse_rcnn from . import sparse_rcnn
from . import tood from . import tood
from . import retinanet from . import retinanet
from . import bytetrack
from .meta_arch import * from .meta_arch import *
from .faster_rcnn import * from .faster_rcnn import *
...@@ -51,3 +52,4 @@ from .detr import * ...@@ -51,3 +52,4 @@ from .detr import *
from .sparse_rcnn import * from .sparse_rcnn import *
from .tood import * from .tood import *
from .retinanet import * from .retinanet import *
from .bytetrack import *
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from ppdet.core.workspace import register, create
from .meta_arch import BaseArch
__all__ = ['ByteTrack']
@register
class ByteTrack(BaseArch):
"""
ByteTrack network, see https://arxiv.org/abs/
Args:
detector (object): detector model instance
reid (object): reid model instance
tracker (object): tracker instance
"""
__category__ = 'architecture'
def __init__(self,
detector='YOLOX',
reid=None,
tracker='JDETracker'):
super(ByteTrack, self).__init__()
self.detector = detector
self.reid = reid
self.tracker = tracker
@classmethod
def from_config(cls, cfg, *args, **kwargs):
detector = create(cfg['detector'])
if cfg['reid'] != 'None':
reid = create(cfg['reid'])
else:
reid = None
tracker = create(cfg['tracker'])
return {
"detector": detector,
"reid": reid,
"tracker": tracker,
}
def _forward(self):
det_outs = self.detector(self.inputs)
if self.training:
return det_outs
else:
if self.reid is not None:
assert 'crops' in self.inputs
crops = self.inputs['crops']
pred_embs = self.reid(crops)
else:
pred_embs = None
det_outs['embeddings'] = pred_embs
return det_outs
def get_loss(self):
return self._forward()
def get_pred(self):
return self._forward()
...@@ -102,7 +102,8 @@ class DeepSORTTracker(object): ...@@ -102,7 +102,8 @@ class DeepSORTTracker(object):
""" """
pred_cls_ids = pred_dets[:, 0:1] pred_cls_ids = pred_dets[:, 0:1]
pred_scores = pred_dets[:, 1:2] pred_scores = pred_dets[:, 1:2]
pred_tlwhs = pred_dets[:, 2:6] pred_xyxys = pred_dets[:, 2:6]
pred_tlwhs = np.concatenate((pred_xyxys[:, 0:2], pred_xyxys[:, 2:4] - pred_xyxys[:, 0:2] + 1), axis=1)
detections = [ detections = [
Detection(tlwh, score, feat, cls_id) Detection(tlwh, score, feat, cls_id)
......
...@@ -34,9 +34,6 @@ from ppdet.engine import Tracker ...@@ -34,9 +34,6 @@ from ppdet.engine import Tracker
from ppdet.utils.check import check_gpu, check_version, check_config from ppdet.utils.check import check_gpu, check_version, check_config
from ppdet.utils.cli import ArgsParser from ppdet.utils.cli import ArgsParser
from ppdet.utils.logger import setup_logger
logger = setup_logger('eval')
def parse_args(): def parse_args():
parser = ArgsParser() parser = ArgsParser()
...@@ -83,11 +80,8 @@ def run(FLAGS, cfg): ...@@ -83,11 +80,8 @@ def run(FLAGS, cfg):
tracker = Tracker(cfg, mode='eval') tracker = Tracker(cfg, mode='eval')
# load weights # load weights
if cfg.architecture in ['DeepSORT']: if cfg.architecture in ['DeepSORT', 'ByteTrack']:
if cfg.det_weights != 'None': tracker.load_weights_sde(cfg.det_weights, cfg.reid_weights)
tracker.load_weights_sde(cfg.det_weights, cfg.reid_weights)
else:
tracker.load_weights_sde(None, cfg.reid_weights)
else: else:
tracker.load_weights_jde(cfg.weights) tracker.load_weights_jde(cfg.weights)
......
...@@ -28,7 +28,6 @@ import warnings ...@@ -28,7 +28,6 @@ import warnings
warnings.filterwarnings('ignore') warnings.filterwarnings('ignore')
import paddle import paddle
from ppdet.core.workspace import load_config, merge_config from ppdet.core.workspace import load_config, merge_config
from ppdet.utils.check import check_gpu, check_version, check_config from ppdet.utils.check import check_gpu, check_version, check_config
from ppdet.utils.cli import ArgsParser from ppdet.utils.cli import ArgsParser
...@@ -65,11 +64,8 @@ def run(FLAGS, cfg): ...@@ -65,11 +64,8 @@ def run(FLAGS, cfg):
trainer = Trainer(cfg, mode='test') trainer = Trainer(cfg, mode='test')
# load weights # load weights
if cfg.architecture in ['DeepSORT']: if cfg.architecture in ['DeepSORT', 'ByteTrack']:
if cfg.det_weights != 'None': trainer.load_weights_sde(cfg.det_weights, cfg.reid_weights)
trainer.load_weights_sde(cfg.det_weights, cfg.reid_weights)
else:
trainer.load_weights_sde(None, cfg.reid_weights)
else: else:
trainer.load_weights(cfg.weights) trainer.load_weights(cfg.weights)
......
...@@ -34,9 +34,6 @@ from ppdet.engine import Tracker ...@@ -34,9 +34,6 @@ from ppdet.engine import Tracker
from ppdet.utils.check import check_gpu, check_version, check_config from ppdet.utils.check import check_gpu, check_version, check_config
from ppdet.utils.cli import ArgsParser from ppdet.utils.cli import ArgsParser
from ppdet.utils.logger import setup_logger
logger = setup_logger('train')
def parse_args(): def parse_args():
parser = ArgsParser() parser = ArgsParser()
...@@ -94,11 +91,8 @@ def run(FLAGS, cfg): ...@@ -94,11 +91,8 @@ def run(FLAGS, cfg):
tracker = Tracker(cfg, mode='test') tracker = Tracker(cfg, mode='test')
# load weights # load weights
if cfg.architecture in ['DeepSORT']: if cfg.architecture in ['DeepSORT', 'ByteTrack']:
if cfg.det_weights != 'None': tracker.load_weights_sde(cfg.det_weights, cfg.reid_weights)
tracker.load_weights_sde(cfg.det_weights, cfg.reid_weights)
else:
tracker.load_weights_sde(None, cfg.reid_weights)
else: else:
tracker.load_weights_jde(cfg.weights) tracker.load_weights_jde(cfg.weights)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册