使用光流进行特征跟踪

24

我在论坛中找到了一个类似的问题,但那里的答案并没有回答我的问题。

  • 如果我只在第一张图像上进行特征检测(goodFeaturesToTrack),然后使用光流(calcOpticalFlowPyrLK)来跟踪这些特征,问题是:只有在第一张图像上检测到的特征可以被跟踪。当这些特征超出图像范围时,就没有特征可以跟踪了。

  • 如果我为每个新图像进行特征检测,则特征跟踪不稳定,因为上次检测到的特征可能无法再次检测到。

我正在使用光流进行3D重建。因此,我对追踪哪些特征不感兴趣,我只关心视野中的特征能否得到稳定地跟踪。总之,我的问题是:如何使用光流跟踪旧特征,并同时添加进入视野的新图像特征和移除超出视野的旧特征?


因为这个老问题中没有提到,lkdemo的Python版本比其C++版本多做了一些事情,可以看看这个链接,也许对某些人有帮助:https://github.com/npinto/opencv/blob/master/samples/python/lkdemo.py - Stefan Karlsson
3个回答

19

有几种方法可行。一个好的方法是:

  1. 在第1帧中检测N个特征点,这是关键帧 m=1
  2. 在帧k中通过光流跟踪特征点
  3. 在帧k中,如果成功跟踪的特征点数下降到小于N/2:
    • 这一帧是关键帧 m+1
    • 计算描述关键帧m和m+1之间运动的单应性或基本矩阵
    • 检测N个特征点并丢弃旧的特征点
    • k := k+1 转到 2

在该方法中,基本上你需要估计最后两个关键帧之间的相机运动。

由于您没有提及用于3D重建的方法,我假设首先计算了 HF 来估计运动。为了准确估计它们,关键帧之间的基线应尽可能宽。一般来说,最好考虑相机的粗略运动模型。如果相机手持,应使用与将相机固定在汽车或机器人顶部时不同的策略。 如果需要,我可以提供Python的最小工作示例,请告诉我。


谢谢。这似乎是一个不错的解决方案。我使用C++。无论如何,感谢您的慷慨提供。 - Shiyu
@fireant 感谢您的答复。如果您能为我提供一个Python示例,我会很高兴的。 - Clive
@Clive,虽然已经晚了近2年,但我希望这能对某些人有所帮助! 代码 魔法发生在更新特征后的注释行之后。大部分源代码与OpenCV文档相同,可以在此处阅读。 - Rishabh Bhardwaj

3

仅供文档用途,有几个GPU/C++实现的光流跟踪方法很好。你的代码可能更适合你的目的,但如果你只需要轨迹的输出数据,请考虑查看以下任何来源:这里这里这里


0

有另一种很好的方法可以为现有功能添加新功能。您可以将掩码传递到cv::goodFeaturesToTrack()中。因此,您将创建一个新的Mat(与原始图像相同大小,type: CV_8UC1),将所有像素设置为255,并将每个特征点绘制为黑色圆形到此Mat中。当您将此掩码传递到goodFeaturesToTrack()中时,该函数将跳过这些黑色圆圈。

我还建议限制要素的数量。假设您将其限制为MAX_FEATURES = 300。然后,您每个周期都会检查是否少于MAX_FEATURES - z(例如z = 30)。如果是这样,请按上述方式搜索多达z个新功能,并将它们添加到您的功能容器中。

还请注意,当跟踪失败时,您必须积极删除功能。因此,您将不得不查看calcOpticalFlowPyrLK的状态输出。


这是一种非常好的方法,但我注意到使用掩码比使用整个图像要慢。我无法相信,但至少在3.2版本中发生了这种情况。 - Pablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接