我在论坛中发现了类似的问题。但是那里的答案并没有回答我的问题。
-
如果我只在第一张图像上做一次特征检测(goodFeaturesToTrack),然后使用光流(calcOpticalFlowPyrLK)来跟踪这些特征,问题是:只能在第一张图像上检测到的特征才能被跟踪。当这些特征超出图像范围时,将没有要跟踪的特征。
-
如果我对每个新图像进行特征检测,则特征跟踪不稳定,因为上次检测到的特征这次可能无法检测到。
我正在使用光流进行3D重建。 所以我对跟踪哪些特征不感兴趣,而是只关心视野中的特征是否可以稳定跟踪。总而言之,我的问题是:如何使用光流来跟踪旧特征,同时添加进入视野的新图像特征并删除超出视野的旧特征?
有几种方法。一个好方法是这样的:
- 在第 1 帧中检测 N 个特征,这是关键帧 m=1
- 在帧 k 中通过光流跟踪特征
- 如果成功追踪的要素数低于 N/2,则在帧 k 中:
- 此帧是关键帧 M+1
- 计算描述关键帧 m 和 m+1 之间运动的单应性或基本矩阵
- 检测 N 个特征并丢弃旧特征
- k := k+1 转到 2
在这种方法中,基本上您可以估计最后两个关键帧之间的相机运动。
由于您没有提到使用什么方法进行3D重建,因此我假设首先计算H或F以估计运动。为了准确估计它们,关键帧之间的基线应尽可能宽。通常,最佳策略是考虑相机的粗略运动模型。如果用手握住相机,则与将相机固定在汽车或机器人顶部时相比,应使用不同的策略。如果有帮助,我可以在 Python 中提供一个最小的工作示例,请告诉我。
仅出于文档目的,光流跟踪有几个很好的GPU/C++实现。您的代码可能更适合您的目的,但如果您只需要轨道的输出数据,请考虑检查以下任何来源:此处、此处或此处。
还有另一种向现有功能添加新功能的好方法。您可以将掩码传递到cv::goodFeaturesToTrack()
中。因此,您将创建一个新的垫子(与原始图像的大小相同,type: CV_8UC1
),将所有像素设置为 255,并将每个特征点作为黑色圆圈绘制到此垫子中。当您将此掩码传递到goodFeaturesToTrack()
函数将跳过这些黑色圆圈时。
我还建议限制功能的数量。假设您将其限制为 MAX_FEATURES = 300
.然后,您检查每个周期的曲目是否少于MAX_FEATURES - z (e.g. z = 30)
。如果您这样做,请如上所述搜索最多 z 个新功能,并将它们添加到您的功能容器中。
另请注意,当追踪失败时,您必须主动删除要素。因此,您必须查看 calcOpticalFlowPyrLK
的状态输出。