- 参考博客:多目标跟踪之数据关联算法——匈牙利算法
- Yolov5_DeepSort_Pytorch仓库: https://github.com/mikel-brostrom/Yolov5_DeepSort_Pytorch.git
- 参考博客:Deep SORT论文阅读总结
- DeepSORT论文翻译(SIMPLE ONLINE AND REALTIME TRACKING WITH A DEEP ASSOCIATION METRIC)_alex1801的博客-CSDN博客_deepsort论文翻译
- Deep SORT多目标跟踪算法代码解析 - pprp - 博客园
-
本方法加入了外观信息来提高SORT的性能,用余弦距离来度量 tracks 和 detection 的相似度以减少 SORT算法中ID switch的次数
-
并使用Kalman预测和实际detection间的平方马氏距离来滤除可能性小的匹配。
加入Reid提取的外观特征,对目标进行深度关联度量,ID switch减少了45%,外观距离减少ID交换;马氏距离滤除不大可能的匹配。
1. Introduction:This is, because the employed association metric is only accurate when state estimation uncertainty is low.
只有在状态估计的残差协方差的值较小(估计不确定性小,就是估计的方差小)时,关联的Metric才是准确的。
SORT算法ID switch次数高是因为采用的关联矩阵只在状态预测不确定性较小的时候准确(状态估计模型存在缺陷)
mark: 是啊,一直predict,不update,covariance就是一直累加累加。可不就变大了。costMatrix可不就变小了,然后unAssignedTrack就更容易匹配上Detect,因为它的Covariance太大了。
因此,SORT在遮挡场景下存在缺陷。解决遮挡问题的办法:关联metric改为新的metric,新的metric结合了运动信息和外观信息。
2 SORT with deep association metric:
We adopt a conventional single hypothesis tracking methodology with recursive Kalman fifiltering and frame-by-frame data association.我们采用了传统的单一假设跟踪方法,逐帧数据关联。
A conventional way to solve the association between the predicted Kalman states and newly arrived measurements is to build an assignment problem that can be solved using the Hungarian algorithm. Into this problem formulation we integrate motion and appearance information through combination of two appropriate metrics.
运动模型、外观模型,两个metric的组合(但绝非相加之类的metric处理,因为两个metric的意义和量纲绝非一直,无法融合再一起。)
补充SORT部分:马氏距离是二维联合高斯分布,取log后的值,可以认为是概率分布。
但是卡方分布是两个i.i.d.的高斯分布的平方相加 Z1^2+Z2^2~卡方分布(n),n=2, α=95%的阈值
私以为,二者的概念都不一样,为什么要放在一起讨论????
sort最大的问题,是IOU的costMatrix不可靠。导致大量的ID switch。
一、Yolov5有检测输出,deepsort无track输出,原因
测试视频:MOT_trackingDemo/test_MOT16-01.avi,MOT challenge,MOT16中的test_MOT16-01.avi。把img序列压成一个avi格式的视频。
① 现象:有检测输出,无轨迹输出
原因:第68帧为止,新建了491个ID了。(代码丝毫无改动的情况下)——基本上毫无匹配
video 1/1 (66/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 7 persons, Done. YOLO:(0.018s), DeepSort:(0.136s)
video 1/1 (67/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 8 persons, Done. YOLO:(0.019s), DeepSort:(0.139s)
video 1/1 (68/450) /home/zhr/zhr_file/MOT_trackingDemo/test_MOT16-01.avi: 384x640 8 persons, Done. YOLO:(0.018s), DeepSort:(441.283s)
② 现象——kf.predict() 预测环节中的不合理之处:这些track基本上只出现过一次,没有过匹配,也没有被删除。且track的残差协方差巨大。
残差协方差的predict过程中,过程噪声processNoiseCov Qn与状态变量强相关,不符合kalman的基本假设!————『作者设计意图&根据未知』
同时,由于track.mean的速度部分只有第一次初始化为0,所以mean一直原地踏步,没有速度增量。一旦不被匹配,一直不会被update更新,将一直停留在原地。
③ 级联匹配逻辑:cascade_depth为max_age
由于time_since_update即,目标连续XXX帧无匹配,就不进入cost Matrix计算。
def matching_cascade(
distance_metric, max_distance, cascade_depth, tracks, detections,
track_indices=None, detection_indices=None):
# cascade_depth = self.max_age # 30
if track_indices is None:
track_indices = list(range(len(tracks)))
if detection_indices is None:
detection_indices = list(range(len(detections)))
unmatched_detections = detection_indices
matches = []
for level in range(cascade_depth):
if len(unmatched_detections) == 0: # No detections left
break
track_indices_l = [
k for k in track_indices
if tracks[k].time_since_update == 1 + level
]
if len(track_indices_l) == 0: # Nothing to match at this level
continue
matches_l, _, unmatched_detections = \
min_cost_matching(
distance_metric, max_distance, tracks, detections,
track_indices_l, unmatched_detections)
matches += matches_l
unmatched_tracks = list(set(track_indices) - set(k for k, _ in matches))
return matches, unmatched_tracks, unmatched_detections
命令行参数设置:
parser = argparse.ArgumentParser()
# 检测模型:模型位置,放在当前 Yolov5_DeepSort_Pytorch 目录下就可以了
parser.add_argument('--yolo_model', nargs='+', type=str, default='yolov5m.pt', help='model.pt path(s)')
# ReID模型
parser.add_argument('--deep_sort_model', type=str, default='osnet_ibn_x1_0_MSMT17')
# 视频输入:img/video、camera
parser.add_argument('--source', type=str, default='0', help='source') # file/folder, 0 for webcam
# 输出文件地址,推理output
parser.add_argument('--output', type=str, default='inference/output', help='output folder') # output folder
# 推理图像尺寸设置
parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
# 目标置信度阈值筛选
parser.add_argument('--conf-thres', type=float, default=0.5, help='object confidence threshold')
# NMS的IOU阈值设置
parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
# 输出视频格式设置
parser.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)')
# GPU/CPU设置
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
# 是否展示tracking结果
parser.add_argument('--show-vid', action='store_true', help='display tracking video results')
# 是否存储视频跟踪结果
parser.add_argument('--save-vid', action='store_true', help='save video tracking results')
# 是否保存跟踪结果
parser.add_argument('--save-txt', action='store_true', help='save MOT compliant results to *.txt')
# 检测类别筛选:class 0 is person, 1 is bycicle, 2 is car... 79 is oven
parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 16 17')
#
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
parser.add_argument('--augment', action='store_true', help='augmented inference')
parser.add_argument('--evaluate', action='store_true', help='augmented inference')
parser.add_argument("--config_deepsort", type=str, default="deep_sort/configs/deep_sort.yaml")
parser.add_argument("--half", action="store_true", help="use FP16 half-precision inference")
parser.add_argument('--visualize', action='store_true', help='visualize features')
parser.add_argument('--max-det', type=int, default=1000, help='maximum detection per image')
# 使用opencv dnn for ONNX 推理
parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
# 工程保存到runs/track/文件夹下
parser.add_argument('--project', default=ROOT / 'runs/track', help='save results to project/name')
parser.add_argument('--name', default='exp', help='save results to project/name')
# 就在已有的目录下,不要新建目录
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
# 模型位置,yolov5m.pt放在当前 Yolov5_DeepSort_Pytorch 目录下就可以了,其余参数设置如下
--source ../../MOT_trackingDemo/test_MOT16-03.avi --show-vid --exist-ok --class 0
输出结果如下:(模型读入成功)
# 输出的结果如下:
Available ReID models for automatic download
['resnet50_market1501', 'resnet50_dukemtmcreid', 'resnet50_msmt17', 'resnet50_fc512_market1501', 'resnet50_fc512_dukemtmcreid', 'resnet50_fc512_msmt17', 'mlfn_market1501', 'mlfn_dukemtmcreid', 'mlfn_msmt17', 'hacnn_market1501', 'hacnn_dukemtmcreid', 'hacnn_msmt17', 'mobilenetv2_x1_0_market1501', 'mobilenetv2_x1_0_dukemtmcreid', 'mobilenetv2_x1_0_msmt17', 'mobilenetv2_x1_4_market1501', 'mobilenetv2_x1_4_dukemtmcreid', 'mobilenetv2_x1_4_msmt17', 'osnet_x1_0_market1501', 'osnet_x1_0_dukemtmcreid', 'osnet_x1_0_msmt17', 'osnet_x0_75_market1501', 'osnet_x0_75_dukemtmcreid', 'osnet_x0_75_msmt17', 'osnet_x0_5_market1501', 'osnet_x0_5_dukemtmcreid', 'osnet_x0_5_msmt17', 'osnet_x0_25_market1501', 'osnet_x0_25_dukemtmcreid', 'osnet_x0_25_msmt17', 'resnet50_MSMT17', 'osnet_x1_0_MSMT17', 'osnet_x0_75_MSMT17', 'osnet_x0_5_MSMT17', 'osnet_x0_25_MSMT17', 'osnet_ibn_x1_0_MSMT17', 'osnet_ain_x1_0_MSMT17']
YOLOv5 🚀 v6.1-38-g7c6a335 torch 1.11.0+cu102 CUDA:0 (NVIDIA GeForce RTX 2060, 5926MiB)
Model: osnet_ibn_x1_0
- params: 2,194,640
- flops: 978,878,352
Successfully loaded pretrained weights from "deep_sort/deep/checkpoint/osnet_ibn_x1_0_MSMT17.pth"
** The following layers are discarded due to unmatched keys or layer size: ['classifier.weight', 'classifier.bias']
YOLOv5 🚀 v6.1-38-g7c6a335 torch 1.11.0+cu102 CUDA:0 (NVIDIA GeForce RTX 2060, 5926MiB)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)