如何从OPENCV中的FLANNBASED Matcher中删除错误匹配?

时间:2014-06-06 17:47:28

标签: c++ opencv sift surf flann

[请求您在标记重复或向下投票之前阅读问题详细信息。我已经彻底搜索过,无法找到解决方案,因此在此处发布问题。]

我正在尝试将一个图像与多个图像进行比较,并获得所有匹配图像的列表。我不想在图像之间绘制关键点。

我的解决方案基于以下源代码:

https://github.com/Itseez/opencv/blob/master/samples/cpp/matching_to_many_images.cpp

以上源代码将一张图片与多张图片进行匹配,并获得最佳匹配图片。

我修改了上面的示例并生成了:

 vector<vector<DMatch>> matches;
 vector<vector<DMatch>> good_matches;

现在我的问题是如何应用最近邻搜索比率以获得多个图像的良好匹配?

修改1:

我的实施如下:

  1. 对于数据集中的每个图像,计算SURF描述符。

  2. 将所有描述符合并为一个大矩阵。

  3. 从连续矩阵构建FLANN索引。

  4. 查询图像的计算描述符。

  5. 在FLANN索引上运行KNN搜索,以查找前20个或更少最佳匹配图像。 K设为20。

  6. 过滤掉上一步计算出的所有不匹配的匹配项。 (如何?)

  7. 我已成功完成第1步到第5步。我在第6步遇到问题,我无法删除错误的匹配。

2 个答案:

答案 0 :(得分:12)

您的问题有两个答案。第一个是你应该使用完全不同的技术,第二个答案是如何实际做你要求的。

使用其他方法

您想要查找给定查询图像的重复项。传统上,您通过比较全局图像描述符而不是本地功能描述符来实现此目的。

最简单的方法是将本地特征描述符聚合到本地描述符中。这里的标准方法是&#34;视觉词袋&#34;。在OpenCV中,这称为Bag-Of-Words(如BOWTrainerBOWImgDescriptorExtractor等)。看一下使用它的文档。

samples/cpp/bagofwords_classification.cpp

中有一些示例代码

好处将使您获得更强大的结果(取决于您现在正在执行的操作),并且匹配通常更快。

使用您的方法

我了解您要从输入中删除导致匹配误报的点。

您无法从FLANN(123)中删除积分。 FLANN构建了一个用于快速搜索的树。根据树的类型,删除节点变得不可能。猜猜看,FLANN使用的KD树没有(很容易)允许删除点。

  

FlannBasedMatcher不支持屏蔽允许的描述符集匹配,因为flann :: Index不支持此功能。

我建议使用半径搜索而不是普通搜索。或者,查看找到的匹配项的L2距离,并在代码中编写一个函数,以查看距离是否低于阈值。

修改

我还应该注意你可以重建你的flann树。显然,这样做会带来性能损失。但是,如果你有大量的查询和一些特征以误报方式出现,那么这样做可能是有意义的。

您需要功能DescriptorMatcher::clear(),然后DescriptorMatcher::add(const vector<Mat>& descriptors)Referenz

答案 1 :(得分:6)

首先,您需要定义“不匹配”,如果没有此定义,您将无法执行任何操作。

有几个松散的定义让人想起:

1:匹配不足=与距离匹配&gt;预定距离

在这种情况下,法兰半径搜索可能更合适,因为它只会给出目标预定义半径范围内的那些索引:

http://docs.opencv.org/trunk/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html#flann-index-t-radiussearch

2:匹配不足=与距离匹配&gt;动态定义的距离基于检索到的k-nn

这更棘手,我可以想到两个可能的解决方案:

2a:根据第一个1-NN的距离定义一些比率测试,如:

基准距离=到1NN的距离

match_k = match distance_k&gt; = a *基本距离;

2b:使用动态阈值技术,例如Otsu阈值对k-nn的距离的归一化分布,从而将k-nn分成两组,包含1-nn的组是适当的组,另一个是不充分的群体。

http://en.wikipedia.org/wiki/Otsu's_method,

http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#threshold