OpenCv特征匹配

OpenCv提供了两种描述符匹配方法:Brute-Force匹配与FLANN匹配

1.Brute-Force匹配

1.1创建BFMatcher对象

1.2使用两个方法:match()或knnMatch()进行描述符匹配 

1.3基于ORB或SIFT的BF匹配

2.FLANN匹配

2.1第一个字典是IndexParams

2.2第二个字典是SearchParams:

2.3FLANN匹配器示例


1.Brute-Force匹配

Brute-Force匹配又称蛮力匹配, 将一组特征点中的每一个特征点描述符与另一组的最接近的特征点描述符匹配。

下面介绍OpenCv中的使用流程:

1.1创建BFMatcher对象

retval = cv.BFMatcher_create([, normType[, crossCheck]]) ,参数详解如下

1.normType:NORM_L1,NORM_L2,NORM_HAMMING,NORM_HAMMING2四种可选。

SIFT与SUFT描述符应使用NORM_L1、NORM_L2。ORB、BRISK和BRIEF描述符应该使用NORM_HAMMING。使用ORB描述符但当WTA_K等于3或4时应该选用NORM_HAMMING2。

2.crossCheck:默认为FALSE。如果设置为TRUE,只有当两组中特征点互相匹配时才算匹配成功。也就是说A组中x点描述符的最佳匹配点是B组的y点,那么B组的y点的描述符最佳匹配点也要是A组的x点才算匹配成功。

1.2使用两个方法:match()或knnMatch()进行描述符匹配 

二者的区别是match()返回最佳匹配,knnMathch()返回最佳的k个匹配。

matches = cv.DescriptorMatcher.match( queryDescriptors, trainDescriptors[, mask] )

# 创建BF匹配器对象
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)

# 特征点描述符匹配
matches = bf.match(des1,des2)

# 距离排序
matches = sorted(matches, key = lambda x:x.distance)

# 画出前30匹配
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:30], None, flags=2)

matches = cv.DescriptorMatcher.knnMatch( queryDescriptors, trainDescriptors, k[, mask[, compactResult]] )

**注意,两种方法对应的画点方法也不一样。 

# 创建BF匹配器对象
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)

# 特征点描述符匹配
matches = bf.knnMatch(des1,des2,k=1)

# 画出前30匹配
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches[:30], None, flags=2)

**关于Matcher对象: 

可能会有人好奇返回的变量matches是什么?其实是一种DMatch数据结构的列表。

DMatch结构含有: 

DMatch.distance:描述符之间的距离,越低越好。

DMatch.queryIdx:主动匹配的描述符组中描述符的索引。

DMatch.trainIdx:被匹配的描述符组中描述符的索引。

DMatch.imgIdx:目标图像的索引。

更详细见:

opencv中match与KnnMatch返回值解释 

1.3基于ORB或SIFT的BF匹配

# 使用ORB描述符进行Brute-Force匹配:

import cv2

img1 = cv2.imread('gyy.jpg')

# 设一个ROI为被匹配的图像
ROI = img1[100:350,150:300]
img2=cv2.resize(ROI,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)

# 初始化ORB特征点检测器
orb = cv2.ORB_create()

# 检测特征点与描述符
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

# 创建蛮力(BF)匹配器
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)

# 匹配描述符
matches = bf.match(des1,des2)

# 整理排序匹配后的描述符
matches = sorted(matches, key = lambda x:x.distance)

# 画出前10个匹配的描述符
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)

cv2.imshow("show",img3)
cv2.waitKey()
cv2.destroyAllWindows()

# 带有SIFT描述符和比例测试的BF匹配:

import cv2

img1 = cv2.imread('gyy.jpg')

# 设一个ROI为被匹配的图像
ROI = img1[250:350,150:300]             # trainImage
img2=cv2.resize(ROI,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)

# 初始化SIFT特征点检测器
sift = cv2.xfeatures2d.SIFT_create()

# 检测特征点与描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# 创建蛮力(BF)匹配器
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)

# 比值测试,首先获取与 A 距离最近的点 B(最近)和 C(次近),只有当 B/C
# 小于阈值时( 0.75)才被认为是匹配,因为假设匹配是一一对应的,真正的匹配的理想距离为 0
good = []
for m,n in matches:
    if m.distance < 0.75*n.distance:
        good.append([m])

# cv.drawMatchesKnn()把列表作为匹配项。
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)

cv2.imshow("show",img3)
cv2.waitKey()
cv2.destroyAllWindows()

2.FLANN匹配

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

基于FLANN的匹配器,我们需要传递两个字典,这些字典指定要使用的算法,其相关参数等。

2.1第一个字典是IndexParams

对于SIFT、SUFT算法应该是:

FLANN_INDEX_KDTREE = 1 
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)

对于ORB算法应该是:

FLANN_INDEX_LSH = 6
index_params= dict(algorithm = FLANN_INDEX_LSH,
                   table_number = 6, # 12
                   key_size = 12,     # 20
                   multi_probe_level = 1) #2

2.2第二个字典是SearchParams:

它指定索引中的树应递归遍历的次数。较高的值可提供更好的精度,但也需要更多时间。例如:

search_params = dict(checks = 100)

2.3FLANN匹配器示例

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

img1 = cv.imread('gyy.jpg',cv.IMREAD_GRAYSCALE)    # 索引图像
img2 = cv.imread('gyy.jpg',cv.IMREAD_GRAYSCALE)    # 训练图像

# 初始化SIFT描述符
sift = cv.xfeatures2d.SIFT_create()

# 基于SIFT找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# FLANN的参数
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)   # 或传递一个空字典
flann = cv.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)

# 只需要绘制好匹配项,因此创建一个掩码
matchesMask = [[0,0] for i in range(len(matches))]

# 根据Lowe的论文进行比例测试
for i,(m,n) in enumerate(matches):
    if m.distance < 0.7*n.distance:
        matchesMask[i]=[1,0]
draw_params = dict(matchColor = (0,255,0),
                   singlePointColor = (255,0,0),
                   matchesMask = matchesMask,
                   flags = cv.DrawMatchesFlags_DEFAULT)
img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)

plt.imshow(img3,),plt.show()
  • 9
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
OpenCV中,特征匹配是一个常用的计算机视觉任务,它可以用于在图像中找到相似的特征点或对象。OpenCV提供了几种特征匹配算法,其中最常见的是基于特征描述子的匹配算法,例如SIFT(Scale-Invariant Feature Transform)和SURF(Speeded-Up Robust Features)。 要进行特征匹配,首先需要检测图像中的特征点。这可以使用SIFT、SURF或其他检测器来完成。然后,提取这些特征点的描述子,描述子是一种能够唯一描述特征点的向量。 接下来,我们可以使用一些匹配算法,如暴力匹配(Brute-Force Matching)或基于kd树的匹配来比较两个图像中的特征点,并找到最佳匹配。 以下是一个简单的代码示例,展示了如何使用OpenCV进行SIFT特征匹配: ```python import cv2 # 加载图像 img1 = cv2.imread('image1.jpg', 0) img2 = cv2.imread('image2.jpg', 0) # 创建SIFT对象 sift = cv2.xfeatures2d.SIFT_create() # 检测和计算描述子 kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) # 创建暴力匹配器对象 bf = cv2.BFMatcher() # 使用KNN匹配算法进行特征匹配 matches = bf.knnMatch(des1, des2, k=2) # 应用比值测试,以筛选出最佳匹配 good_matches = [] for m, n in matches: if m.distance < 0.75 * n.distance: good_matches.append([m]) # 绘制匹配结果 img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good_matches, None, flags=2) # 显示结果 cv2.imshow('Matches', img3) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这只是一个简单的示例,你可以根据自己的需求进一步调整参数和优化算法。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东东咚咚东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值