写在前面

由于笔者如今正在做有关多目标跟踪的相关科研项目,因此想先开一个有关多目标跟踪的新专题,好的,话不多说,直接来上干货,在这篇文章中笔者将介绍如下的内容:

  • 什么是多目标跟踪
  • 进一步理解自动驾驶中的多目标跟踪,以大牌数据集KITTI为例,讲述KITTI上的多目标跟踪
    同样的,学无止境,如有错误也欢迎大家指出~

什么是多目标跟踪(MOT)

  • 多目标跟踪英文:Multiple Object Tracking,缩写MOT
  • 是单目标跟踪的超集
  • 基本任务正如“多目标跟踪”这五个字所描述的一样,就是给定一个图像序列(同一场景scene的不同frame),找到图像序列中运动的物体,并将不同帧(同一场景scene下)的同一运动物体(object,也是检测过后的bounding box)进行识别标号(也就是赋予track id),由于一个检测框(bounding box,也就是一个物体)只能匹配到一个轨迹(track)上,因此多目标跟踪在数学上是一个经典的二部图问题
  • 提到二部图问题,有相关数学和计算机基础的同学应该可以马上想到匈牙利算法,没错!构造代价矩阵进而使用匈牙利算法获得检测框和轨迹的对应关系是多目标跟踪(MOT)中的一个核心算法
  • 先甩一张照片,大家可以直观感受一下多目标跟踪MOT,注意三维检测框上的ID(这就是track id)
    AB3DMOT
    图片来源是AB3DMOT,这篇文章发表于IROS(机器人领域顶会) 2020,AB3DMOT只使用了激光这一种单传感器,文章最大的贡献是给出了一种简单(使用3DIOU关联)有效(当时SOTA)高实时性(在CPU上207.4FPS)的单激光传感器MOT的baseline(文章就叫“3D Multi-Object Tracking: A Baseline and New Evaluation Metrics”),并且文章提出的“New Evaluation Metrics”——AMOTA、AMOTP至今仍是Nuscenes的官方评价MOT算法效果的主要标准,值得一提的是AB3DMOT的作者小姐姐本科毕业于武汉大学

KITTI上的多目标跟踪

KITTI数据集笔者觉得无须多说,KITTI的数据量和传感器模态如今看来或许落后了后来者(Nuscenes, waymo),但也正是它启发了这些现代大规模数据集的产生,有关KITTI数据集的基本内容,大家可以去其官网了解,或者通过查看这篇博客及逆行了解,本节将主要讲述的是跟踪任务上的KITTI

KITTI的跟踪任务标签

笔者一直在思考如何才能生动形象的讲述KITTI上的MOT,最后我认为直接感受数据集标签label是一个不错入手点

KITTI跟踪任务数据集结构

训练集train有如下的文件夹结构:

  - image_02/%04d/ contains the left color camera sequence images (png)(这个我们经常使用,因为有标签与其对应)
  - image_03/%04d/ contains the right color camera sequence images  (png)(这个我们不常用,可以忽略)
  - label_02/ contains the left color camera label files (plain text files)(数据集的标签)
  - calib/ contains the calibration for all four cameras (plain text files)(四个相机的内参矩阵(P0-P3)、基准相机(0号)的修正矩阵(R-rect)、CAMERA-Lidar-IMU之间的变换矩阵Tr_velo_cam、Tr_imu_velo,经常用于将三维检测框投影到像素平面来获取二维检测框)
  - velodyne/ contains the raw velodyne point clouds (binary file)(激光雷达数据、二进制模式,在MOT一般画图用)
  - oxts/ contains the raw position (oxts) data (plain text files)(GPU+IMU数据,在MOT也不太常用,可以忽略)
  - pose/ contains the ground truth poses (trajectory) for the first 11 sequences(left相机的真实位姿,相对于第一帧(frame id=0)开始描述,其实就是相机坐标到世界世界坐标的变换矩阵)

来张图看一下吧:
KITTI tracking文件夹
而对于测试集test,则是没有label标签
让我们继续来看下一级的文件夹结构:
calib
label和image
重点关注的点有这么几个:

  • 第一个需要注意的是:calib一共有21个文件,这里的“20”其实就是第一节的”序列scene”这两个字的集合,20意味着有21个场景scene,image_02和label_02都给出了我们证明,即一个场景scene有很多帧frame构成,每一帧frame都有对应的label
  • 第二个需要注意的是:calib这个文件夹比较重要,也比较难以理解,说直白一点,文件里面其实就是各种坐标系之间的变换矩阵,对于它的理解可以看这篇博客,关于相机内参外参的问题看这个博客,关于相机修正矩阵的问题看这个博客
    为什么说他在MOT问题中重要?这是因为在多传感器后融合模式中,我们通常需要将第一次未匹配的三维检测框投影到二维像素平面进而进行第二次匹配,具体这么做的原因之后的博客中会介绍
  • 第三个需要注意的是:pose文件是从别的任务中拷贝而来,例如odometry里程计任务(SLAM)

label_02标签格式介绍

