失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 特征点的检测与匹配(ORB SIFT SURFT比较)[opencv-python]

特征点的检测与匹配(ORB SIFT SURFT比较)[opencv-python]

时间:2024-05-08 07:18:18

相关推荐

特征点的检测与匹配(ORB SIFT SURFT比较)[opencv-python]

特征点的检测与匹配(ORB,SIFT,SURFT比较)

本文旨在总结opencv-python上特征点的检测和匹配。

1、特征点的检测(包括:ORB,SIFT,SURFT)

2、特侦点匹配方法 (包括:暴力法,FLANN,以及随机抽样一致性优化RANSAC算法)

注:由于SURF专利问题,所以opencv官方包目前不支持SURF但支持ORB和SIFT,安装opencv-contrib-python包就可以解决

pip uninstall opencv-pythonpip install opencv-contrib-python==3.4.2.17

一、特征点检测

1、ORB算法

大致步骤:

ORB 的特点是速度超快,而且在一定程度上不受噪点和图像变换的影响,例如旋转和缩放变换等。

原理(步骤:)

(1)对图像进行多个版本的下采样,构建图像金字塔。对每个采样图像进行特征点检测。

(2)采用FAST特征点检测算法来检测特征点。

(3)采用BRIEF描述子来描述每个特征点。注:描述子可以理解为一个用来描述特征点的向量,每个特侦点都有对应的描述子,后面的特征点匹配就是对每个特征点之间描述子是否相似的判断。

关于FAST特征点检测算法:

FAST算法定义:特征点是如果某个像素点和他周围领域足够多的像素点处于不同区域,那么这个像素点就是特征点。

对于灰度图,及特征点处灰度值与周围足够多像素灰度值不同。即设定一个阈值若16个点中有n(取12)个点的灰度与中心点的灰度差超过阈值则判断为特征点。

关于BRIEF描述子

后面再补充—

实现代码如下:

import numpy as npimport cv2from matplotlib import pyplot as pltdef ORB(img):"""ORB角点检测实例化ORB对象"""orb = cv2.ORB_create(nfeatures=500)"""检测关键点,计算特征描述符"""kp, des = orb.detectAndCompute(img, None)# 将关键点绘制在图像上img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)cv2.imwrite("1.jpg", img2)# 画图plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img2[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desimg1 = cv2.imread("../asset/image/5.jpg")kp1, des1 = ORB(img1)

结果如图:

可以看出ORB可以提取一些关键的特征点

2、SIFT算法

SIFT特征点:尺度不变特征变换(Scale-invariant feature transform):大致方法是首先搜索所有尺度下图像的位置,通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点,然后在候选位置通过拟合精细的模型来确定位置和尺度,再基于图像梯度,分配给关键点一个或多个方向,最后在每个关键点的周围邻域,在选定的尺度下测量图像局部梯度来描述关键点。(总的来说就是根据梯度描述关键点)

图像高斯金字塔就考虑了这两个方面:① 图像的远近程度;② 图像的模糊程度(理解为粗细更好)。前者通过上下采样来实现,后者通过高斯平滑处理来实现。

所谓的高斯金字塔是由原始图像的n层下采样图像组成,然后在每个下采样的层中利用不同核大小的高斯滤波来生成t张图像,t张图像除了第一张和最后一张其余图像在本张、上张、下张一共26个点中看是否为极值。

具体原理可参考

代码如下:

import numpy as npimport cv2from matplotlib import pyplot as pltdef SIFT(img):# SIFT算法关键点检测# 读取图像gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# SIFT关键点检测# 1. 实例化siftsift = cv2.xfeatures2d.SIFT_create()# 2. 利用sift.detectAndCompute()检测关键点并计算kp, des = sift.detectAndCompute(gray, None)# gray: 进行关键带你检测的图像,注意是灰度图像# kp: 关键点信息,包括位置,尺度,方向信息# des: 关键点描述符,每个关键点对应128个梯度信息的特征向量# 3. 将关键点检测结果绘制在图像上# cv2.drawKeypoints(image, keypoints, outputimage, color, flags)# image: 原始图像# keypoints: 关键点信息,将其绘制在图像上# outputimage: 输出图片,可以是原始图像# color: 颜色设置,通过修改(b, g, r)的值,更改画笔的颜色,b = 蓝色, g = 绿色, r = 红色# flags: 绘图功能的标识设置# 1. cv2.DRAW_MATCHES_FLAGS_DEFAULT: 创建输出图像矩阵,使用现存的输出图像绘制匹配对象和特征点,对每一个关键点只绘制中间点# 2. cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG: 不创建输出图像矩阵,而是在输出图像上绘制匹配对# 3. cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS: 对每一个特征点绘制带大小和方向的关键点图形# 4. cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS: 单点的特征点不被绘制cv2.drawKeypoints(img, kp, img, (0, 255, 0))cv2.imwrite("1.jpg", img)# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desimg1 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SIFT(img1)

