多幅图像的OpenCV特征匹配

2024-06-28 19:47:24 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用FLANN优化许多图片的SIFT功能匹配?

我有一个来自Python OpenCV文档的工作示例。然而,这是比较一个图像与另一个,它是缓慢的。我需要它来搜索一系列图像(几千)中的特征匹配,我需要它更快。

我现在的想法:

  1. 运行所有图像并保存功能。怎样?
  2. 将相机的图像与上面的底片进行比较,找到正确的底片。怎样?
  3. 给我结果,匹配图像什么的。

http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html

import sys # For debugging only
import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10

img1 = cv2.imread('image.jpg',0) # queryImage
img2 = cv2.imread('target.jpg',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)

flann = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(des1,des2,k=2)

# store all the good matches as per Lowe's ratio test.
good = []
for m,n in matches:
    if m.distance MIN_MATCH_COUNT:
    src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
    dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)

    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
    matchesMask = mask.ravel().tolist()

    h,w = img1.shape
    pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
    dst = cv2.perspectiveTransform(pts,M)

    img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)

else:
    print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
    matchesMask = None

draw_params = dict(matchColor = (0,255,0), # draw matches in green color
                   singlePointColor = None,
                   matchesMask = matchesMask, # draw only inliers
                   flags = 2)

img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)

plt.imshow(img3, 'gray'),plt.show()

更新

在尝试了很多事情之后,我现在可能更接近解决方案了。我希望可以建立索引,然后像这样搜索:

flann_params = dict(algorithm=1, trees=4)
flann = cv2.flann_Index(npArray, flann_params)
idx, dist = flann.knnSearch(queryDes, 1, params={})

但是,我仍然没有成功地为flann_索引参数构建一个可接受的npArray。

loop through all images as image:
  npArray.append(sift.detectAndCompute(image, None))
npArray = np.array(npArray)

Tags: py图像importnoneasnpparamscv2
3条回答

以下是我的几点建议:

  1. 您应该使用适当的技术来减少点数据的数量。
  2. 反复计算参考图像是一种浪费。您应该持久化所有计算的引用。
  3. 不要将计算结果放在移动设备上。你最好把计算出来的一张抓拍图像的参考上传到一个功能强大的服务器上进行搜索。

这是一个非常有趣的话题。我的耳朵也开了。

随着@stanleysu2005的回复,我想补充一些技巧,如何做整个匹配本身,因为我目前正在工作这样的事情。

  1. 我强烈建议创建一些自定义类,该类包装在cv::Mat上,但也存储各种其他重要的数据片段。在我的例子中,我有一个ImageContainer来存储原始图像(我将用于最后的缝合)、处理过的图像(灰度、未失真等)、其关键点和这些图像的描述符。通过这样做,您可以访问所有匹配的相关信息在一个相当好的组织。您可以在其中实现关键点提取和描述符生成,也可以在类外部实现,只需将结果存储在该容器中。
  2. 将所有图像容器存储在某种结构中(矢量通常是一个不错的选择),以便于访问。
  3. 我还创建了一个名为ImageMultiMatchContainer的类,它存储一个指向给定查询图像(所有图像都是查询图像)的指针、一个指向所有匹配的训练图像(对于图像集的单个查询图像,所有其他图像都是训练图像)的指针的向量,以及这些匹配的每个匹配向量的向量。在这里,我无意中发现了一个存储问题,即:首先,您必须跳过图像本身的匹配,因为这是毫无意义的;其次,您有两次比较两个图像的问题,因此,如果您有很多图像,会产生相当大的开销。第二个问题是,我们遍历所有图像(查询图像)并将它们与集合中的其他图像(火车图像)进行比较。在某一点上,我们有图像X(query)与图像Y(train)匹配,但后来我们也有图像Y(now query)与图像X(now train)匹配。正如你所见,这也是毫无意义的,因为它基本上是匹配同一对图像两次。这可以通过创建一个类(MatchContainer)来解决(目前正在处理这个问题),该类将指向两个图像中的每一个的指针存储在匹配对中,同时也存储匹配向量。您将其存储在一个中心位置(在我的例子中,这是我的matcher类),对于每个图像作为查询图像,您将检查火车图像的匹配图像列表。如果为空,则创建一个新的MatchContainer并将其添加到其余MatchContainer中。如果不存在,那么您可以查看其中是否不存在当前查询图像(比较指针是一个快速操作)。如果是,则只需将指针传递给MatchContainer的向量项,该向量项存储这两个图像的匹配项。如果不是这样的话,你就好像它是空的,然后创建一个新的matchinterance等等。MatchingContainers应该存储在一个访问时间很短的数据结构中,因为你会经常查看它们,并且从头到尾的迭代花费了太多的时间。我正在考虑使用地图,但也许某种树也能提供一些好处。
  4. 单应估计是一个非常棘手的部分。在这里,我建议您查看束块调整。我看到OpenCV中的缝合器类有一个BundleBase类,但是还没有测试它来查看其中的内容。

一般的建议是查看OpenCV中的缝合过程并阅读源代码。缝合管道是一个直截了当的流程集,您只需看看如何准确地实现单个步骤。

< P>我从未在Python中解决过这个问题,但是我把环境转换成C++,在那里你得到更多的OpenCV例子,不必使用一个文档更少的包装器。

关于我在多个文件中进行匹配的问题,可以在这里找到一个示例:https://github.com/Itseez/opencv/blob/2.4/samples/cpp/matching_to_many_images.cpp

相关问题 更多 >