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

本文旨在总结opencv-python上特征点的检测和匹配。
1、特征点的检测(包括:ORB,SIFT,SURFT)
2、特侦点匹配方法 (包括:暴力法,FLANN,以及随机抽样一致性优化RANSAC算法)
注:由于SURF专利问题,所以opencv官方包目前不支持SURF但支持ORB和SIFT,安装opencv-contrib-python包就可以解决

pip uninstall opencv-python
pip 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 np
import cv2
from 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 np
import cv2
from 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 np
import cv2
from 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 np
import cv2
from 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 np
import cv2
from 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 np
import cv2
from 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 np
import cv2
from 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、ORB
2、SIFT
3、SURF
""""""
一、图像特征点的检测
"""
import numpy as np
import cv2
from 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]相关推荐

  1. 计算机视觉与深度学习 | ORB特征提取:基于OpenCV+Python(附代码)

    ===================================================== github:https://github.com/MichaelBeechan CSDN: ...

  2. 毕业设计 - 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

    文章目录 1 简介 2 传统机器视觉的手势检测 2.1 轮廓检测法 2.2 算法结果 2.3 整体代码实现 2.3.1 算法流程 3 深度学习方法做手势识别 3.1 经典的卷积神经网络 3.2 YOL ...

  3. 图像特征点检测与匹配评价准则——量化

    欢迎转载,转载请注明出处,谢谢! 目前图像匹配中,局部特征匹配占据了绝大部分,常用的局部特征匹配方法有Harris.SIFT.SURF.ORB等等,不同的特征点检测和匹配方法尤其独特的优势和不足:  ...

  4. 【图像处理】——特征匹配(SIFT特征检测器+FLANN特征匹配方法+KNN近邻最优匹配筛选)——cv.xfeatures2d.SIFT_create()sift.detectAndCompute

    转载请注明地址 目录 1.特征检测和特征匹配方法 (1)特征检测算法 (2)特征匹配算法 (3)各种特征检测算法的比较 2.特征匹配的基本步骤(附带主要的函数) (1)图像预处理--灰度化(模板--查 ...

  5. 图像特征点检测与匹配评价——量化指标

    原文:http://blog.csdn.net/cgwang_1580/article/details/68944319 目前图像匹配中,局部特征匹配占据了绝大部分,常用的局部特征匹配方法有Harri ...

  6. 基于图像的三维建模——特征点检测与匹配

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:梦寐mayshine 链接:https://zhuanlan.zhihu.com/p/12893 ...

  7. 系统性综述:特征点检测与匹配

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨梦寐mayshine@知乎(已授权) 来源丨https://zhuanlan.zhihu.com ...

  8. 基于图像的三维重建——特征点检测与匹配(2)

    文章目录 前言 一.特征点检测 二阶的拉普拉斯高斯边缘提取算法(LOG) 尺度不变特征变换算法(SIFT) 加速稳健特征算法(SURF) Harris角点特征提取算子 加速分割测试特征提取(FAST) ...

  9. 十.OpenCv 特征点检测和匹配

    特征点检测和匹配 1. 特征检测的基本概念 特征检测是计算机视觉和图像处理中的一个概念.它指的是使用计算机提取图像信息,决定每个图像的点是否属于一个图像特征.特征检测的结果是把图像上的点分为不同的子集 ...

最新文章

  1. 下面可提供安全电子邮件服务的是()【最全!最详细解析!!】
  2. WPF与WCF c#
  3. ffmpeg builds by zeranoe_FFmpeg
  4. ubuntu shell简介
  5. 31模板方法(Template Method)
  6. 工具 | 实用的嵌入式软件测试工具
  7. css修改图标字体大小,css-更改AngularJS材质图标的图标大小
  8. Python安装 第三方库的安装技巧
  9. 射频信号处理知识点点滴滴
  10. MySQL高级篇——锁的概述与案例应用
  11. php excel导入功能
  12. 什么是等级保护?等保二级和三级的区别?
  13. 微软七月十四日发行四个安全补丁
  14. 2020BAJT等九大一线大厂的薪资和职级对比
  15. HTB Optimum[Hack The Box HTB靶场]writeup系列6
  16. 【高中数学选修2-3】排列,组合,二项式定理,杨辉三角
  17. 远程搜索多选组件实现
  18. 读取Excel文件并用jdbc连接将内容导入MySQL数据库
  19. 144 phpstorm如何实现ctrl+s 自动格式化代码
  20. ATM机等待时间详细代码和解释

热门文章

  1. 计算机应用填空题大全,计算机应用基础填空题(附答案)
  2. 极大连通子图与极小连通子图(带图讲解)
  3. 网站友情链接怎么做最好,友情链接如何做详细解读
  4. 张晓波:浅谈大数据应用的知与行|V课堂第82期
  5. git clone 报错fatal: unable to access ‘https://github.com/xxxx‘: OpenSSL SSL_read
  6. 从高德搁置O2O看BAT“圈地”
  7. egg,七牛云上传图片
  8. selenium配置ip代理和无头selenium
  9. php 用 jSignature手写签名保存图片到本地
  10. C语言程序的编译+链接详解