0
votes

I'm trying to do bag of words on a set of images, extracting SURF descriptors. However, I obtain the following error on the very last line of the code pasted below:

type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)

If I use "SIFT" instead, then everything works. But when I use "SURF", BoW cannot compute the SURF descriptors.

Is this the correct way to instantiate SURF? Am I allowed to use the cv2.NORM_L2 distance function?

imgs2Keypoints = {}
kmeansTrainer = cv2.BOWKMeansTrainer(10);  
for pathToImage in images:
    sift = cv2.SURF(400)
    img = cv2.imread(pathToImage)
    kp, des = sift.detectAndCompute(img, None)
    des = np.float32(des)
    kmeansTrainer.add(des)
    imgs2Keypoints[pathToImage] = kp 
vocabulary = kmeansTrainer.cluster()
bow_ext.setVocabulary(vocabulary)

surf2 = cv2.DescriptorExtractor_create("SURF")
bow_ext = cv2.BOWImgDescriptorExtractor(surf2, cv2.BFMatcher(cv2.NORM_L2))

for pathToImage in images:
    img = cv2.imread(pathToImage)
    histogram = bow_ext.compute(img, imgs2Keypoints[pathToImage])[0]
1

1 Answers

1
votes

Edit:

sift = cv2.SURF(400)

creates extended SURF descriptors (128 dimensional), whereas

surf2 = cv2.DescriptorExtractor_create("SURF")

creates standard SURF descriptors (64 dimensional).

A possible solution is to disable extended descriptors for the sift object

sift.extended = False

Edit 2:

For use with extended descriptors:

surf2.setBool("extended", True)

As for L2 norm: Yes, L2 distance is fine. As stated in OpenCV docs:

L1 and L2 norms are preferable choices for SIFT and SURF descriptors