据我目前了解掌握,多目标跟踪大概有两种方式:算法
Option1函数
基于初始化帧的跟踪,在视频第一帧中选择你的目标,以后交给跟踪算法去实现目标的跟踪。这种方式基本上只能跟踪你第一帧选中的目标,若是后续帧中出现了新的物体目标,算法是跟踪不到的。这种方式的优势是速度相对较快。缺点很明显,不能跟踪新出现的目标。spa
Option2视频
基于目标检测的跟踪,在视频每帧中先检测出来全部感兴趣的目标物体,而后将其与前一帧中检测出来的目标进行关联来实现跟踪的效果。这种方式的优势是能够在整个视频中跟踪随时出现的新目标,固然这种方式要求你前提得有一个好的“目标检测”算法。blog
本文主要讲述Option2的实现原理,也就是Tracking By Detecting的跟踪方式。这篇文章没有源码连接,关于“目标检测”算法的源码能够参见我上一篇文章,至于“轨迹跟踪”算法的源码实现很简单,看完本文相信你们都能写出来,Python实现大概200行不到。源码
Tracking By Detecting的跟踪过程io
Step1:使用目标检测算法将每帧中感兴趣的目标检测出来,获得对应的(位置坐标, 分类, 可信度),假设检测到的目标数量为M;原理
Step2:经过某种方式将Step1中的检测结果与上一帧中的检测目标(假设上一帧检测目标数量为N)一一关联起来。换句话说,就是在M*N个Pair中找出最像似的Pair。numpy
对于Step2中的“某种方式”,其实有多种方式能够实现目标的关联,好比常见的计算两帧中两个目标之间的欧几里得距离(平面两点之间的直线距离),距离最短就认为是同一个目标,而后经过匈牙利算法找出最匹配的Pair。当让,你还能够加上其余的判断条件,好比我用到的IOU,计算两个目标Box(位置大小方框)的交并比,该值越接近1就表明是同一个目标。还有其余的好比判断两个目标的外观是否类似,这就须要用到一种外观模型去作比较了,可能耗时更长。方法
在关联的过程当中,会出现三种状况:
1)在上一帧中的N个目标中找到了本次检测到的目标,说明正常跟踪到了;
2)在上一帧中的N个目标中没有找到本次检测到的目标,说明这个目标是这一帧中新出现的,因此咱们须要把它记录下来,用于下下一次的跟踪关联;
3)在上一帧中存在某个目标,这一帧中并无与之关联的目标,那么说明该目标可能从视野中消失了,咱们须要将其移除。(注意这里的可能,由于有可能因为检测偏差,在这一帧中该目标并无被检测到)
存在的问题
上面提到的跟踪方法在正常状况下都可以很好的工做,可是若是视频中目标运动得很快,先后两帧中同一个目标运动的距离很远,那么这种跟踪方式就会出现问题。
如上图,实线框表示目标在第一帧的位置,虚线框表示目标在第二帧的位置。当目标运行速度比较慢的时候,经过以前的跟踪方式能够很准确的关联(A, A’)和(B, B’)。可是当目标运行速度很快(或者隔帧检测)时,在第二帧中,A就会运动到第一帧中B的位置,而B则运动到其余位置。这个时候使用上面的关联方法就会获得错误的结果。
那么怎样才能更加准确地进行跟踪呢?
基于轨迹预测的跟踪方式
既然经过第二帧的位置与第一帧的位置进行对比关联会出现偏差,那么咱们能够想办法在对比以前,先预测目标的下一帧会出现的位置,而后与该预测的位置来进行对比关联。这样的话,只要预测足够精确,那么几乎不会出现前面提到的因为速度太快而存在的偏差。
如上图,咱们在对比关联以前,先预测出A和B在下一帧中的位置,而后再使用实际的检测位置与预测的位置进行对比关联,能够完美地解决上面提到的问题。理论上,无论目标速度多么快,都能关联上。那么问题来了,怎么预测目标在下一帧的位置?
方法有不少,可使用卡尔曼滤波来根据目标前面几帧的轨迹来预测它下一帧的位置,还可使用本身拟合出来的函数来预测下一帧的位置。实际过程当中,我是使用拟合函数来预测目标在下一帧中的位置。
如上图,经过前面6帧的位置,我能够拟合出来一条(T->XY)的曲线(注意不是图中的直线),而后预测目标在T+1帧的位置。具体实现很简单,Python中的numpy库中有相似功能的方法。
仍然存在的不足
即便如此完美了,仍是存在不足。
轨迹预测的前提是须要知道目标前面若干帧的轨迹信息,所以在刚开始,目标的轨迹是预测不到的,或者说预测得不许。因此在刚开始的几帧,咱们仍是须要使用原来的方式进行对比关联。