BFmatcher with crossCheck doesn't crossCheck
If I understand the purpose and documentation of the brute force matcher with cross check enabled, I don't think it works as expected. See the example code below
import numpy
import cv2
sources = numpy.array([[1, 1, 0], [1, 1, 1]], dtype=numpy.uint8)
targets = numpy.array([[1, 1, 1], [0, 0, 0]], dtype=numpy.uint8)
for si, source in enumerate(sources):
for ti, target in enumerate(targets):
print('%d -> %d: %d' % (si, ti, cv2.norm(source, target, cv2.NORM_HAMMING)))
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.knnMatch(sources, targets, k=1)
print('-- crosscheck=True')
for match in matches:
if match:
print('%d -> %d: %f' % (match[0].queryIdx, match[0].trainIdx, match[0].distance))
bf_nocc = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
matches_nocc = bf.knnMatch(sources, targets, k=1)
print('-- crosscheck=False')
for match in matches_nocc:
if match:
print('%d -> %d: %f' % (match[0].queryIdx, match[0].trainIdx, match[0].distance))
With output
0 -> 0: 1
0 -> 1: 2
1 -> 0: 0
1 -> 1: 3
-- crossCheck=True
0 -> 1: 2.000000
1 -> 0: 0.000000
-- crossCheck=False
0 -> 0: 1.000000
1 -> 0: 0.000000
I would expect the crossCheck to remove the 0 -> 1 match since source 0 is closest to target 0. Have I misunderstood how the cross check is supposed to work or is this an issue with the matcher?
Yesit's weird. I can reproduce your issue in C++ :
//
results :
Data order changes results : I don't understand.
Good catch! Indeed, if I switch sources and targets at the top, I get only 0 -> 1 with crossCheck=True (the correct one in this example).
Source code is here and doc
IMHO something is wrong Post an issue
crossmacth doesnot mean best match? If it is not an optional parameter is necessary cross best match !
Thanks! I have submitted issue #11855.