如何从OpenCV Python中的特征匹配中获取像素坐标

时间:2015-06-08 18:36:49

标签: python opencv image-processing matching feature-detection

我需要获取功能匹配器在提供的代码中选择的像素的xy坐标列表。我使用的是Python和OpenCV。任何人都可以帮助我吗?

img1=cv2.imread('DSC_0216.jpg',0)
img2=cv2.imread('DSC_0217.jpg',0)

orb=cv2.ORB(nfeatures=100000)
kp1,des1=orb.detectAndCompute(img1,None)
kp2,des2=orb.detectAndCompute(img2,None)

img1kp=cv2.drawKeypoints(img1,kp1,color=(0,255,0),flags=0)
img2kp=cv2.drawKeypoints(img2,kp2,color=(0,255,0),flags=0)
cv2.imwrite('m_img1.jpg',img1kp)
cv2.imwrite('m_img2.jpg',img2kp)

bf=cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches=bf.match(des1,des2)
matches=sorted(matches, key= lambda x:x.distance)

1 个答案:

答案 0 :(得分:21)

我们知道您的关键点存储在kp1kp2中,它们分别与第一个和第二个图像匹配。在cv2.ORB透视图中,这些是2D矩阵,其中每一行是在第一张图像kp1和第二张图像kp2中检测到的关键点。

在您的情况下因为您使用cv2.BFMatchmatches会返回cv2.DMatch个对象的列表,其中每个对象包含多个成员....其中有两个重要成员:

  • queryIdx - 匹配的kp1兴趣点矩阵的索引或
  • trainIdx - 匹配的kp2兴趣点矩阵的索引或

因此,queryIdxtrainIdx会告诉您kp1kp2之间哪些ORB功能匹配。因此,您可以使用这些索引编入kp1kp2并获取pt成员,这是(x,y)坐标的元组,用于确定实际的空间坐标。匹配。

您要做的就是遍历cv2.DMatch中的每个matches对象,附加到kp1kp2的坐标列表,您就完成了。

这样的事情:

# Initialize lists
list_kp1 = []
list_kp2 = []

# For each match...
for mat in matches:

    # Get the matching keypoints for each of the images
    img1_idx = mat.queryIdx
    img2_idx = mat.trainIdx

    # x - columns
    # y - rows
    # Get the coordinates
    (x1,y1) = kp1[img1_idx].pt
    (x2,y2) = kp2[img2_idx].pt

    # Append to each list
    list_kp1.append((x1, y1))
    list_kp2.append((x2, y2))

请注意,我可能刚刚完成了list_kp1.append(kp1[img1_idx].pt)list_kp2的相同操作,但我想清楚地说明如何解释空间坐标。你也可以更进一步,做一个列表理解:

list_kp1 = [kp1[mat.queryIdx].pt for mat in matches] 
list_kp2 = [kp2[mat.trainIdx].pt for mat in matches]

list_kp1将包含与list_kp2中相应位置匹配的要素点的空间坐标。换句话说,i的元素list_kp1包含img1中与img2list_kp2的相应要素点匹配的要素点的空间坐标。空间坐标位于元素i中。

作为次要的旁注,当我为drawMatches编写解决方法时,我使用了这个概念,因为对于OpenCV 2.4.x,C ++函数的Python包装器不存在,所以我在上面使用了上面的概念找到两个图像之间匹配特征的空间坐标,以编写我自己的实现。

如果你愿意,请查看它!

module' object has no attribute 'drawMatches' opencv python