6

我正在阅读大量使用特征提取(sift ecc)进行对象检测的帖子。

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

我能理解为什么会这样选择吗?

为什么我们需要同时评估两者

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

我不明白。

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

4

2 回答 2

28

您通常不能假设您的匹配器将使用 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()只保留双向匹配的函数的结果。

图1

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

于 2012-07-14T15:23:02.303 回答
2

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

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

似乎第二个调用是用查询交换训练,因此可以给你一组不同的结果。将matches12 的命名更改为matches21 也暗示了这一点——这不是双向关联,而是方向关联。

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

欧几里得距离在两个方向上都是相同的,但是双向量的顺序会发生变化,因此两个调用之间的关联结构也会发生变化(除非描述符 1 == 描述符 2,这将形成一个对称矩阵,然后可能无法重复)。

稍后在代码库中发布matches12 和matches21 的使用可能也会阐明具有两个方向关联的确切原因。

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

*编辑*

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

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

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

于 2012-07-12T17:43:34.673 回答