opencv / opencv

Open Source Computer Vision Library
https://opencv.org
Apache License 2.0
78.77k stars 55.8k forks source link

BFMatcher does not do what it claims to do with crossCheck = True #12484

Closed headdab closed 6 years ago

headdab commented 6 years ago

opencv-4.0pre Ubuntu 17.10, x86_64 gcc 7.2.0

BFMatcher describes its behavior with crossCheck = True as:

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

python example *(run interactively):

>>> import cv2
>>> import numpy as np

>>> a = np.array([[0,0],[0,1]]).astype(np.uint8)
>>> b = np.array([[0,0],[1,3],[1,2]]).astype(np.uint8) 

>>> bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
>>> matches = bf.match(a, b)
>>> len(matches)
2
>>> m=matches[0]; m.distance, m.queryIdx, m.trainIdx
(1.0, 0, 0)
>>> m=matches[1]; m.distance, m.queryIdx, m.trainIdx 
(2.0, 1, 2)

Graphically, this dataset looks like

      b1

a1        b2
a0   b0  

with distances:

     b0   b1    b2
a0  1.00  3.16  2.23
a1  1.41  2.23  2.00

As such the nearest neighbors in both directions are:

a0 -> b0 a1 -> b0

b0 -> a0 b1 -> a1 b2 -> a1

so the only consistent match is a0 <-> b0, but the matcher returns also a1 <-> b2, even though the closest point to a1 is b0.

Maybe its working as desired but, if it is, it is described incorrectly.

LaurentBerger commented 6 years ago

same as #11855 ?

headdab commented 6 years ago

Yes, I just found that one too.