结果如图:

看以看出SIFT算法所求的特征点远远大于ORB

3、SURF算法

SURF特征点:加速稳健特征(Speeded Up Robust Features):加速版的SIFT。通过修改滤波器的尺寸和模糊度从而得到不同层级的影像,别的和SIFT差不多。

Surf是可以说是对Sift算法的改进,该算子在保持 SIFT 算子优良性能特点的基础上,同时解决了 SIFT 计算复杂度高、耗时长的缺点,提升了算法的执行效率,为算法在实时计算机视觉系统中应用提供了可能,SIFT在一般的计算机对于日常使用的图片想做到实时基本上是不可能的。

代码如下:

import numpy as npimport cv2from matplotlib import pyplot as pltdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))cv2.imwrite("1.jpg", img)# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desimg1 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)

结果如图

可以看到和SIFT差不多密密麻麻的一大片,密集恐惧症看的都哭了,

可达鸭,你…绿了。 可达鸭:我%#@#¥%#¥#¥¥##¥¥%!你不准丑化我,我可是顶流。

特征点检测还有些其他的算法,就先介绍这么多,以后有时间在总结。

二、特征点匹配算法

1、暴力求解

让前一个图像的每一个特征点直接遍历后一个图像的所有特征点,找到最小值即为匹配,真的是简单粗暴。

代码:暴力求解+SURF

import numpy as npimport cv2from matplotlib import pyplot as pltdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef ByBFMatcher(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)暴力法:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法或SURFbf = cv2.BFMatcher_create(cv2.NORM_L1, crossCheck=False)else:# ORB方法bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=False)ms = bf.match(des1, des2)# ms = sorted(ms, key=lambda x: x.distance)img3 = cv2.drawMatches(img1, kp1, img2, kp2, ms, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imwrite("1.jpg", img3)cv2.imshow("Matches", img3)cv2.waitKey(0)return msimg1 = cv2.imread("../asset/image/4.jpg")img2 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)kp2, des2 = SURF(img2)matches = ByBFMatcher(img1, img2, kp1, kp2, des1, des2, "SIFT")

结果如下

可以看得出来,什么也看不出来,一团乱麻,而且一看就有很多误匹配的,不急后文讲优化的时候会解决这一问题。‘

可达鸭:喂喂喂,我人都没了,你这可恶的人类。

如果想使用ORB就可以把上面的ORB函数粘贴进来,然后修改这几行,SIFT同理。

kp1, des1 = ORB(img1)kp2, des2 = ORB(img2)matches = ByBFMatcher(img1, img2, kp1, kp2, des1, des2, "ORB")

1、FLANN求解

使用快速近似最近邻搜索算法寻找。

代码:FLANN + SURF

import numpy as npimport cv2from matplotlib import pyplot as pltdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef ByFlann(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)FLANN匹配器:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)search_params = dict(check=50)else:# ORB方法FLANN_INDEX_LSH = 6index_params = dict(algorithm=FLANN_INDEX_LSH,table_number=6,key_size=12,multi_probe_level=1)search_params = dict(check=50)# 定义FLANN参数flann = cv2.FlannBasedMatcher(index_params, search_params)matches = flann.match(des1, des2)img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imshow("Matches", img3)cv2.imwrite("1.jpg", img3)cv2.waitKey(0)return matchesimg1 = cv2.imread("../asset/image/4.jpg")img2 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)kp2, des2 = SURF(img2)matches = ByFlann(img1, img2, kp1, kp2, des1, des2, "SIFT")

结果如下

依旧看不见鸭鸭。

三、优化

由上图匹配结果可以看出存在较多误匹配现象所以必须采取手段来实现减少误匹配。

1、RANSAC算法

RANSAC算法,是随机抽样一致。

代码如下:FLANN + SURF + RANSAC

