我正在尝试在两个图像上使用 SIFT,并在 OpenCV 中使用 BFMatcher 匹配关键点。
但是,匹配的数量不等于查询描述符的数量。有人可以解释为什么它们不相等吗?
根据文档
match()
功能“从查询集中找到每个描述符的最佳匹配。”
import cv2
import numpy as np
im1 = cv2.imread("trex1.png", cv2.IMREAD_GRAYSCALE)
im2 = cv2.imread("trex2.png", cv2.IMREAD_GRAYSCALE)
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(im1, None)
kp2, des2 = sift.detectAndCompute(im2, None)
im_kp1 = np.zeros(im1.shape, dtype=np.uint8)
im_kp2 = np.zeros(im1.shape, dtype=np.uint8)
im_kp1 = cv2.drawKeypoints(im1,kp1,None)
im_kp2 = cv2.drawKeypoints(im2,kp2,None)
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
matches = bf.match(des1,des2)
print len(des1)
# Result : 78
print len(des2)
# Result : 71
print len(matches)
# Result : 55
Run Code Online (Sandbox Code Playgroud)
因为crossCheck=True
正在删除一些结果。
如果您检查构造函数的文档BFMatcher()
:
crossCheck如果它为 false,这将是 BFMatcher 为每个查询描述符找到 k 个最近邻居时的默认行为。如果 crossCheck==true,那么 k=1 的 knnMatch() 方法将只返回对 (i,j) 使得对于第 i 个查询描述符,匹配器集合中的第 j 个描述符是最近的,反之亦然,即BFMatcher 只会返回一致的对。当有足够的匹配时,这种技术通常会以最少的异常值产生最佳结果。这是 D. Lowe 在 SIFT 论文中使用的比率测试的替代方法。
这看起来只会影响knnMatch()
方法,但match()
方法实际上显式调用knnMatch()
:
Run Code Online (Sandbox Code Playgroud)void DescriptorMatcher::match( InputArray queryDescriptors, std::vector<DMatch>& matches, InputArrayOfArrays masks ) { CV_INSTRUMENT_REGION() std::vector<std::vector<DMatch> > knnMatches; knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ ); convertMatches( knnMatches, matches ); }
如果你设置crossCheck=False
(或者只是不指定,False
默认情况下),那么你会得到
len(query_descriptors) == len(matches)
Run Code Online (Sandbox Code Playgroud)