图像特征检测笔记(特征检测基本概念,Harris,Shi-Tomasi,SIFT,SURF,ORB,暴力特征匹配,FLANN特征匹配))
文章目录
-
前言
-
一、特征检测基本概念
-
二、哈里斯角点检测(Harris)
-
- 1.Harris角点基本原理
- 2.Harris角点检测API
- 3.Harris角点检测代码实例:
-
三、Shi-Tomasi角点检测(Shi-Tomasi)
-
- 1.Shi-Tomasi角点基本原理
- 2.Shi-Tomasi角点检测API
- 3.Shi-Tomasi角点检测代码实例:
-
四、SIFT关键点检测(scale-invariant feature transform)
-
- 1.SIFT出现的原因
- 2.使用SIFT的步骤
- 3.SIFT检测代码实例:
-
五、计算SIFT描述子(scale-invariant feature transform)
-
- 1.关键点和描述子
- 2.计算描述子
- 3.计算SIFT描述子代码实例:
-
六、SURF特征检测(speeded-up robust features)
-
- 1.SURF的优点
- 2.使用SURF的步骤
- 3.SURF代码实例:
-
七、ORB特征检测(oriented fast and rotated brief)
-
- 1.ORB优势
- 2.使用ORB的步骤
- 3.ORB代码实例:
-
八、暴力特征匹配
-
- 1.特征匹配方法
- 2.暴力特征匹配原理
- 3.OpenCV特征匹配步骤
- 4.暴力特征匹配代码实例:
-
八、FLANN特征匹配
-
- 1.FLANN优缺点
- 3.FLANN特征匹配步骤
- 4.暴力特征匹配代码实例:
-
总结
前言
基于Python与OpenCV的图像特征匹配学习笔记,供大家参考
一、特征检测基本概念
特征中最重要的是角点,主要包括:
1.灰度梯度的最大值对应的像素
2.两条线的交点
3.极值点(一阶导最大值,二阶导等于0)
二、哈里斯角点检测(Harris)
1.Harris角点基本原理

