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

22

我需要获得在提供的代码中特征匹配器选择的像素的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个回答

44
我们知道你的关键点存储在kp1kp2中,它们分别是第一张图片和第二张图片的特征匹配列表。在cv2.ORB模式下,特征描述符是二维矩阵,其中每行是在第一张和第二张图片中检测到的一个关键点。
在你的情况下,因为你使用了cv2.BFMatch,所以matches返回一个cv2.DMatch对象列表,其中每个对象包含多个成员,其中两个重要的成员是:
- queryIdx - 匹配kp1兴趣点矩阵的索引或 - trainIdx - 匹配kp2兴趣点矩阵的索引或 因此,queryIdxtrainIdx告诉您第一张和第二张图像之间的ORB特征匹配情况。您可以使用它们来索引kp1kp2并获取pt成员,pt是一个包含实际空间匹配坐标的元组(x,y)
您只需遍历matches中的每个cv2.DMatch对象,将其添加到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中对应位置匹配的特征点的空间坐标。换句话说,list_kp1的第i个元素包含了来自img1的特征点的空间坐标,该特征点与list_kp2中其空间坐标在第i个元素的相应特征点匹配。


作为一个小的旁注,我在为drawMatches编写解决方法时使用了这个概念。因为OpenCV 2.4.x缺少Python封装到C++函数的包装器,所以我利用了上述概念来定位两幅图像之间匹配特征的空间坐标,从而编写了自己的实现。

如果您感兴趣,请查看!

module' object has no attribute 'drawMatches' opencv python


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