为什么我们需要crossCheckMatching功能?

时间:2012-06-24 22:50:30

标签: c++ opencv sift surf

我正在阅读很多使用特征提取(sift ecc)进行物体检测的帖子。

在两个图像上计算描述符之后,为了获得良好的匹配,他们使用了crossCheckMatching。 (见sample/cpp/descritpor_extractor_matcher.cpp

Coudl我理解为什么选择这个?

为什么我们需要评估两者

descriptorMatcher->knnMatch( descriptors1, descriptors2, matches12, knn );
descriptorMatcher->knnMatch( descriptors2, descriptors1, matches21, knn );

我不明白。

例如,计算欧几里德距离并不会在两个方向上返回相同的结果

2 个答案:

答案 0 :(得分:21)

您通常不能假设您的匹配器将使用Eucludian距离。例如,BFMatcher支持不同的规范:L1,L2,Hamming ......

您可以在此处查看文档以获取更多详细信息:http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html

无论如何,所有这些距离测量都是对称的,并且您使用哪一个来回答您的问题并不重要。

答案是:调用knnMatch(A,B)与调用knnMatch(B,A)不同。

如果你不相信我,我会尝试给你一个图形和直观的解释。为了简单起见,我假设knn==1,因此对于每个查询的描述符,算法只能找到1个对应关系(更容易绘制: - )

我随机挑选了几个2D样本并创建了两个数据集(红色和绿色)。在第一个图中,绿色在查询数据集中,这意味着对于每个绿点,我们尝试找到最接近的红点(每个箭头代表一个对应关系)。

在第二个图中,查询&列车数据集已被交换。

最后,我还绘制了crossCheckMatching()函数的结果,该结果仅保留了双向匹配。

Figure 1

正如您所看到的,crossCheckMatching()的输出比每个knnMatch(X,Y)/ knnMatch(Y,X)要好得多,因为只保留了最强的对应关系。

答案 1 :(得分:2)

我没有处理您正在使用的确切模块,但是来自文档:

http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html

似乎第二个调用是使用查询交换训练,因此可以为您提供不同的结果集。这也通过match12的命名改为match21来暗示 - 它不是双向关联,而是方向关联。

您可以在机器学习中训练大型数据集时看到这一点,在这些数据集中,您可以在结果中训练一个数据子集,而不是在不同数据子集上进行训练。我不知道在您编写的步骤后如何使用这两个匹配,但我认为它允许选择最佳训练,或者从数据中捕获更好的协方​​差信息。

欧几里德距离在两个方向上是相同的,但双向量的排序发生变化,因此两个调用之间的关联结构发生变化(除非描述符1 == descriptors2,它们会形成对称矩阵,然后可能对于重复)。

稍后在代码库中发布match12和matches21的使用可能也会澄清两个方向关联的确切原因。

希望这为理解重复呼叫提供了一个起点。

* 编辑 *

我查看了您提供链接的源代码并回答了您的问题,两点之间的距离是相同的,但是特定点(点A)与另一个特定点(点B)的最近点不一定是可以反驳的陈述。因此B可能是最接近A的点,但A可能不是最接近B的点。

Frédéric的帖子以图形方式显示,并不是欧几里德距离在2点之间变化,而是在改变比较视角时,欧几里德距离最近的点可能会发生变化。因此,交叉检查可以验证共享最近点关系的点(A最接近B,B最接近A)。

你的直觉认为这不是最好的方法(有大量的点)是正确的,因为更复杂的方法可以在O(N * ln(N))时间内找到所有这样的关系而不是O(N ^ 2)时间 - 尤其是启发式驱动搜索。但是对于(相对)少量的点,预期的性能增益可以忽略不计,并且实现(很多是为了良好的改进)更复杂。