Reputation: 139
I am trying to use SIFT on two images and match the keypoints using BFMatcher in OpenCV.
However, the number of matches is not equal to the number of query descriptors. Can someone explain why they are not equal?
According to docs
match()
function "Finds the best match for each descriptor from a query set."
import cv2
import numpy as np
im1 = cv2.imread("trex1.png", cv2.IMREAD_GRAYSCALE)
im2 = cv2.imread("trex2.png", cv2.IMREAD_GRAYSCALE)
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(im1, None)
kp2, des2 = sift.detectAndCompute(im2, None)
im_kp1 = np.zeros(im1.shape, dtype=np.uint8)
im_kp2 = np.zeros(im1.shape, dtype=np.uint8)
im_kp1 = cv2.drawKeypoints(im1,kp1,None)
im_kp2 = cv2.drawKeypoints(im2,kp2,None)
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
matches = bf.match(des1,des2)
print len(des1)
# Result : 78
print len(des2)
# Result : 71
print len(matches)
# Result : 55
Upvotes: 4
Views: 4415
Reputation: 23052
Because crossCheck=True
is removing some of the results.
If you check the docs for the BFMatcher()
constructor:
crossCheck If it is false, this is will be default BFMatcher behaviour when it finds the k nearest neighbors for each query descriptor. If crossCheck==true, then the knnMatch() method with k=1 will only return pairs (i,j) such that for i-th query descriptor the j-th descriptor in the matcher's collection is the nearest and vice versa, i.e. the BFMatcher will only return consistent pairs. Such technique usually produces best results with minimal number of outliers when there are enough matches. This is alternative to the ratio test, used by D. Lowe in SIFT paper.
This reads like it will only affect the knnMatch()
method, but the match()
methods actually explicitly call knnMatch()
:
void DescriptorMatcher::match( InputArray queryDescriptors, std::vector<DMatch>& matches, InputArrayOfArrays masks ) { CV_INSTRUMENT_REGION() std::vector<std::vector<DMatch> > knnMatches; knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ ); convertMatches( knnMatches, matches ); }
If you set crossCheck=False
(or just don't specify, it's False
by default), then you'll get
len(query_descriptors) == len(matches)
Upvotes: 6