如何使用FLANN优化多幅图片的SIFT特征匹配?
我有一个从Python OpenCV文档中获取的工作示例。然而,这是比较一个图像与另一个,它是缓慢的。我需要它来搜索在一系列图像(几千)匹配的特征,我需要它更快。
我现在的想法:
- 浏览所有图像并保存特征。如何?
- 将相机的图像与上面的基础进行比较,并找到正确的图像。如何?
- 给我结果,匹配图像或其他。
在尝试了许多方法之后,我现在可能已经接近解决方案了。我希望可以建立索引,然后像这样搜索:
<>之前Flann_params = dict(算法=1,树=4)Flann = cv2。flann_Index (npArray flann_params)Idx, dist = flann。knnSearch(queryDes, 1, params={})之前然而,我仍然没有设法建立一个可接受的npArray到flann_Index参数
<>之前循环遍历所有图像为image:npArray.append (sift.detectAndCompute(图片,没有)npArray = np.array(npArray)我从未在Python中解决过这个问题,但是我将环境切换到c++,在那里您可以获得更多的OpenCV示例,并且不必使用具有较少文档的包装器。
关于我在多个文件中匹配的问题的一个例子可以在这里找到:https://github.com/Itseez/opencv/blob/2.4/samples/cpp/matching_to_many_images.cpp
随着@stanleyxu2005的回复,我想添加一些关于如何做整个匹配本身的技巧,因为我目前正在做这样的事情。
- 我强烈建议创建一些自定义类来包装cv::Mat,但也存储各种其他必要的数据。在我的例子中,我有一个ImageContainer存储原始图像(我将用于最终拼接),处理后的图像(灰度化,未失真等),其关键点和描述符。通过这样做,您可以以非常有组织的方式访问所有匹配相关的信息。您可以在其中实现关键点提取和描述符生成,也可以在类之外实现,并将结果存储在该容器中。
- 将所有图像容器存储在某种结构中(vector通常是一个不错的选择),以便于访问。
- 我还创建了一个名为ImageMultiMatchContainer的类,它存储一个指向给定查询图像的指针(所有图像都是查询图像),一个指向与之匹配的所有火车图像的指针的向量(对于图像集的单个查询图像,所有其他图像都是火车图像),以及每个匹配的匹配向量的向量。在这里,我偶然发现了一个存储问题——首先,你必须跳过图像与自身的匹配,因为这是毫无意义的;其次,你有两个图像进行两次比较的问题,从而产生相当大的开销,如果你有很多图像。第二个问题是由于我们遍历所有图像(查询图像)并将它们与集合中的其余图像(火车图像)进行比较。在某一点上,我们有图像X(查询)与图像Y(训练)匹配,但稍后我们也有图像Y(现在查询)与图像X(现在训练)匹配。正如你所看到的,这也是毫无意义的,因为它基本上是将同一对图像匹配两次。这可以通过创建一个类(MatchContainer)来解决(目前正在解决这个问题),该类存储一个指向匹配对中的两个图像中的每个图像的指针以及匹配向量。您将其存储在中心位置(在我的示例中,这是我的matcher类),并且对于作为查询图像的每个图像,您检查火车图像的匹配图像列表。如果它是空的,那么你创建一个新的MatchContainer并将它添加到MatchContainer的其余部分。如果不是,那么查看它,看看当前查询图像是否不在那里(比较指针是一个快速的操作)。如果是,那么你就把指针传递给那个MatchContainer的vector项目,它存储了那两个图像的匹配。如果不是这样,你做,如果它是空的,并创建一个新的MatchContainer等。MatchingContainers应该存储在访问时间短的数据结构中,因为您将经常查看它们,并且从头到尾迭代花费太多时间。我正在考虑使用地图,但也许某种类型的树也可以提供一些优势。
- 单应性估计是一个非常棘手的部分。这里我建议您查看包块调整。我看到OpenCV中的stitcher类有一个bundlebase类,但还没有测试它,看看里面有什么。
一般的建议是查看OpenCV中的拼接过程并阅读源代码。拼接流水线是一组直接的流程,您只需要了解如何精确地实现单个步骤。
以下是我的几点建议:
- 你应该通过使用适当的技术来减少点数据的数量。
- 重复计算参考图像是浪费。应该持久化所有计算过的引用。
- 不要把计算放到移动设备上。您最好将捕获的图像的计算引用上传到功能强大的服务器,并在那里进行搜索。
这是一个非常有趣的话题。我的耳朵也张开了。