参考文献:
KIM A, OSEP A, LEAL-TAIXE L. EagerMOT: 3D Multi-Object Tracking via Sensor Fusion[C]//2021 IEEE International Conference on Robotics and Automation (ICRA). Xi’an, China: IEEE, 2021: 11315-11321.

一、论文贡献

论文主要研究的内容是自动驾驶中的三维多目标跟踪问题。检测和跟踪是两个相互依赖的问题,近年来有一些文章将两个问题合二为一,但是本文还是遵循传统的方式,即建立在检测的基础上进行跟踪。目前主流的检测方法按照输入可以分为2D和3D方法,2D上的检测可以看得更远,而且对于小目标的检测更准,但是缺乏距离测量;而3D点云有精确的距离测量,但是比较稀疏,尤其是远距离的物体扫到的点很少,经常出现漏检,文章的创新点1就在于考虑融合3D检测距离很准而2D检测看得更远的优势,提高3D目标跟踪对遮挡、远距离目标跟踪的效果。
算法流程图
本方法的主要特点是在Kitti和NuScenes上效果很好,速度很快,不需要额外训练模型,直接利用现有的2D和3D检测器就可以。

二、如何使用

下面让我们来看如何实现

首先是数据集加载,以NuScenes为例

mot_dataset = MOTDatasetNuScenes(work_dir=args.root_dir + args.work_dir + args.dataset, det_source=param['nuscenes']['CENTER_POINT'],      seg_source=param['nuscenes']['MMDETECTION_CASCADE_NUIMAGES'], version=param['nuscenes']['version'], data_dir=args.root_dir + args.data_dir + args.dataset, param=param['nuscenes'], args=args)

其中需要指定工作空间和数据集的位置,所使用的检测源,网络参数等。
之后通过sequence_names方法获取序列的名称列表
mot_dataset.sequence_names(split)
之后对于算法主体进行加载,注意输入不是数据集,而是通过get_sequence方法获取序列类,算法是以sequence运行的。

model = build_model(source="eagermot",
					sequence=mot_dataset.get_sequence(args.split[1:], sequence_name, args.ignore_result), 
					params=param['nuscenes'], 
					test_mode=args.test_mode)

最后通过run_info = model.run()对于算法进行运行。对于结果的保存,在Kitti数据集下每一个sequence结束后会自动保存为txt,对于NuScenes数据下,需要在算法的最后调用save_all_mot_results方法,传入想要保存的位置,所有的跟踪结果都会存入一个json文件中。

三、算法实现

下面让我们进入Eagermot类中看一看算法是如何是如何实现的
首先对于输入的序列,通过preprocess函数进行预生成,生成所需的各种文件。

run_info, mot_3d_file, mot_2d_from_3d_file, flag = self.sequence.preprocess(self.params)

之后算法会按帧进行循环

for frame_i, frame_name in enumerate(self.sequence.frame_names):
    frame = self.sequence.get_frame(frame_name)

作为数据预处理阶段,算法首先会对输入的2D和3D检测进行融合,根据他们的交并比和贪心算法生成实例,每一个实例至少包含2D或3D检测。这里通过fuse函数实现

fuse_result = frame.fuse(self.params, self.run_info, self.test_mode)

在开始跟踪之前,需要对于轨迹进行重置,实现方法如下:

for track in self.sequence.mot.trackers: track.reset_for_new_frame()

至此正式开始跟踪,算法是按照要跟踪的物体类别一一计算的,获取类别的方法是classes_to_track

for class_target in self.sequence.mot.classes_to_track:

算法的第一阶段是根据3D位置进行匹配的,即比较已跟踪的物体在当前帧的预测位置和3D检测位置,在这里封装成了类Matche3D

stage1 = Match3d(track_empty[0], track_empty[2], self.params)
result1 = stage1.run()

对于第一阶段没有匹配成功的检测实例,会进入第二阶段,即根据2D框的位置进行匹配,其中如果实例包含3D检测结果,会将其映射到2D图像坐标系进行匹配。第二阶段封装成了类Match2D

stage2 = Match2d(track_empty, result1, self.run_info, fuse_result, self.sequence.mot,frame.data)
result2 = stage2.run(self.sequence.mot)

最后对于轨迹进行更新和分类,输入轨迹管理模块,即对于未匹配的检测生成新轨迹,更新已有轨迹的位置和速度(卡尔曼滤波器),终止若干帧未更新的轨迹,实现方法是report_tracks

predicted_instances = self.sequence.mot.report_tracks(ego_transform, angle_around_y)

四、可视化结果

为了将Kitti的跟踪的结果直观显示出来,可以使用函数draw_kitti_2ddraw_kitti_3d,需要指定希望可视化的序列号,跟踪结果地址,数据集地址,保存的帧数,结果会以gif的格式保存。

draw_kitti_2d(seq="0001", data_path=data_path, pred_path=pred_path_2d, save_path=save_path, frames=20)

可视化结果

参考:

https://blog.csdn.net/qq_42575422/article/details/120982453
https://blog.csdn.net/qq_40498388/article/details/125540571

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