import numpy as npimport cv2from matplotlib import pyplot as pltdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef ByFlann(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)FLANN匹配器:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)search_params = dict(check=50)else:# ORB方法FLANN_INDEX_LSH = 6index_params = dict(algorithm=FLANN_INDEX_LSH,table_number=6,key_size=12,multi_probe_level=1)search_params = dict(check=50)# 定义FLANN参数flann = cv2.FlannBasedMatcher(index_params, search_params)matches = flann.match(des1, des2)# img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)# cv2.imshow("Matches", img3)# cv2.imwrite("1.jpg", img3)# cv2.waitKey(0)return matchesdef RANSAC(img1, img2, kp1, kp2, matches):MIN_MATCH_COUNT = 10# store all the good matches as per Lowe's ratio test.matchType = type(matches[0])good = []print(matchType)if isinstance(matches[0], cv2.DMatch):# 搜索使用的是matchgood = matcheselse:# 搜索使用的是knnMatchfor m, n in matches:if m.distance < 0.7 * n.distance:good.append(m)if len(good) > MIN_MATCH_COUNT:src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)# M: 3x3 变换矩阵.M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)matchesMask = mask.ravel().tolist()# h, w = img1.shape# pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)# dst = cv2.perspectiveTransform(pts, M)## img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)else:print"Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT)matchesMask = Nonedraw_params = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=matchesMask, # draw only inliersflags=2)img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)draw_params1 = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=None, # draw only inliersflags=2)img33 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params1)cv2.imwrite("1.jpg", img33)cv2.imwrite("2.jpg", img3)cv2.imshow("before", img33)cv2.imshow("now", img3)cv2.waitKey(0)img1 = cv2.imread("../asset/image/4.jpg")img2 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)kp2, des2 = SURF(img2)matches = ByFlann(img1, img2, kp1, kp2, des1, des2, "SIFT")RANSAC(img1, img2, kp1, kp2, matches)

结果:

不使用RANSAC

使用RANSAC

可以看到匹配的特征点减少了很多,但是还是存在误匹配的现象,效果不够理想。

2、使用knnMatch

就是将flann.knnMatch改为flann.match

使用knnMatch得到的matches会是一个tuple,里面储存两个match。

match结构为:

queryIdx:当前帧特征点序号

trainIdx:下一帧最为匹配的特征点序号

distance:距离

一个match存最接近,一个match存次最接近。

代码如下:

import numpy as npimport cv2from matplotlib import pyplot as pltdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef ByFlann(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)FLANN匹配器:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)search_params = dict(check=50)else:# ORB方法FLANN_INDEX_LSH = 6index_params = dict(algorithm=FLANN_INDEX_LSH,table_number=6,key_size=12,multi_probe_level=1)search_params = dict(check=50)# 定义FLANN参数flann = cv2.FlannBasedMatcher(index_params, search_params)matches = flann.knnMatch(des1, des2, k=2)# img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)# cv2.imshow("Matches", img3)# cv2.imwrite("1.jpg", img3)# cv2.waitKey(0)return matchesdef RANSAC(img1, img2, kp1, kp2, matches):MIN_MATCH_COUNT = 10# store all the good matches as per Lowe's ratio test.matchType = type(matches[0])good = []print(matchType)if isinstance(matches[0], cv2.DMatch):# 搜索使用的是matchgood = matcheselse:# 搜索使用的是knnMatchfor m, n in matches:if m.distance < 0.7 * n.distance:good.append(m)if len(good) > MIN_MATCH_COUNT:src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)# M: 3x3 变换矩阵.M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)matchesMask = mask.ravel().tolist()# h, w = img1.shape# pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)# dst = cv2.perspectiveTransform(pts, M)## img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)else:print"Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT)matchesMask = Nonedraw_params = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=matchesMask, # draw only inliersflags=2)img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)draw_params1 = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=None, # draw only inliersflags=2)img33 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params1)cv2.imwrite("1.jpg", img33)cv2.imwrite("2.jpg", img3)cv2.imshow("before", img33)cv2.imshow("now", img3)cv2.waitKey(0)img1 = cv2.imread("../asset/image/4.jpg")img2 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)kp2, des2 = SURF(img2)matches = ByFlann(img1, img2, kp1, kp2, des1, des2, "SIFT")RANSAC(img1, img2, kp1, kp2, matches)

结果:

使用FLANN + SURF(match) + RANSAC

使用FLANN + SURF(knnMatch) + 不使用RANSAC

使用FLANN + SURF(knnMatch) + RANSAC

由上面可以看出,就算不使用RANSAC,单单就FLANN + SURF(knnMatch)的效果就已经比FLANN + SURF(match) + RANSAC好很多,当然效果最好的还是FLANN + SURF(knnMatch) + RANSAC。

可达鸭:我就一直绿呗。

四、总结

1、总的来说就时效性应该是ORB>SURF>SIFT, FLANN>暴力求解。具体对比可以参考这篇文章

2、从效果来看FLANN + SURF/SURF(knnMatch) + RANSAC是最好的。ORB好像不支持knnMatch,我后面再测测看。

3、整个程序源码放在最后,大家可以依据自己的需要组合成不的方式。

程序代码:

要想使用knnMatch,把SURT,SIFT函数里面的

matches = flann.match(des1, des2)

改为

matches = flann.knnMatch(des1, des2, k=2)

"""图像特征点的检测与匹配主要涉及:1、ORB2、SIFT3、SURF""""""一、图像特征点的检测"""import numpy as npimport cv2from matplotlib import pyplot as pltdef ORB(img):"""ORB角点检测实例化ORB对象"""orb = cv2.ORB_create(nfeatures=500)"""检测关键点,计算特征描述符"""kp, des = orb.detectAndCompute(img, None)# 将关键点绘制在图像上img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)# 画图plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img2[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef SIFT(img):# SIFT算法关键点检测# 读取图像gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# SIFT关键点检测# 1. 实例化siftsift = cv2.xfeatures2d.SIFT_create()# 2. 利用sift.detectAndCompute()检测关键点并计算kp, des = sift.detectAndCompute(gray, None)# gray: 进行关键带你检测的图像,注意是灰度图像# kp: 关键点信息,包括位置,尺度,方向信息# des: 关键点描述符,每个关键点对应128个梯度信息的特征向量# 3. 将关键点检测结果绘制在图像上# cv2.drawKeypoints(image, keypoints, outputimage, color, flags)# image: 原始图像# keypoints: 关键点信息,将其绘制在图像上# outputimage: 输出图片,可以是原始图像# color: 颜色设置,通过修改(b, g, r)的值,更改画笔的颜色,b = 蓝色, g = 绿色, r = 红色# flags: 绘图功能的标识设置# 1. cv2.DRAW_MATCHES_FLAGS_DEFAULT: 创建输出图像矩阵,使用现存的输出图像绘制匹配对象和特征点,对每一个关键点只绘制中间点# 2. cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG: 不创建输出图像矩阵,而是在输出图像上绘制匹配对# 3. cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS: 对每一个特征点绘制带大小和方向的关键点图形# 4. cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS: 单点的特征点不被绘制cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, desdef SURF(img):surf = cv2.xfeatures2d.SURF_create()kp, des = surf.detectAndCompute(img, None)cv2.drawKeypoints(img, kp, img, (0, 255, 0))# 图像显示plt.figure(figsize=(10, 8), dpi=100)plt.imshow(img[:, :, ::-1])plt.xticks([]), plt.yticks([])plt.show()return kp, des"""2.图像特征点匹配方法(1)暴力法(2)FLANN匹配器"""def ByBFMatcher(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)暴力法:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法bf = cv2.BFMatcher_create(cv2.NORM_L1, crossCheck=False)else:# ORB方法bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=False)ms = bf.knnMatch(des1, des2, k=2)# ms = sorted(ms, key=lambda x: x.distance)# img3 = cv2.drawMatches(img1, kp1, img2, kp2, ms, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)# cv2.imshow("Matches", img3)# cv2.waitKey(0)return msdef ByFlann(img1, img2, kp1, kp2, des1, des2, flag="ORB"):"""(1)FLANN匹配器:param img1: 匹配图像1:param img2: 匹配图像2:param kp1: 匹配图像1的特征点:param kp2: 匹配图像2的特征点:param des1: 匹配图像1的描述子:param des2: 匹配图像2的描述子:return:"""if (flag == "SIFT" or flag == "sift"):# SIFT方法FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE,trees=5)search_params = dict(check=50)else:# ORB方法FLANN_INDEX_LSH = 6index_params = dict(algorithm=FLANN_INDEX_LSH,table_number=6,key_size=12,multi_probe_level=1)search_params = dict(check=50)# 定义FLANN参数flann = cv2.FlannBasedMatcher(index_params, search_params)matches = flann.knnMatch(des1, des2, k=2)return matches"""优化匹配结果RANSAC算法是RANdom SAmple Consensus的缩写,意为随机抽样一致"""def RANSAC(img1, img2, kp1, kp2, matches):MIN_MATCH_COUNT = 10# store all the good matches as per Lowe's ratio test.matchType = type(matches[0])good = []print(matchType)if isinstance(matches[0], cv2.DMatch):# 搜索使用的是matchgood = matcheselse:# 搜索使用的是knnMatchfor m, n in matches:if m.distance < 0.7 * n.distance:good.append(m)if len(good) > MIN_MATCH_COUNT:src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)# M: 3x3 变换矩阵.M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)matchesMask = mask.ravel().tolist()# h, w = img1.shape# pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)# dst = cv2.perspectiveTransform(pts, M)## img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)else:print"Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT)matchesMask = Nonedraw_params = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=matchesMask, # draw only inliersflags=2)img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)draw_params1 = dict(matchColor=(0, 255, 0), # draw matches in green colorsinglePointColor=None,matchesMask=None, # draw only inliersflags=2)img33 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params1)cv2.imshow("before", img33)cv2.imshow("now", img3)cv2.waitKey(0)img1 = cv2.imread("../asset/image/4.jpg")img2 = cv2.imread("../asset/image/5.jpg")kp1, des1 = SURF(img1)kp2, des2 = SURF(img2)matches = ByFlann(img1, img2, kp1, kp2, des1, des2, "SIFT")RANSAC(img1, img2, kp1, kp2, matches)

如果觉得《特征点的检测与匹配(ORB SIFT SURFT比较)[opencv-python]》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。