BoxMOT:可插拔的SOTA跟踪模块,适用于分割、目标检测和姿态估计模型
介绍
这个代码库包含了一系列可插拔的多目标跟踪模块,适用于分割、目标检测和姿态估计模型。对于使用外观描述的方法,我们提供了重型(CLIPReID)和轻量级的SOTA ReID模型(LightMBN、OSNet等),可自动下载。我们还提供了如何将此软件包与流行的目标检测模型结合使用的示例,例如:Yolov8、Yolo-NAS和YOLOX。
跟踪器 | HOTA↑ | MOTA↑ | IDF1↑ |
---|---|---|---|
BoTSORT | 77.8 | 78.9 | 88.9 |
DeepOCSORT | 77.4 | 78.4 | 89.0 |
OCSORT | 77.4 | 78.4 | 89.0 |
HybridSORT | 77.3 | 77.9 | 88.8 |
ByteTrack | 75.6 | 74.6 | 86.0 |
StrongSORT | |||
ImprAssoc | |||
注:在每个MOT17序列的前10帧上执行。使用的检测器是ByteTrack的YoloXm,训练于:CrowdHuman、MOT17、Cityperson和ETHZ。每个跟踪器都使用其各自官方库中找到的原始参数进行配置。
第三方资源
实验
按时间倒序排列:
新闻
- 使用RayTune进行所有跟踪器的超参数搜索(2024年7月)
- 在#1527中由rolson24添加了改进的关联管道 我们支持将ReID模型导出为ONNX、OpenVINO、TorchScript和TensorRT
# 导出为ONNX
$ python3 boxmot/appearance/reid_export.py --include onnx --device cpu
# 导出为OpenVINO
$ python3 boxmot/appearance/reid_export.py --include openvino --device cpu
# 使用动态输入导出为TensorRT
$ python3 boxmot/appearance/reid_export.py --include engine --device 0 --dynamic
导致最佳HOTA结果的超参数集被写入跟踪器的配置文件中。
自定义跟踪示例
检测
import cv2
import numpy as np
from pathlib import Path
from boxmot import DeepOCSORT
tracker = DeepOCSORT(
model_weights=Path('osnet_x0_25_msmt17.pt'), # 使用哪个ReID模型
device='cuda:0',
fp16=False,
)
vid = cv2.VideoCapture(0)
while True:
ret, im = vid.read()
# 替换为您的对象检测器,输出必须为N X (x, y, x, y, conf, cls)
dets = np.array([[144, 212, 578, 480, 0.82, 0],
[425, 281, 576, 472, 0.56, 65]])
# 检查是否有任何检测
if dets.size > 0:
tracker.update(dets, im) # --> M X (x, y, x, y, id, conf, cls, ind)
# 如果没有检测,进行预测
else:
dets = np.empty((0, 6)) # 空的N X (x, y, x, y, conf, cls)
tracker.update(dets, im) # --> M X (x, y, x, y, id, conf, cls, ind)
tracker.plot_results(im, show_trajectories=True)
# 按下q或空格键退出
cv2.imshow('BoxMOT detection', im)
key = cv2.waitKey(1) & 0xFF
if key == ord(' ') or key == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
姿态和分割
import cv2
import numpy as np
from pathlib import Path
from boxmot import DeepOCSORT
tracker = DeepOCSORT(
model_weights=Path('osnet_x0_25_msmt17.pt'), # 使用哪个ReID模型
device='cuda:0',
fp16=True,
)
vid = cv2.VideoCapture(0)
while True:
ret, im = vid.read()
keypoints = np.random.rand(2, 17, 3)
mask = np.random.rand(2, 480, 640)
# 替换为您的对象检测器,跟踪器输入必须为N X (x, y, x, y, conf, cls)
dets = np.array([[144, 212, 578, 480, 0.82, 0],
[425, 281, 576, 472, 0.56, 65]])
tracks = tracker.update(dets, im) # --> M x (x, y, x, y, id, conf, cls, ind)
# xyxys = tracks[:, 0:4].astype('int') # float64转int
# ids = tracks[:, 4].astype('int') # float64转int
# confs = tracks[:, 5]
# clss = tracks[:, 6].astype('int') # float64转int
inds = tracks[:, 7].astype('int') # float64转int
# 如果您在检测旁边有分割或姿态,可以使用
# ind变量来识别哪个跟踪与每个分割或姿态相关:
# masks = masks[inds]
# keypoints = keypoints[inds]
# 这样你就可以:zip(tracks, masks)或zip(tracks, keypoints)
# 按下q或空格键退出
cv2.imshow('BoxMOT segmentation | pose', im)
key = cv2.waitKey(1) & 0xFF
if key == ord(' ') or key == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
分块推理
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
import cv2
import numpy as np
from pathlib import Path
from boxmot import DeepOCSORT
tracker = DeepOCSORT(
model_weights=Path('osnet_x0_25_msmt17.pt'), # 使用哪个ReID模型
device='cpu',
fp16=False,
)
detection_model = AutoDetectionModel.from_pretrained(
model_type='yolov8',
model_path='yolov8n.pt',
confidence_threshold=0.5,
device="cpu", # 或'cuda:0'
)
vid = cv2.VideoCapture(0)
color = (0, 0, 255) # BGR
thickness = 2
fontscale = 0.5
while True:
ret, im = vid.read()
# 获取分块预测
result = get_sliced_prediction(
im,
detection_model,
slice_height=256,
slice_width=256,
overlap_height_ratio=0.2,
overlap_width_ratio=0.2
)
num_predictions = len(result.object_prediction_list)
dets = np.zeros([num_predictions, 6], dtype=np.float32)
for ind, object_prediction in enumerate(result.object_prediction_list):
dets[ind, :4] = np.array(object_prediction.bbox.to_xyxy(), dtype=np.float32)
dets[ind, 4] = object_prediction.score.value
dets[ind, 5] = object_prediction.category.id
tracks = tracker.update(dets, im) # --> (x, y, x, y, id, conf, cls, ind)
tracker.plot_results(im, show_trajectories=True)
# 按下q或空格键退出
cv2.imshow('BoxMOT tiled inference', im)
key = cv2.waitKey(1) & 0xFF
if key == ord(' ') or key == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
贡献者
联系
有关Yolo跟踪的错误和功能请求,请访问GitHub Issues。 如需商业合作或专业支持请求,请发送电子邮件至:box-mot@outlook.com