Search code examples
pythonopencvpattern-matchingstereo-3d

Python - Distance between Feature Matching Keypoints with OpenCV


I am trying to implement a program which will input two stereo images and find the distance between the keypoints that have a feature match. Is there any way to do it? I am working with SIFT/BFMatcher and my code is as follows:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = dst1
img2 = dst2

# 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)

# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)

# Apply ratio test
good = []
for m, n in matches:
    if m.distance < 0.3 * n.distance:
        good.append([m])

# cv2.drawMatchesKnn expects list of lists as matches.
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, flags=2, outImg=img2)

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

Solution

  • The following algorithm finds the distance between the keypoints of img1 with its featured matched keypoints in img2 (ommiting the first lines):

    # Apply ratio test
    good = []
    for m,n in matches:
        if m.distance < 0.3 * n.distance:
            good.append(m)
    
    # Featured matched keypoints from images 1 and 2
    pts1 = np.float32([kp1[m.queryIdx].pt for m in good])
    pts2 = np.float32([kp2[m.trainIdx].pt for m in good])
    
    # Convert x, y coordinates into complex numbers
    # so that the distances are much easier to compute
    z1 = np.array([[complex(c[0],c[1]) for c in pts1]])
    z2 = np.array([[complex(c[0],c[1]) for c in pts2]])
    
    # Computes the intradistances between keypoints for each image
    KP_dist1 = abs(z1.T - z1)
    KP_dist2 = abs(z2.T - z2)
    
    # Distance between featured matched keypoints
    FM_dist = abs(z2 - z1)
    

    Thus, KP_dist1 is a symmetrical matrix with the distances between img1 keypoints, KP_dist2 is the same for img2 and FM_dist is a list with the distances between the featured matched keypoints from both images with len(FM_dist) == len(good).

    Hope this helped!