OpenCV-Python ORB特征匹配(实践篇)
- 特征提取和匹配
- OpenCV的ORB特征
- 第一步:导入库,图片,创建ORB对象
- 第二步:寻找关键点和描述子
- 第三步:进行匹配
- 第四步:对匹配点进行筛选
- 第五步:绘制结果图
- 完整代码
特征提取和匹配
SIFT已经获取专利,所以OpenCV不用调用,我们用ORB来代替SIFT特征,在这篇文章里我们直接谈如何用代码实现。
OpenCV的ORB特征
第一步:导入库,图片,创建ORB对象
导入OpenCV库。
1 | import cv2 as cv |
在进行特征的提取之前,我们要读入两张图片(图片我就不提供了)。
1 2 | image1 = cv.imread('1.png') image2 = cv.imread('2.png') |
这里我们使用的是ORB特征,所以要创建一个ORB对象:
1 2 | # 初始化ORB orb = cv.ORB_create() |
第二步:寻找关键点和描述子
创建之后,就是主要的寻找关键点和计算描述子:
1 2 3 4 5 6 7 | # 寻找关键点 kp1 = orb.detect(img1) kp2 = orb.detect(img2) # 计算描述符 kp1, des1 = orb.compute(img1, kp1) # 计算哪张图片的用哪张图片的关键点。 kp2, des2 = orb.compute(img2, kp2) |
找到了关键点可以画出关键点看一看:
1 2 3 4 5 6 7 8 9 | # 画出关键点 outimg1 = cv.drawKeypoints(img1, keypoints=kp1, outImage=None) outimg2 = cv.drawKeypoints(img2, keypoints=kp2, outImage=None) # 这里是把两张图片在同一个窗口中显示。 import numpy as np outimg3 = np.hstack([outimg1, outimg2]) cv.imshow("Key Points", outimg3) cv.waitKey(0) |
显示出来的关键点结果:
有了关键点和描述子,我们就要对这些点进行匹配。这里我们用的是Brute-Force匹配器,它获取第一组中一个特征的描述符,并通过一些距离计算与第二组中的所有其他特征匹配,最接近的一个被返回。
我们用Hamming距离对描述子进行匹配。
第三步:进行匹配
1 2 3 4 5 | # 初始化 BFMatcher bf = cv.BFMatcher(cv.NORM_HAMMING) # 对描述子进行匹配 matches = bf.match(des1, des2) |
第四步:对匹配点进行筛选
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 计算最大距离和最小距离 min_distance = matches[0].distance max_distance = matches[0].distance for x in matches: if x.distance < min_distance: min_distance = x.distance if x.distance > max_distance: max_distance = x.distance ''' 当描述子之间的距离大于两倍的最小距离时,认为匹配有误。 但有时候最小距离会非常小,所以设置一个经验值30作为下限。 ''' good_match = [] for x in matches: if x.distance <= max(2 * min_distance, 30): good_match.append(x) |
第五步:绘制结果图
这里我们将绘制结果单独拿出来:
1 2 3 4 5 6 7 | draw_match(img1, img2, kp1, kp2, good_match) def draw_match(img1, img2, kp1, kp2, match): outimage = cv.drawMatches(img1, kp1, img2, kp2, match, outImg=None) cv.imshow("Match Result", outimage) cv.waitKey(0) |
显示出来的结果:
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import cv2 as cv def ORB_Feature(img1, img2): # 初始化ORB orb = cv.ORB_create() # 寻找关键点 kp1 = orb.detect(img1) kp2 = orb.detect(img2) # 计算描述符 kp1, des1 = orb.compute(img1, kp1) kp2, des2 = orb.compute(img2, kp2) # 画出关键点 outimg1 = cv.drawKeypoints(img1, keypoints=kp1, outImage=None) outimg2 = cv.drawKeypoints(img2, keypoints=kp2, outImage=None) # 显示关键点 # import numpy as np # outimg3 = np.hstack([outimg1, outimg2]) # cv.imshow("Key Points", outimg3) # cv.waitKey(0) # 初始化 BFMatcher bf = cv.BFMatcher(cv.NORM_HAMMING) # 对描述子进行匹配 matches = bf.match(des1, des2) # 计算最大距离和最小距离 min_distance = matches[0].distance max_distance = matches[0].distance for x in matches: if x.distance < min_distance: min_distance = x.distance if x.distance > max_distance: max_distance = x.distance # 筛选匹配点 ''' 当描述子之间的距离大于两倍的最小距离时,认为匹配有误。 但有时候最小距离会非常小,所以设置一个经验值30作为下限。 ''' good_match = [] for x in matches: if x.distance <= max(2 * min_distance, 30): good_match.append(x) # 绘制匹配结果 draw_match(img1, img2, kp1, kp2, good_match) def draw_match(img1, img2, kp1, kp2, match): outimage = cv.drawMatches(img1, kp1, img2, kp2, match, outImg=None) cv.imshow("Match Result", outimage) cv.waitKey(0) if __name__ == '__main__': # 读取图片 image1 = cv.imread('1.png') image2 = cv.imread('2.png') ORB_Feature(image1, image2) |
参考文献:
OpenCV-Python官方文档.