使用光流进行特征跟踪

Feature tracking using optical flow

本文关键字:特征 跟踪 光流      更新时间:2023-10-16

我在论坛中发现了类似的问题。但是那里的答案并没有回答我的问题。

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

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

我正在使用光流进行3D重建。 所以我对跟踪哪些特征不感兴趣,而是只关心视野中的特征是否可以稳定跟踪。总而言之,我的问题是:如何使用光流来跟踪旧特征,同时添加进入视野的新图像特征并删除超出视野的旧特征?

有几种方法。一个好方法是这样的:

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

在这种方法中,基本上您可以估计最后两个关键帧之间的相机运动。

由于您没有提到使用什么方法进行3D重建,因此我假设首先计算HF以估计运动。为了准确估计它们,关键帧之间的基线应尽可能宽。通常,最佳策略是考虑相机的粗略运动模型。如果用手握住相机,则与将相机固定在汽车或机器人顶部时相比,应使用不同的策略。如果有帮助,我可以在 Python 中提供一个最小的工作示例,请告诉我。

仅出于文档目的,光流跟踪有几个很好的GPU/C++实现。您的代码可能更适合您的目的,但如果您只需要轨道的输出数据,请考虑检查以下任何来源:此处、此处或此处。

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

我还建议限制功能的数量。假设您将其限制为 MAX_FEATURES = 300 .然后,您检查每个周期的曲目是否少于MAX_FEATURES - z (e.g. z = 30)。如果您这样做,请如上所述搜索最多 z 个新功能,并将它们添加到您的功能容器中。

另请注意,当追踪失败时,您必须主动删除要素。因此,您必须查看 calcOpticalFlowPyrLK 的状态输出。