从零开始的运动目标跟踪
2021.07.12 10:47浏览量:238简介:介绍单目标跟踪和多目标跟踪及单镜跟踪和跨镜跟踪的解决方法。
昨天写了写运动目标检测的各种方法,今天写一下跟踪部分。
相对于单一的图像,运动目标的跟踪是计算机视觉的另一个重点。从跟踪目标的多少来看,跟踪可分为单目标跟踪和多目标跟踪;从是否需要在不同的镜头中跟踪到同一个目标来看,跟踪可分为单镜跟踪和跨镜跟踪。
目标跟踪算法研究难点与挑战:实际复杂的应用环境 、背景相似干扰、光照条件的变化、遮挡等外界因素以及目标姿态变化,外观变形,尺度变化、平面外旋转、平面内旋转、出视野、快速运动等。还有,实时性也是十分关键的问题。
当然,跟踪准的前提是检测准,跟踪快的前提是检测快,毕竟一切的跟踪必须建立在检测的基础之上。(好的检测是跟踪的一半,十分重要!!!)检测的方法我个人最推荐YOLOv3/4/5,在确保实时性的基础上准确性也很好。
假设检测部分已经做好了,现在开始写如何跟踪。
从单镜单目标跟踪写起。
假设我们在连续两帧分别检测到了一个物体,如何让计算机知道它们是不是同一个呢?很自然的想法,我们可以取两个检测框的中心,如果它们相距不太远(小于一个阈值),则判定它们是一个物体;反之,判定它们不是一个物体。
事实上,这个想法已经能解决大部分场景下的跟踪了。然而,面临遮挡、快速运动以及检测算法并非百分之百准确的各种问题,这个简单的质心跟踪想法还有很大的提升空间。
比较好的方法,一般而言有最重要的两个部分:
- 运动模型:预测下一帧目标的区域。例如Mean shift、Kalman Filter等等;
- 外观模型:在当前帧中判决目标位置是运动模型预测到的位置的可能性,最终确定目标的位置。
目前而言,opencv库中内置了七个tracker,分别是:
- CSRT: cv2.TrackerCSRT_create
- KCF: cv2.TrackerKCF_create
- BOOSTING: cv2.TrackerBoosting_create
- MIL: cv2.TrackerMIL_create
- TLD: cv2.TrackerTLD_create
- MEDIANFLOW: cv2.TrackerMedianFlow_create
- MOSSE: cv2.TrackerMOSSE_create
BOOSTING是基于Haar和Adaboost的跟踪方法,过时已久,不建议使用;
MIL比BOOSTING准确一些,但跟踪错误时的纠错机制很差,不建议使用;
KCF(Kernelized Correlation Filters)比MIL和BOOSTING更加准确快速,但处理遮挡时效果不好;
CSRT比KCF更加准确,但比KCF稍慢一些;
TLD极其容易出现假阳性的情况,有人认为是opencv在实现过程中存在问题,不建议使用;
MEDIANFLOW纠错水平一流,但处理快速运动时效果不好;
MOSSE是这七个中运行最快的,但准确性不如MIL、KCF和CSRT。
个人意见,如果需要使用的话,从CSRT、KCF、MOSSE中三选一。如果要求极好的实时性,建议用MOSSE;如果要求极高的准确性,建议用CSRT;如果两者并重,建议用KCF。
当然,如果不是调用opencv的内置方法,而是调用这些跟踪方法的源码,那么把其中两三种方法组合使用的效果会更好。例如先使用KCF,响应值过低(存在遮挡)时改用CSRT,遮挡消失后再切回KCF;或者先使用MIL,一旦可能出错时使用MEDIANFLOW纠错,然后再切回MIL,等等。
这些是单目标跟踪方法,那多目标如何处理?其实很简单,把这些目标当成一个个的单目标处理即可。具体到代码,可以一个目标定义一个class,class内定义自己的tracker。这些方法的计算量不是太大,使用在多目标上也完全可以做到实时处理。
但是这些opencv内置的跟踪方法还不是最好的,个人认为最佳的当属deepsort。
- 运动模型:kalman filter
- 外观模型:匈牙利算法
具体而言,通过kalman filter预测下一帧的目标位置,再通过匈牙利算法对检测到的物体与预测到的目标位置进行级联匹配和IOU匹配。在这里我也不细讲了,想了解的可以看看这篇博客:Deep sort算法代码解读
单镜跟踪基本上写完了,跟踪完成之后轨迹点的处理问题,放在最后写。
跨镜跟踪与单镜跟踪的思路完全不同,它最大的难点在于如何在不同的镜头中判定两个物体是不是同一个目标。同一个目标在不同镜头中的角度、大小、位置可能是完全不同的,该如何处理呢?这个问题显然无法通过刚才的方法来解决了,只能通过神经网络进行训练。
目前看到最好的方法是siamnet(孪生网络),通过把连续两帧的图像块放入CNN中进行特征提取,根据其相似度判决是否存在同一个目标。
然而,目前的跨镜跟踪只能做到处理单目标,跨镜多目标跟踪还是个无解难题。如果给所有目标分别创建一个基于神经网络的跟踪器,那么程序的计算量会很大,运行极为缓慢,根本无法做到实时处理。我自己试了一下,用两块GPU,结果一分钟只处理了两帧……
最后写一下跟踪完成后轨迹点处理的问题。如果目标的轨迹选取为各帧检测框中心的集合,由于检测方法自身的问题(例如物体大小和角度的变化造成检测框中心位置的变化),会导致轨迹点之间的间距十分不平滑,从而对后续处理造成不良影响(例如检测车辆急加速)。
解决这个问题,需要分为两步处理:
- 我们默认目标在短时间内做匀速直线运动,因此使用savgol filter对连续N帧的轨迹做平滑处理(N根据实际需求选取)。Savgol filter的原理是使用高次多项式拟合轨迹点,python的scipy.signal库中内置了这一方法,可以调用。
- 把轨迹点分组,连续N个一组,使用exponentially weighted averges方法平滑组与组的间距。公式为:
最后,还是想再强调一句,好的检测是跟踪的一半,检测的准确性对于跟踪至关重要,如果跟踪存在问题,而且找不到解决方法的时候,一定要去优化一下检测的方法。
发表评论
登录后可评论,请前往 登录 或 注册