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

9

[在标记为重复或投票反对之前,请阅读问题细节。我已经彻底搜索过,找不到解决方案,因此在此发布问题。]

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

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

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步遇到问题,无法删除错误的匹配项。

所以你已经找到了一张图片的多个匹配项,现在想要找到前k个最佳匹配项? - Simson
是的,我能够找到匹配项。我将k设置为20,因为我想找到“所有”相似的图像。 - milan m
好的,所以你基本上想要在你的k个最佳结果中找到假阳性?你之前不是已经问过这个问题了吗?(https://dev59.com/Un7aa4cB1Zd3GeqPq36h) - Simson
最初,我在提出那个问题时使用了BruteForce匹配器。使用BruteForce匹配器,我能够消除误报并获得良好的结果。不幸的是,使用BruteForce匹配器的速度非常慢。现在我正在使用FLANN匹配器,但又陷入了同样的困境。 - milan m
@Unapiedra,我正在尝试查找一个文件夹中的重复图像。该文件夹包含5000张图片。我的解决方案与我在问题中提到的链接完全相似。唯一的区别是我想要找到多个匹配的图像,而不是最佳的一个。 - milan m
显示剩余2条评论
2个回答

12

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

使用不同的方法

您想找到给定查询图像的重复项。传统上,您可以通过比较全局图像描述符而不是本地特征描述符来完成此操作。

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

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

好处是您会获得更稳健的结果(取决于现在执行的实现方式),并且匹配通常更快。

使用您的方法

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

您无法从FLANN(123)中删除点。 FLANN构建一个树以进行快速搜索。根据树的类型,删除节点变得不可能。猜猜看,FLANN使用KD树,它不容易允许删除点。

FlannBasedMatcher不支持掩码描述符集的合法匹配,因为flann :: Index不支持此操作。

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

编辑

我还应该指出,您可以重新构建flann-tree。显然,这样做会带来性能损失。但是,如果您有大量查询并且某些特征经常出现误报,那么进行一次重建可能是有意义的。

为此,您需要使用函数DescriptorMatcher :: clear(),然后使用DescriptorMatcher :: add(const vector<Mat>& descriptors)参考资料


我尝试了第二种方法。它没有移除假阳性。 :-( - milan m

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的距离

不足匹配_k=匹配距离_k >= 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

我将提供有关OpenCV图像处理库中阈值函数的链接。


我使用了BruteForce匹配器和Flannn匹配器来开发我的应用程序。使用BF匹配器得到的结果是完美的。我希望能够在FLANN中获得同样的结果。选择Flann而不是BF匹配器的明显原因是速度。 - milan m
@milanm FLANN是一种近似算法,您可以调整其参数以在速度和准确性之间进行权衡。 - QED
@milanm FLANN参数文档。http://docs.opencv.org/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html#flann::Index_,http://docs.opencv.org/modules/flann/doc/flann_fast_approximate_nearest_neighbor_search.html#flann-index-t-knnsearch - QED

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接