我对使用OpenCV制作运动跟踪应用程序很感兴趣,在网上有大量的信息可用。然而,我在特征匹配和使用稀疏光流算法如Lucas-Kanade跟踪特征之间有些困惑。考虑到这一点,我有以下问题:
如果我指定了要跟踪的像素区域,那么两者(特征匹配和光流)之间的主要区别是什么?我不关心实时跟踪,如果这有助于澄清任何假设。
此外,既然我不进行实时跟踪,那么使用密集光流(Farneback)来跟踪我指定的兴趣区域中的像素是否是更好的主意?
谢谢。
我对使用OpenCV制作运动跟踪应用程序很感兴趣,在网上有大量的信息可用。然而,我在特征匹配和使用稀疏光流算法如Lucas-Kanade跟踪特征之间有些困惑。考虑到这一点,我有以下问题:
如果我指定了要跟踪的像素区域,那么两者(特征匹配和光流)之间的主要区别是什么?我不关心实时跟踪,如果这有助于澄清任何假设。
此外,既然我不进行实时跟踪,那么使用密集光流(Farneback)来跟踪我指定的兴趣区域中的像素是否是更好的主意?
谢谢。
我很感兴趣这个问题,想分享一些相关思路。如前所述,特征匹配是一种技术,基于以下步骤:
特征检测阶段会返回一组所谓的特征点。这些特征点位于显著的图像结构位置,例如使用FAST时类似于边缘的结构或使用SIFT或SURF时类似于斑点结构。
第二步是匹配。将从两个不同图像中提取的特征点进行关联。匹配基于局部视觉描述符,例如梯度直方图或二进制模式,这些描述符在特征位置周围被局部提取。描述符是一个特征向量,并且相关特征点对是具有最小特征向量距离的点对。
大多数特征匹配方法是尺度和旋转不变的,并且对照明变化(例如由阴影或不同对比度引起的)具有强大的适应性。因此,这些方法可以应用于图像序列,但通常更常用于不同视角或使用不同设备捕获的图像配准。特征匹配方法的缺点是难以定义匹配特征发生在哪里,并且特征对(在图像序列中是运动向量)通常非常稀疏。此外,由于大多数检测器被细分到整数位置,因此匹配方法的亚像素精度非常有限。
根据我的经验,特征匹配方法的主要优势是它们可以计算出非常大的运动/ 位移。
OpenCV提供了一些特征匹配方法,但在线上有许多更新、更快速和更精确的方法可用,例如:
相比之下,光流 方法依赖于亮度恒定的最小化和额外的约束条件,例如平稳性等。因此,它们基于连续帧序列的空间和时间图像梯度导出运动向量。因此,它们更适合于图像序列,而不是从非常不同的视角拍摄的图像对。使用光流向量估计运动的主要挑战是大运动、遮挡、强烈光照变化和物体外貌变化,以及主要是低运行时间。然而,光流方法可以非常准确地计算出与场景中物体共享运动边界相关的密集运动场。
但是,不同光流方法的准确性差异很大。通常来说,诸如PLK(Lucas Kanade)之类的局部方法不太精确,但允许仅计算预先选择的运动向量,并且因此非常快速。 (近年来,我们已经进行了一些研究以提高局部方法的准确性,有关更多信息,请参见此处)。
主要的OpenCV主干提供了全局方法,例如Farnback。但这是一种相当过时的方法。请尝试使用OpenCV contrib主干,其中包含更多最新的方法。但是,要获取最新方法的良好概述,请查看公共光流基准测试。在这里,您将找到代码和实现,例如:
但从我的角度来看,我不会在早期阶段拒绝与光学流匹配的特定方法。尽可能多地使用在线实现,并查看对于您的应用程序最佳的是什么。
光流算法不看描述符空间,而是查看围绕特征周围的像素块,然后尝试匹配这些块。如果您熟悉稠密光流,则稀疏光流仅在功能点周围的图像小区域上进行稠密光流。因此,光流假定亮度恒定,即像素亮度在帧之间不会改变。另外,由于您在查看相邻像素,所以需要假设相邻点与您的特征移动方式相似。最后,由于它在小区域上使用稠密流算法,所以它们移动的点不能远离原始特征位置的图像太远。如果是,则建议使用金字塔分辨率方法,在执行此操作之前缩小图像,以使曾经是16像素平移的现在是2像素平移,然后可以将找到的转换作为先验进行缩放。
cv::calcOpticalFlowFarneback
返回的结果的“形状”? - JDBonesimgPrev
和imgCur
的尺寸相同,这就不会在我的密集光流调用中失败某些断言。 - JDBones关键点匹配 = 稀疏光流
KLT跟踪是稀疏光流的一个很好的例子,可以查看演示LKDemo.cpp(它还有一些Python包装器示例,现在无法记住)。
对于密集示例,请参见samples/python/opt_flow.py,使用Farnebäcks方法。
你的困惑是正确的...整个世界都对这个非常简单的主题感到困惑。很大一部分原因是人们认为Lucas-Kanade是稀疏光流(由于OpenCV中一个名字和注释非常糟糕的示例:LKdemo,应该被称为KLTDemo)。