OpenCV-Python实践之Feature-Matching算法

特征匹配算法简介

OpenCV库函数里面集成了相关特征匹配算法,目前有:Brute-Force Matcher(BF)算法、FLANN算法使用频率较高。暴力匹配算法比较简单:就是通过描述子descriptors1中任意特征去匹配descriptors2中的所有特征,得到距离的结果值,然后通过Ratio-test抑制来降低错误匹配点。FLANN算法是最近邻算法的快速近似,以此来提升匹配的计算效率,下面我们来简单通过调用OpenCV自带的库函数进行运用。

1 ORB匹配算法(Python)

ORB算法是当前唯一能够满足实时性的应用场景匹配算法,当然其性能要比SIFT/SURF算法略差。但是,其能够在相对保持性能的同时,计算速度大幅提升。在室内定位、导航等应用广泛,例如较为经典算法:ORB-SLAM,具体ORB算法细节可以参考我另外一篇C++版本的ORB博文:OpenCV实践之ORB算法

from __future__ import print_function
import cv2 as cv
import numpy as np

img1 = cv.imread('./data/box.png', cv.IMREAD_GRAYSCALE)
img2 = cv.imread('./data/box_in_scene.png', cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
    print('Could not open or find the images!')
    exit(0)

#-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
detector = cv.ORB_create()

keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)

#-- Step 2: Matching descriptor vectors with a brute force matcher
matcher = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True)
matches = matcher.match(descriptors1, descriptors2)

# Sort matches in the order of their distances
matches = sorted(matches, key = lambda x : x.distance)
#-- Draw matches
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
cv.drawMatches(img1, keypoints1, img2, keypoints2, matches[:10], img_matches)

#-- Show detected matches
cv.imshow('Matches', img_matches)
cv.waitKey(0)
1.1 ORB算法实验结果
代码中cv.drawMatches()参数matches[:10]代表只画出前面10个排序鲁棒的特征点对。二值描述子经过一定的排序,matches=sorted()这个函数就是对匹配的描述子进行排序。
2 SIFT算法

谈到SIFT算法,不用再具体讨论其算法细节!网上资源解说很多,原因也是SIFT算法是最经典的特征匹配算法。当然,也可以参考一下我的博文:C++版本实现OpenCV实践之SIFT/SURF算法,SIFT算法解说:SIFT算法系列之尺度空间SIFT算法系列之特征点检测。OK, 下面上Python版本的代码:

2.1 SIFT+BF+Ratio-Test
from __future__ import print_function
import cv2 as cv
import numpy as np

img1 = cv.imread('./data/box.png', cv.IMREAD_GRAYSCALE)
img2 = cv.imread('./data/box_in_scene.png', cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
    print('Could not open or find the images!')
    exit(0)

#-- Step 1: Detect the keypoints using SIFT Detector, compute the descriptors
detector = cv.xfeatures2d_SIFT.create()

keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)

#-- Step 2: Matching descriptor vectors with a brute force matcher
matcher = cv.BFMatcher()
matches = matcher.knnMatch(descriptors1, descriptors2, k=2)

#--Step 3: Apply Ratio Test
good = []
for m,n in matches:
    if m.distance < 0.5*n.distance:
        good.append([m])

#-- Draw matches
img_matches = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
cv.drawMatchesKnn(img1, keypoints1, img2, keypoints2, good, img_matches)

#-- Show detected matches
cv.imshow('Matches', img_matches)
cv.waitKey(0)
2.1 SIFT使用BF算法+Ratio-Test来进行特征匹配
2.2 SIFT+FLANN算法代码
from __future__ import print_function
import cv2 as cv

from matplotlib import pyplot as plt

img1 = cv.imread('./data/box.png', cv.IMREAD_GRAYSCALE)
img2 = cv.imread('./data/box_in_scene.png', cv.IMREAD_GRAYSCALE)
if img1 is None or img2 is None:
    print('Could not open or find the images!')
    exit(0)

# Initiate SIFT detector
detector = cv.xfeatures2d_SIFT.create()

keypoints1, descriptors1 = detector.detectAndCompute(img1, None)
keypoints2, descriptors2 = detector.detectAndCompute(img2, None)

# FLANN paramters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(check=50) # or pass dictory

flann = cv.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(descriptors1, descriptors2, k=2)

# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))] # python2.x for xrange()

# 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, 0, 255), singlePointColor=(255, 0, 0),
                   matchesMask=matchesMask, flags=0)

img_matches = cv.drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches, None, **draw_params)

#-- Show detected matches
cv.imshow('Matches', img_matches)
cv.waitKey(0)
2.2 SIFT+FLANN算法特征匹配结果
3 小结

简单学习使用opencv-python版本进行调用相关特征匹配函数,当然python2.x在官网示例可以直接运行。python3.x会有一些小地方需要修改,本文是基于python3.x系列的代码,如果你安装的是python3.x系列的话,可以直接运行。逐渐熟悉python-opencv版本函数调用后,将会在以后更新python-opencv相关算法。如有错误,还请批评指正!

4 参考

https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_matcher/py_matcher.html#matcher

### 使用 OpenCV-Python 实现 ORB 特征匹配 ORB (Oriented FAST and Rotated BRIEF) 是一种高效的特征检测与描述方法,在计算机视觉领域广泛应用。通过使用 `cv2.ORB_create()` 函数可以创建一个 ORB 对象用于提取图像中的关键点和描述符。 下面是一个完整的 Python 脚本,展示了如何利用 OpenCV 进行两幅图片之间的 ORB 特征匹配: ```python import cv2 import numpy as np from matplotlib import pyplot as plt def orb_feature_matching(image_path1, image_path2): # 读取两张待比较的图片 img1 = cv2.imread(image_path1, cv2.IMREAD_GRAYSCALE) img2 = cv2.imread(image_path2, cv2.IMREAD_GRAYSCALE) # 初始化 ORB 检测器 orb = cv2.ORB_create() # 查找关键点和描述符 kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) # 创建 BFMatcher 对象并指定距离计算方式为 Hamming Distance bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 匹配描述子向量 matches = bf.match(des1, des2) # 根据 distance 排序 matches = sorted(matches, key=lambda x: x.distance) # 绘制前 10 个最佳匹配结果 matched_img = cv2.drawMatches( img1, kp1, img2, kp2, matches[:10], outImg=None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS ) plt.figure(figsize=(10, 8)) plt.imshow(matched_img), plt.title("Top 10 Matches"), plt.axis('off') plt.show() if __name__ == "__main__": orb_feature_matching('image1.jpg', 'image2.jpg') # 替换为实际路径 ``` 此脚本实现了如下功能: - 加载两个输入图像,并将其转换成灰度模式; - 利用 ORB 算法获取每张图像的关键点及其对应的描述符; - 建立基于汉明距离的暴力匹配器来寻找最接近的匹配项; - 将找到的最佳匹配可视化展示出来[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值