【转载】OpenCV-Python系列之特征匹配(五十三)

之前我们讨论过了诸多的特征检测算法,这次我们来讨论如何运用相关的方法进行特征匹配。本次教程完全为实战教程,没有相关的算法原理介绍,大家可以轻松一下了。

蛮力匹配(ORB匹配)

Brute-Force匹配非常简单,首先在第一幅图像中选择一个关键点然后依次与第二幅图像的每个关键点进行(改变)距离测试,最后返回距离最近的关键点。

对于BF匹配器,首先我们必须使用cv2.BFMatcher()创建BFMatcher对象。它需要两个可选的参数。

1.第一个是normType,它指定要使用的距离测量,或在其他情况下,它是cv2.NORM_L2。它适用于SIFT,SURF等(cv2.NORM_L1也在那里)。对于基于二进制串行的替代,如ORB,BRIEF,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(),第一个返回最佳匹配,第二种方法返回k个最佳匹配,其中k由用户指定。

使用cv2.drawMatches()来对齐匹配的点,它可以将两幅图像先行水平划分,然后在最佳匹配的点之间对齐直线。如果前面使用的BFMatcher.knnMatch(),现在可以使用函数cv2.drawMatchsKnn为每个关键点和它的一个最佳匹配如果要选择性替换就要给函数重新定义一个指针。

我们来看代码:

view plaincopy to clipboardprint?
def BruteForce(img1,img2):  
     # Initiate ORB detector  
     orb = cv2.ORB_create()  
   
     # find the keypoints and descriptors with ORB  
     kp1, des1 = orb.detectAndCompute(img1, None)  
     kp2, des2 = orb.detectAndCompute(img2, None)  
   
     # create BFMatcher object  
     bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)  
   
     # Match descriptors.  
     matches = bf.match(des1, des2)  
   
     # Sort them in the order of their distance.  
     matches = sorted(matches, key=lambda x: x.distance)  
   
     # Draw first 10 matches.  
     img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)  
   
     plt.imshow(img3), plt.show()  

输出:
【转载】OpenCV-Python系列之特征匹配(五十三)_第1张图片

SIFT的特征匹配

关于SIFT的概念我们之前已经讨论过,现在来看相关的实战代码:

view plaincopy to clipboardprint?
def SIFT(img1, img2):  
     # Initiate SIFT detector  
     sift = cv2.xfeatures2d.SIFT_create()  
   
     # find the keypoints and descriptors with SIFT  
     kp1, des1 = sift.detectAndCompute(img1, None)  
     kp2, des2 = sift.detectAndCompute(img2, None)  
   
     # BFMatcher with default params  
     bf = cv2.BFMatcher()  
     matches = bf.knnMatch(des1, des2, k=2)  
   
     # Apply ratio test  
     good = []  
     for m, n in matches:  
         if m.distance < 0.6 * n.distance:  
             good.append([m])  
   
     # cv.drawMatchesKnn expects list of lists as matches.  
     img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)  
   
     plt.imshow(img3), plt.show()  

结果:
【转载】OpenCV-Python系列之特征匹配(五十三)_第2张图片

事实上我们可以看到,与蛮力匹配相比,SIFT算法的特征匹配是十分强大的,效果显而易见。

SURF的特征匹配

view plaincopy to clipboardprint?
def SURF(img1, img2):  
     # Initiate SIFT detector  
     surf = cv2.xfeatures2d.SURF_create()  
   
     # find the keypoints and descriptors with SIFT  
     kp1, des1 = surf.detectAndCompute(img1, None)  
     kp2, des2 = surf.detectAndCompute(img2, None)  
   
     # BFMatcher with default params  
     bf = cv2.BFMatcher()  
     matches = bf.knnMatch(des1, des2, k=2)  
   
     # Apply ratio test  
     good = []  
     for m, n in matches:  
         if m.distance < 0.6 * n.distance:  
             good.append([m])  
   
     # cv.drawMatchesKnn expects list of lists as matches.  
     img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)  
   
     plt.imshow(img3), plt.show()  

【转载】OpenCV-Python系列之特征匹配(五十三)_第3张图片

SIFT算法的特征匹配相比较SURF来说,基本上效果差不多,但是速度不同。

基于FLANN的匹配器

FLANN代表近似最近邻居的快速库。它包含一组算法,这些算法针对大型数据集中的快速最近邻搜索和高维特征进行了优化。对于大型数据集,它比BFMatcher工作得更快。

代码:

view plaincopy to clipboardprint?
def FLANN(img1, img2):  
     # Initiate SIFT detector  
     sift = cv2.xfeatures2d.SIFT_create()  
   
     # find the keypoints and descriptors with SIFT  
     kp1, des1 = sift.detectAndCompute(img1, None)  
     kp2, des2 = sift.detectAndCompute(img2, None)  
   
     # FLANN parameters  
     FLANN_INDEX_KDTREE = 1  
     index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)  
     search_params = dict(checks=50)  # or pass empty dictionary  
   
     flann = cv2.FlannBasedMatcher(index_params, search_params)  
   
     matches = flann.knnMatch(des1, des2, k=2)  
   
     # Need to draw only good matches, so create a mask  
     matchesMask = [[0, 0] for i in range(len(matches))]  
   
     # ratio test as per Lowe's paper  
     for i, (m, n) in enumerate(matches):  
         if m.distance < 0.6 * n.distance:  
             matchesMask[i] = [1, 0]  
   
     draw_params = dict(matchColor=(0, 255, 0),  
                        singlePointColor=(255, 0, 0),  
                        matchesMask=matchesMask,  
                        flags=0)  
   
     img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)  
   
     plt.imshow(img3, ), plt.show()  

输出结果:
【转载】OpenCV-Python系列之特征匹配(五十三)_第4张图片

FLANN属于单应性匹配,单应性指的是图像在投影发生了畸变后仍然能够有较高的检测和匹配准确率,它可以大概率上避免旋转和放缩带来的影响。

查看文章汇总页https://blog.csdn.net/weixin_44237705/article/details/107864965
更多openvino技术信息可以入群交流~
申请备注:CSDN
【转载】OpenCV-Python系列之特征匹配(五十三)_第5张图片

你可能感兴趣的:(python,opencv,机器学习,人工智能)