8

[请您在将问题标记为重复或否决之前阅读问题详细信息。我已经彻底搜索,找不到解决方案,因此在这里发布问题。]

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

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

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. 过滤掉上一步计算的所有不充分匹配。(如何??)

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

4

2 回答 2

12

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

使用不同的方法

您想查找给定查询图像的重复项。传统上,您通过比较全局图像描述符而不是局部特征描述符来做到这一点。

最简单的方法是将局部特征描述符聚合到局部描述符中。这里的标准方法是“视觉词袋”。在 OpenCV 中,这称为 Bag-Of-Words(如BOWImgDescriptorExtractorBOWTrainer等)。查看使用它的文档。

有一些示例代码samples/cpp/bagofwords_classification.cpp

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

使用你的方法

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

您不能从 FLANN( 1 , 2 , 3 ) 中删除点。FLANN 为快速搜索构建了一个树。根据树的类型,删除节点变得不可能。你猜怎么着,FLANN 使用了一个 KD-tree,它(很容易)不允许删除点。

FlannBasedMatcher 不支持屏蔽描述符集的允许匹配,因为 flann::Index 不支持这一点。

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

编辑

我还应该注意,你可以重建你的 flann-tree。显然,这样做会降低性能。但是,如果您有大量查询并且某些功能经常出现误报,那么执行一次可能是有意义的。

您需要这些功能DescriptorMatcher::clear(),然后DescriptorMatcher::add(const vector<Mat>& descriptors)为此。参考

于 2014-06-13T15:53:15.213 回答
6

首先你需要定义“不充分的匹配”,没有这个定义你什么都做不了。

有几个松散的定义浮现在脑海中:

1:匹配不足=距离匹配>预定义距离

在这种情况下,flann 半径搜索可能更合适,因为它只会为您提供目标预定义半径内的那些索引:

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

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

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

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

基本距离 = 到 1NN 的距离

不足的 match_k = 匹配 distance_k >= a * 基本距离;

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

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

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

于 2014-06-11T15:43:28.747 回答