通过降维加速opencv中的knnMatch图像匹配_波波杨Luke的博客-CSDN博客
ORB_SLAM2特征点提取策略及描述子的计算_嚣张的叉烧包的博客-CSDN博客
从OpenCV源码学习match()和knnMatch()进行双目匹配 - JavaShuo
一、Brute-Force蛮力匹配(ORB 匹配)
Brute-Force 匹配非常简单,首先在第一幅图像中选择一个关键点然后依次与第二幅图像的每个关键点进行(改变)距离测试,最后返回距离最近的关键点。
对于 BF 匹配器,首先我们必须使用 CV2.BFMatcher() 创建 BFMatcher 对象。它需要两个可选的参数。
bf = cv2.BFMatcher(cv2.NORM_HAMMING) #加载类rBrief(BFMatcher)用于特征匹配 :因为是二进制串,所以计算的是汉明距离。
matches = bf.knnMatch(des1.astype(np.uint8), des2.astype(np.uint8), 2) #调用了knnMatch函数,距离最近的top k个点。
1. 第一个是 normType ,它指定要使用的距离测量,或在其他情况下,它是 CV2.NORM_L2 。它适用于 SIFT , SURF 等( CV2.NORM_L1 也在那里)。替代,如 ORB ,附图, BRISK 等,应使用 CV2.NORM_HAMMING ,使用汉明距离作为度量,如果 ORB 使用 WTA_K == 3or4 ,则应使用 CV2.NORM_HAMMING2 。
2. crossCheck :最小数值为假。如果设置为 True ,则匹配条件就会更加严格,只有到 A 中的第 i 个特征点与 B 中的第 j 个特征点距离最近,并且 B 中的第 j 个特征点到 A 中的第 i 个特征点也是最近时才会返回最佳匹配,即这两个特征点要互相匹配才行。
两个重要的方法是 BFMatcher.match() 和 BFMatcher.knnMatch(),第一个返回最佳匹配,第二种方法返回 top k 个最佳匹配,其中 k 由用户指定。
使用 CV2.drawMatches() 来拆分匹配的点,它可以将两幅图像先行水平划分,然后在最佳匹配的点之间对齐直线。如果前面使用的 BFMatcher.knnMatch(),现在可以使用函数 CV2。 drawMatchsKnn 为每个关键点和它的一个最佳匹配, 如果要选择替换就要给函数重新定义一个指针。
def get_count(des1,des2):
if des1 is None or des2 is None:
return 0
if des1.shape[0]<2 or des2.shape[0]<2:
return 0
bf = cv2.BFMatcher(cv2.NORM_HAMMING) #加载类 BFMatcher 用于特征匹配 :因为是二进制串,所以计算的是汉明距离。
matches = bf.knnMatch(des1.astype(np.uint8), des2.astype(np.uint8), 2) #调用了knnMatch函数,距离最近的top k个点。
count = 0
for match in matches:
d1 = match[0].distance
d2 = match[1].distance
if d1 < d2 * 0.75: #
count+=1 #匹配上
return count
源码解读
match() 实际上调用就是 knnMatch() 把返回k个的匹配包了一层皮,设置返回一个最匹配的点。因此重点就一个knnMatch()就完了。
knnMatch() 如果是k=2个,则返回top k个最相似的特征点。
对于特征点,是否接受匹配,根据d1 / d2 < 0.75 (ratio)来判断,因为两个关键点中,如果最近的距离 / 次近的距离 < ratio,则接受。
个人理解:
近邻原则—匹配上的特征点,周围的特征点,应该也是与被匹配点相似的。
如果只有最近特征点满足,而次近特征点不满足,则不接受。