光滑地区,无论向哪里移动,衡量系数不变;
边缘地区,垂直边缘移动,衡量系数变化剧烈;
在交点处,无论往哪个方向移动,衡量系统都变化剧烈。
2.Harris角点检测API
cornerHarris(img,blockSize,ksize,k)
img:输入图片
blockSize:窗口大小,窗口越大,敏感度越高
ksize:Solel卷积核
k:权重系数,经验值,一般0.02-0.04之间
3.Harris角点检测代码实例:
import cv2
blockSize = 2
ksize = 3
k = 0.04
img = cv2.imread('map1.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris角点检测
dst = cv2.cornerHarris(gray, blockSize, ksize, k)
# 检测结果展示,红色
img[dst > 0.01 *dst.max()] = [0,0,255]
cv2.imshow('harris', img)
cv2.waitKey(0)
三、Shi-Tomasi角点检测(Shi-Tomasi)
1.Shi-Tomasi角点基本原理
Shi-Tomasi是Harris角点检测的改进,不需要设置K值
Harris角点检测的稳定性与K值有关,而K是经验值,不好设定最佳值
2.Shi-Tomasi角点检测API
goodFeaturesToTrack(img,maxCorners,...)
img:输入图片
maxCorners:角点的最大数,值为0表示无限制
qualityLevel:小于1.0的正数,一般在0.01-0.1之间
minDistance:角之间最小欧式距离,忽略小于此距离的点
mask:感兴趣的区域
blockSize:窗口大小,窗口越大,敏感度越高
useHarrisDetector:是否使用Harris算法,默认false
k:默认0.04之间
3.Shi-Tomasi角点检测代码实例:
import cv2
import numpy as np
maxCorners = 1000
ql = 0.01
minDistance = 10
img = cv2.imread('map1.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(gray, maxCorners, ql, minDistance)
corners = np.int0(corners)
for i in corners:
x, y = i.ravel()
cv2.circle(img, (x,y), 3, (255,0,0), -1)
cv2.imshow('harris', img)
cv2.waitKey(0)
四、SIFT关键点检测(scale-invariant feature transform)
1.SIFT出现的原因
Harris角点具有旋转不变的特性,但缩放后会影响角点检测。

2.使用SIFT的步骤
1.创建对象
2.进行检测,kp = sift.detect(img,…)
3.绘制关键点,drawKeypoints(gray,kp, )
goodFeaturesToTrack(img,maxCorners,...)
img:输入图片
maxCorners:角点的最大数,值为0表示无限制
qualityLevel:小于1.0的正数,一般在0.01-0.1之间
minDistance:角之间最小欧式距离,忽略小于此距离的点
mask:感兴趣的区域
blockSize:窗口大小,窗口越大,敏感度越高
useHarrisDetector:是否使用Harris算法,默认false
k:默认0.04之间
3.SIFT检测代码实例:
import cv2
# 读文件
img = cv2.imread('map1.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
# 进行检测,None对整张图进行检测
kp = sift.detect(gray, None)
# 绘制keypoints(特征点)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
五、计算SIFT描述子(scale-invariant feature transform)
1.关键点和描述子
关键点:位置、大小和方向
关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换、关照变换等影响
2.计算描述子
kp,des = sift.compute(img, kp)
其作用是进行特征匹配,分开计算关键点和描述子比较麻烦,下面方法可以同时计算关键点和描述子:
kp,des = sift.detectAndCompute(img,...)
img:输入图片
mask:感兴趣的区域
3.计算SIFT描述子代码实例:
import cv2
# 读文件
img = cv2.imread('map1.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
# 进行检测,None对整张图进行检测
kp, des = sift.detectAndCompute(gray, None)
# 打印查看描述子
print(des[0])
# 绘制keypoints(特征点)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
六、SURF特征检测(speeded-up robust features)
1.SURF的优点
SIFT最大的问题是速度慢,因此才有SURF
2.使用SURF的步骤
surf = cv2.xfeatures2d.SURF_create()
kp,des = surf.detectAndCompute(img,...)
img:输入图片
mask:感兴趣的区域
3.SURF代码实例:
import cv2
# 读文件
img = cv2.imread('map1.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建surf对象
surf = cv2.xfeatures2d.SURF_create()
# 使用surf进行检测
kp, des = surf.detectAndCompute(gray, None)
# 绘制keypoints(特征点)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
七、ORB特征检测(oriented fast and rotated brief)
1.ORB优势
ORB可以做到实时检测
整个算法开源
2.使用ORB的步骤
orb = cv2.ORB_create()
kp, des = orb.detectAndCompute(gray, mask)
img:输入图片
mask:感兴趣的区域
3.ORB代码实例:
import cv2
# 读文件
img = cv2.imread('map1.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建ORB对象
orb = cv2.ORB_create()
# orb进行检测
kp, des = orb.detectAndCompute(gray, None)
# 绘制keypoints(特征点)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
八、暴力特征匹配
1.特征匹配方法
BF(brute-force):暴力特征匹配方法
FLANN:最快近邻取特征匹配方法
2.暴力特征匹配原理
使用第一组中的每一个特征的描述字与第二组中的所有特征描述子进行匹配,计算它们之间的差距,然后将最接近的一个匹配返回。
3.OpenCV特征匹配步骤
创建匹配器,BFMatcher(normType,crosscheck)
进行特征匹配,bf.match(des1, des2)
绘制匹配点,cv2.drawMatches(img1, kp1, img2, kp2, …)
(1)BFMatcher参数:
normType:选择近似度算法,有好几种 NORM_L1, NORM_L2,HAMMING1
NORM_L1取描述子的绝对值进行加法运算;NORM_L2为欧氏距离;HAMMING通过判断二进制位
其中,NORM_L1与NORM_L2用于SIFT和SURF,HAMMING1专门用于ORB,默认使用NORM_L2
crosscheck:是否进行交叉匹配,默认为FALSE
(2)match参数:计算的描述
(3)drawMatches参数
搜索img1, kp1
匹配图img2, kp2
match()方法返回的匹配结果
4.暴力特征匹配代码实例:
import cv2
# 读文件
# img = cv2.imread('chess.png')
img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
# 灰度化
# gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
# 创建surf对象
# surf = cv2.xfeatures2d.SURF_create()
# 创建ORB对象
# orb = cv2.ORB_create()
# 进行检测
# kp, des = sift.detectAndCompute(gray, None)
kp1, des1 = sift.detectAndCompute(g1, None)
kp2, des2 = sift.detectAndCompute(g2, None)
# 使用surf进行检测
# kp, des = surf.detectAndCompute(gray, None)
# orb进行检测
# kp, des = orb.detectAndCompute(gray, None)
# 绘制keypoints(特征点)
# cv2.drawKeypoints(gray, kp, img)
bf = cv2.BFMatcher(cv2.NORM_L1)
match = bf.match(des1, des2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)
# cv2.imshow('img', img)
cv2.imshow('img3', img3)
cv2.waitKey(0)
八、FLANN特征匹配
1.FLANN优缺点
在进行批量特征匹配时,FLANN速度更快
由于它使用的是近邻近似值,所以精度较差
3.FLANN特征匹配步骤
创建匹配器,FlannBasedMatcher(…)
进行特征匹配,flann.match 或者knnMatch(…)
绘制匹配点,cv2.drawMatches/drawMatchesKnn(…)
(1)FlannBasedMatcher参数:
index_params字典:
选择近似度算法,有好几种 NORM_L1, NORM_L2,HAMMING1
NORM_L1取描述子的绝对值进行加法运算;NORM_L2为欧氏距离;HAMMING通过判断二进制位
其中,NORM_L1与NORM_L2用于SIFT和SURF,HAMMING1专门用于ORB,默认使用NORM_L2
crosscheck:是否进行交叉匹配,默认为FALSE
(2)match参数:计算的描述
(3)drawMatches参数
搜索img1, kp1
匹配图img2, kp2
match()方法返回的匹配结果
4.暴力特征匹配代码实例:
import cv2
import numpy as np
#打开两个文件
img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
#灰度化
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
#他建SIFT特征检测器
sift = cv2.xfeatures2d.SIFT_create()
#计算描述子与特征点
kp1, des1 = sift.detectAndCompute(g1, None)
kp2, des2 = sift.detectAndCompute(g2, None)
#创建匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
#对描述子进行匹配计算
matchs = flann.knnMatch(des1, des2, k=2)
good = []
for i, (m, n) in enumerate(matchs):
if m.distance < 0.7 * n.distance:
good.append(m)
if len(good) >= 4:
srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
H, _ = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)
h, w = img1.shape[:2]
pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, H)
cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))
else:
print('the number of good is less than 4.')
exit()
ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
cv2.imshow('result', ret)
cv2.waitKey()
总结
以上是我在学习图像典型特征的一些笔记,希望能给大家带来帮助,有任何问题欢迎大家私信我进行讨论。
