Home OpenCV length of matches in BFMatcher
Reply: 1

OpenCV length of matches in BFMatcher

Raghuram Krishnaswami
1#
Raghuram Krishnaswami Published in 2017-12-07 12:07:09Z

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
Alexander Reynolds
2#
Alexander Reynolds Reply to 2017-12-07 12:47:28Z

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)
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.322792 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO