【问题标题】:Why we need crossCheckMatching for feature?为什么我们需要 crossCheckMatching 作为特征?
【发布时间】:2012-06-24 22:50:30
【问题描述】:

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

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

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

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

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

我不明白。

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

【问题讨论】:

    标签: c++ opencv sift surf


    【解决方案1】:

    您通常不能假设您的匹配器会使用欧几里得距离。例如,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() 函数的结果,它只保留了双向匹配。

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

    【讨论】:

    • Frederic 首先感谢您的出色回答!但是,考虑到我们使用的是 BruteForceMatcher,所以基本上每个描述符都与其他所有描述符进行比较,此时 knnMatch(A,B) 应该与 knnMatch(B,A) 相同,你不觉得吗?
    • 另外,假设它们返回不同的结果。但是为了只保留好的匹配而不是再次运行 knnMatch 对匹配运行简单的 ratioTest 不能更好更快吗?
    • 根据文档,对于每个查询的描述符,BruteForceMatcher 都会在训练集中找到最接近的描述符。我在回答中使用的特殊情况“knn==1”没有区别。
    • 对于第二个问题,我刚刚注意到 BFMatcher(与 BruteForceMatcher 不同)构造函数采用“crossCheck”布尔参数。它似乎是 crossCheckMatching() 的内置版本。看看:docs.opencv.org/modules/features2d/doc/…
    • 哇,这解释了很多。引用:If it is false, this is will be default BFMatcher behaviour when it finds the k nearest neighbors for each query descriptor. If crossCheck==true, then the knnMatch() method with k=1 will only return pairs (i,j) such that for i-th query descriptor the j-th descriptor in the matcher’s collection is the nearest and vice versa, i.e. the BFMathcher will only return consistent pairs. Such technique usually produces best results with minimal number of outliers when there are enough matches. This is alternative to the ratio test, used by D. Lowe in SIFT paper.
    【解决方案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)时间——尤其是启发式驱动的搜索。但是对于(相对)少量的点,预期的性能提升可以忽略不计,并且实现会(为了更好的改进)更加复杂。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2014-06-18
    • 2017-02-26
    • 2011-04-03
    • 2017-07-27
    • 2020-09-21
    • 2020-03-09
    相关资源
    最近更新 更多