在首先上面为大家直观讲述了KITTI的跟踪任务数据集的各个组成,接下来是理解多目标跟踪MOT任务的重点,我们也是图文结合来介绍,并且拿几张照片写一些程序来帮助大家理解MOT,同样我们也是先来张图,图的内容是label_02/0000.txt:
label_02/0000.txt
根据我们上节的内容分析一下目录,这描述的就是第一个场景上的所有帧frame组成的标签,而每一位数字对应的内容是什么呢,有如下的描述:

#Values    Name      Description
----------------------------------------------------------------------------
   1    frame        Frame within the sequence where the object appearers
   1    track id     Unique tracking id of this object within this sequence
   1    type         Describes the type of object: 'Car', 'Van', 'Truck',
                     'Pedestrian', 'Person_sitting', 'Cyclist', 'Tram',
                     'Misc' or 'DontCare'
   1    truncated    Float from 0 (non-truncated) to 1 (truncated), where
                     truncated refers to the object leaving image boundaries.
                     Truncation 2 indicates an ignored object (in particular
                     in the beginning or end of a track) introduced by manual
                      labeling.
   1    occluded     Integer (0,1,2,3) indicating occlusion state:
                     0 = fully visible, 1 = partly occluded
                     2 = largely occluded, 3 = unknown
   1    alpha        Observation angle of object, ranging [-pi..pi]
   4    bbox         2D bounding box of object in the image (0-based index):
                     contains left, top, right, bottom pixel coordinates
   3    dimensions   3D object dimensions: height, width, length (in meters)
   3    location     3D object location x,y,z in camera coordinates (in meters)
   1    rotation_y   Rotation ry around Y-axis in camera coordinates [-pi..pi]
   1    score        Only for results: Float, indicating confidence in
                     detection, needed for p/r curves, higher is better.

其实文档描述的已经足够详细,我们还是关注一些重点的信息:

  • frame就是每一张图片,而track id就是每一个帧中物体的唯一跟踪标号
  • rotation_y和alpha其实比较难理解,对于这两个标签的说明可以看这篇博客,但其实我们不是特别关注这两个量,而对于剩下各个部分都足够浅显易懂
  • 最后一位score在label_02中没有给出,因为label_02中是gt,是真值,不存在置信度的问题,但在你的跟踪算法结果中需要给出,因为这关系到你算法的检测效果如何

有了含义和数据就让我们以一个python小程序来实践一下,我们主要关注这样几个信息(frame, track id, bbox的四个数值)
对于第五帧:
0000/4
原图:
4
对于第六帧:
0000/5
原图:
5
对于第七帧:
0000/6
原图:
6
笔者觉着这几帧特别好,我们重点关注这几个信息:

  • 这几帧好的原因:三帧就完美表达了多目标跟踪的物体的几种情况
    1. 追踪的物体消失了,track id为2的行人在第7帧完全消失了,这就意味它的track id需要被完全抛弃
    2. 出现了新的要被跟踪的物体,track id为3的卡车在第七帧出现了,这就意味着需要为他分配新的track id
    3. 跟踪的物体的高遮挡状态,track id为3的卡车在第七帧处于occluded=2的严重遮挡状态,跟踪他面临这样几个问题:A.跟踪不到它,这通常会出现,这就强调我们检测器的性能 B.跟踪到他了,但是由于他给我们的信息太少了,当他在例如第15帧完全出现时,我们却把他当成别的车了(分配了别的track id),这也就是MOT中最复杂和最困难解决的问题之一——ID switch问题,如何解决这个问题呢?我们会在之后的文章中介绍几种解决问题的方式
  • 一个轨迹是由多个检测框bbox构成的,针对轨迹的特征怎么进行合理的描述?这个问题我们同样留在之后的博客中来介绍
  • 一个好的检测器对于跟踪性能至关重要,“VAR体毛越位”的问题在真实场景检测中是真实存在的,第六帧“脚尖”的成功检测与否关系到我们跟踪算法的整体性能

写在最后

我们介绍了MOT的概念和以KITTI数据集中的标签为例进一步介绍了MOT,但是KITTI数据集关于MOT的内容远远不止这些,它对于MOT的评价指标是什么?它都会评估什么类别的物体?AB3DMOT是三维检测,KITTI的MOT是三维检测吗?我们都是怎么解决MOT问题的?笔者会在之后的文章中介绍上述这些问题
同时,我们看到文章出现了提到了开源数据集KITTI,提到了AB3DMOT,代码中使用的是d2l工具包,自动驾驶的发展离不开在社区这些无私奉献的人们,google scholar在首页就写着“站在巨人的肩膀上”,笔者谨代表自己真诚感谢做出这些开源的人们

附录(文章中用到的demo代码)

import torch
import os
import torchvision
from torch import nn
from d2l import torch as d2l
d2l.use_svg_display()
d2l.set_figsize()
img = d2l.Image.open('xxx/training/image_02/0000/000006.png')
d2l.plt.imshow(img);
pred1_bbox = [288.044118,147.111524,439.326636,266.443764]
pred2_bbox = [765.129111,147.124585,966.438106,374.000000]
pred3_bbox = [379.391627,159.146710,464.519993,201.762743]
fig = d2l.plt.imshow(img)
anchors = torch.tensor([pred1_bbox, pred2_bbox, pred3_bbox])
d2l.show_bboxes(fig.axes, anchors, ['0', '1', '3']);