OpenCV Python 特征匹配

【目标】

  • 特征匹配
  • Brute-Force Matcher 和 FLANN Matcher

【理论】

Brute-Force Matcher字面意思是蛮力匹配器,所以它的过程也很简单,从一个集合里取出一个特征描述子,然后与第二个集合里的特征逐个的进行匹配比较。返回最近的一个。

对于BF matcher,首先我们必须使用cv.BFMatcher()创建BFMatcher对象。它接受两个可选参数。第一个是normType。它指定了要使用的距离测量。默认为cv.NORM_L2。对于 SIFT 和 SURF 来说很好。对于基于二进制字符串的描述符,如ORB, BRIEF, BRISK等等,应该使用NORM_HAMMING,它使用汉明距离作为度量。如果ORB使用WTA_K == 3或4,

第二个参数是布尔变量,crossCheck默认为false。如果为真,Matcher只返回值为(i,j)的匹配,这样集合A中的第i个描述符与集合B中的第j个描述符是最佳匹配,反之亦然。也就是说,两个集合中的两个特征应该相互匹配。该方法可较好地替代D.Lowe在SIFT论文中提出的比值检验方法。

创建后,有两个重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。第一个返回最佳匹配。第二个方法返回k个用户指定的最佳匹配项。当我们需要做额外的工作时,它可能会有用。

就像我们使用 cv2.drawKeypoints 绘制关键点一样,cv2.drawMatches 绘制匹配点。它将两张图像水平堆叠,并从第一张图像连接到第二张图像,以显示最佳匹配。

【代码】

  • ORB 特征及 bf matcher

特征点检测 python python特征点匹配_特征点检测 python

# ORB 特征及 bf matcher
import numpy as np 
import cv2 
import matplotlib.pyplot as plt

img1 = cv2.imread("assets/box.png", 0)
img2 = cv2.imread("assets/box_in_scene.png", 0)

# 创建 ORB 对象
orb = cv2.ORB_create()

# 检测关键点并计算特征
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# 匹配
matchs = bf.match(des1, des2)

# 排序
matchs = sorted(matchs, key=lambda x: x.distance)

# 绘制匹配结果
img_res = cv2.drawMatches(img1, kp1, img2, kp2, matchs[:15], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

cv2.imshow("orb-bfmatches", img_res)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • SIFT 和 bf knn matcher

特征点检测 python python特征点匹配_特征点检测 python_02

# SIFT 和 bf knn matcher
import numpy as np 
import cv2

img1 = cv2.imread("assets/box.png", 0)
img2 = cv2.imread("assets/box_in_scene.png", 0)

sift = cv2.SIFT_create()

kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)

good = []
for m, n in matches:
    if m.distance < 0.5*n.distance:
        good.append([m])

img_res = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good,
                            None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

cv2.imshow("sift-bfknnmatches", img_res)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • sift FLANN matcher

特征点检测 python python特征点匹配_opencv_03

# sift FLANN matcher
import numpy as np 
import cv2 

img1 = cv2.imread("assets/box.png", 0)
img2 = cv2.imread("assets/box_in_scene.png", 0)

# 初始化创建
sift = cv2.SIFT_create()

# 关键点检测和特征计算
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.5*n.distance:
        matchesMask[i] = [1, 0]
draw_params = dict(matchColor=(0, 255, 0),
                    singlePointColor=(255, 0, 0),
                    matchesMask=matchesMask,
                    flags=cv2.DrawMatchesFlags_DEFAULT)
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)

cv2.imshow("sift-flannmatches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

【接口】

  • BFMatcher
cv2.BFMatcher(	[, normType[, crossCheck]]	) ->	<BFMatcher object>
  • normType: NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2; L1和L2是SIFT和SURF描述符使用,ORB,BRISK和BRIEF使用,NORM_HAMMING2 是 ORB 中 WTA_K==3或4时使用。
  • crossCheck: 如果为 false, 默认的 BFMatcher 返回 k 最近邻的匹配描述符,如果为真,并且 k=1时,返回的匹配对
cv2.drawMatches(	img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]	) ->	outImg
cv2.drawMatches(	img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchesThickness[, matchColor[, singlePointColor[, matchesMask[, flags]]]]	) ->	outImg
cv2.drawMatchesKnn(	img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]	) ->	outImg

绘制两幅图像中的匹配的点。

  • img1: 第一幅图像
  • keypoints1: 第一幅图像中的关键点
  • img2: 第二幅图像
  • keypoints2: 第二幅图像中的关键点
  • matches1to2: 第一幅图像和第二幅图像中匹配的描述符
  • outImg: 绘制结果的图像
  • matchColor: 绘制匹配点的颜色,如果 matchColor==Scalar::all(-1) 则颜色随机生成
  • singlePointColor: 绘制单个匹配点的颜色,如果 singlePointColor==Scalar::all(-1) 则颜色随机生成
  • matchesMask: 如果为空,绘制所有;
  • flags: 绘制特征的标识符 DrawMatchesFlags.
  • DrawMatchesFlags

特征点检测 python python特征点匹配_计算机视觉_04

【参考】

  1. OpenCV: Feature Matching