OpenCV SIFT+FLANN 单个关键点的多重匹配
OpenCV SIFT+FLANN multiple matches for single keypoint
我正在尝试使用 open cv 匹配关键点。
具体来说,我正在使用“筛选”检测器和“flann”匹配器。我的代码基于 cv2's documentation:
detector = cv2.SIFT_create()
matcher = cv2.FlannBasedMatcher(indexParams=dict(algorithm=0, trees=5), searchParams=dict(checks=50))
kps1, desc1 = detector.detectAndCompute(img1, None)
kps2, desc2 = detector.detectAndCompute(img2, None)
all_matches = matcher.knnMatch(desc1, desc2, 2)
ratio = 0.7
good_matches = []
for m, n in all_matches:
if m.distance <= ratio * n.distance:
good_matches.append(m)
我注意到甚至在 good_matches
列表中,我有一些关键点不止一个匹配项:
extra_matches = dict()
for match in good_matches:
t_idx = match.trainIdx
reps = [mch for mch in good_matches if mch.trainIdx == t_idx]
if len(reps) > 1 and t_idx not in extra_matches.dict():
extra_matches[t_idx] = reps
print(len(extra_matches)) # not 0
我觉得这很奇怪,因为我认为 knnMatch
已经产生了 2 个最佳匹配。为什么在对匹配进行比率修剪后每个关键点会有多个匹配?
果然,发帖五分钟后我找到了答案:
FLANN
不执行 cross-checks,这意味着我将重复第二个关键点,但不会重复第一个关键点(也在我的代码中验证)。
如果您需要 cross-check 和 FLANN
,最佳做法是实现您自己的 cross-check 或使用 FLANN
获取描述符的子集,然后使用 BFMatcher
的cross-check 选项。
以下是一些其他信息来源:[1],
我正在尝试使用 open cv 匹配关键点。 具体来说,我正在使用“筛选”检测器和“flann”匹配器。我的代码基于 cv2's documentation:
detector = cv2.SIFT_create()
matcher = cv2.FlannBasedMatcher(indexParams=dict(algorithm=0, trees=5), searchParams=dict(checks=50))
kps1, desc1 = detector.detectAndCompute(img1, None)
kps2, desc2 = detector.detectAndCompute(img2, None)
all_matches = matcher.knnMatch(desc1, desc2, 2)
ratio = 0.7
good_matches = []
for m, n in all_matches:
if m.distance <= ratio * n.distance:
good_matches.append(m)
我注意到甚至在 good_matches
列表中,我有一些关键点不止一个匹配项:
extra_matches = dict()
for match in good_matches:
t_idx = match.trainIdx
reps = [mch for mch in good_matches if mch.trainIdx == t_idx]
if len(reps) > 1 and t_idx not in extra_matches.dict():
extra_matches[t_idx] = reps
print(len(extra_matches)) # not 0
我觉得这很奇怪,因为我认为 knnMatch
已经产生了 2 个最佳匹配。为什么在对匹配进行比率修剪后每个关键点会有多个匹配?
果然,发帖五分钟后我找到了答案:
FLANN
不执行 cross-checks,这意味着我将重复第二个关键点,但不会重复第一个关键点(也在我的代码中验证)。
如果您需要 cross-check 和 FLANN
,最佳做法是实现您自己的 cross-check 或使用 FLANN
获取描述符的子集,然后使用 BFMatcher
的cross-check 选项。
以下是一些其他信息来源:[1],