BFMatcher match in OpenCV throwing error BFMatcher match in OpenCV throwing error python python

BFMatcher match in OpenCV throwing error


To search between descriptors of two images use:

img1 = cv2.imread('box.png',0)img2 = cv2.imread('box_in_scene.png',0)kp1,des1 = surf.detectAndCompute(img1,None)kp2,des2 = surf.detectAndCompute(img2,None)bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False)matches = bf.match(des1,des2)

To search among multiple images

The add method is used to add descriptor of multiple test images. Once, all descriptors are indexed, you run train method to build an underlying Data Structure(example: KdTree which will be used for searching in case of FlannBasedMatcher). You can then run match to find if which test image is a closer match to which query image. You can check K-d_tree and see how it can be used to search for multidimensional vectors(Surf gives 64-dimensional vector).

Note:- BruteForceMatcher, as name implies, has no internal search optimizing data structure and thus has empty train method.

Code Sample for Multiple Image search

import cv2import numpy as npsurf = cv2.xfeatures2d.SURF_create(400)# Read Imagestrain = cv2.imread('box.png',0)test = cv2.imread('box_in_scene.png',0)# Find Descriptors    kp1,trainDes1 = surf.detectAndCompute(train, None)kp2,testDes2  = surf.detectAndCompute(test, None)# Create BFMatcher and add cluster of training images. One for now.bf = cv2.BFMatcher(cv2.NORM_L1,crossCheck=False) # crossCheck not supported by BFMatcherclusters = np.array([trainDes1])bf.add(clusters)# Train: Does nothing for BruteForceMatcher though.bf.train()matches = bf.match(testDes2)matches = sorted(matches, key = lambda x:x.distance)# Since, we have index of only one training image, # all matches will have imgIdx set to 0.for i in range(len(matches)):    print matches[i].imgIdx

For DMatch output of bf.match, see docs.

See full example for this here: Opencv3.0 docs.

Other Info

OS: Mac.
Python: 2.7.10.
Opencv: 3.0.0-dev [If remember correctly, installed using brew].


I was getting the same error. But in my case it was because I was using SIFT with cv2.NORM_HAMMING metric in cv2.BFMatcher_create. Changing the metric to cv2.NORM_L1 solved the issue.

Citing docs for BFMatcher:

normType – One of NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 and L2 norms are preferable choices for SIFT and SURF descriptors, NORM_HAMMING should be used with ORB, BRISK and BRIEF, NORM_HAMMING2 should be used with ORB when WTA_K==3 or 4 (see ORB::ORB constructor description).


I found I was getting the same error. Took a while to figure out - some of my images were somewhat featureless, therefore no keypoints were found, and detectAndCompute returned None for the descriptors. Might be worth checking the list of descriptors for None elements prior to passing to BFMatcher.add().