[请您在标记为重复或投反对票之前阅读问题详细信息。]
我试图将一个图像与多个图像进行比较,并获得所有匹配图像的列表。我不想在图像之间画关键点。
我的解决方案是基于以下源代码:
https://github.com/Itseez/opencv/blob/master/samples/cpp/matching_to_many_images.cpp上面的源代码将一个图像与多个图像进行匹配,并得到最佳匹配图像
我已经修改了上面的示例并生成: vector<vector<DMatch>> matches;
vector<vector<DMatch>> good_matches;
现在我的问题是我如何应用最近邻搜索比例来获得多个图像的良好匹配?
编辑1:
我的实现如下:
对于数据集中的每张图像,计算SURF描述符
将所有描述符组合成一个大矩阵
从连接矩阵建立FLANN索引。
计算查询图像的描述符
在FLANN索引上运行KNN搜索,找到前20个或更少的最佳匹配图像。K设为20
过滤掉上一步计算的所有不匹配项。(如何?)
我已经成功地完成了步骤1到5。我面临的问题在第6步,其中我无法删除虚假的比赛。
你的问题有两个答案。第一个答案是你应该使用一种完全不同的技术,第二个答案是如何真正做到你所要求的。
使用不同的方法
您想要查找给定查询图像的副本。传统上,您通过比较全局图像描述符而不是本地特性描述符来完成此操作。
要做到这一点,最简单的方法是将本地特征描述符聚合成一个本地描述符。这里的标准方法是"视觉词汇袋"。在OpenCV中,这被称为词袋(如BOWTrainer
, BOWImgDescriptorExtractor等)。请查看使用此功能的文档。
samples/cpp/bagofwords_classification.cpp
的好处是您将获得更健壮的结果(取决于您现在正在做的实现),并且匹配通常更快。
使用你的方法
我明白你想从输入中删除导致匹配误报的点。
你不能从FLANN(1,2,3)中删除点。FLANN建立了一个快速搜索的树。根据树的类型,删除节点是不可能的。你猜怎么着,FLANN使用的kd树不允许(容易地)删除点。
FlannBasedMatcher不支持屏蔽描述符集的允许匹配,因为flann::Index不支持。
我建议使用半径搜索而不是普通搜索。或者,查看找到的匹配的l2距离,并在代码中编写一个函数,以查看距离是否低于阈值。
编辑
我还应该注意到你可以重建你的flanntree。显然,这样做会降低性能。但是如果你有大量的查询和一些功能经常出现误报,那么这样做一次可能是有意义的。
您需要DescriptorMatcher::clear()
和DescriptorMatcher::add(const vector<Mat>& descriptors)
函数。Referenz .
首先你需要定义"不充分匹配",没有这个定义你什么都做不了。
有几个松散的定义浮现在脑海中:
1: matched = match with distance>预定义距离
在这种情况下,弗兰半径搜索可能更合适,因为它只会给你那些从目标到预定义半径内的索引:
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 = match distance_k>= a *基距;
2b:对k-nn的距离归一化分布使用动态阈值技术,如Otsu阈值,从而将k-nn分为两组,包含1-nn的组为充分组,另一组为不充分组。
http://en.wikipedia.org/wiki/Otsu 's_methodhttp://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html阈值。