一、应用场景
1.图像搜索,以图搜图。
2.拼图游戏。
3.图像拼接,将两张有关联的图拼接在一起。
二、基础概念
2.1 什么是图像特征?
图像特征就是指有意义的图像区域,具有独特性、易于识别性,比如角点、斑点以及高密度区。
从上图我们可以发现:
A、B两图我们很难找到具体定位;
C、D两图可以找到一些相似区域,但不太容易确定;
E、F两图则很容易确定其定位,即特征信息丰富。
由此,我们可以知道角点是非常重要的特征信息。
2.2 角点
(1)在特征中最重要的是角点;
(2)灰度梯度的最大值对应的像素点;
(3)两条线的交点;
(4)极值点(一阶导数最大值,但二阶导数为0)。
三、特征检测
3.1 角点检测
3.1.1 Harris角点检测
- 光滑地区,无论向哪个移动,衡量系数不变
- 边缘地区,垂直边缘移动时,衡量系统剧烈变化
- 在交点处,往那个方向移动,衡量系统都发生剧烈变化
Harris角点检测API
- cornerHarrris(img,dst,blockSize,ksize,k)
- blockSize: 检测窗口大小
- ksize: Sobel的卷积核
- k 权重系数,经验值,一般取0.02-0.04之间
import cv2
import numpy as np
# 读取图片
img = cv2.imread('./chess.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris角点检测
dst = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04)
# Harris角点的展示
img[dst > 0.01*dst.max()] = (0, 0, 255)
cv2.imshow('Harris', img)
cv2.waitKey(0)
3.1.2 Shi-Tomasi角点检测
- shi- tomasi是Harris角点检测的改进
- Harris角点检测算的稳定性和k有关,而k是个经验值,不好设定最佳值
Shi-Tomasi角点检测API
- goodFeaturesToTrack(img,maxCorners,…)
- maxCorners:角点的最大数,值为0表示无限制
- qualityLevel:小于1.0的正数,一般在0.01-0.1之间
- minDistance:角之间最小欧式距离,忽略小于此距离的点
- mask: 感兴趣的区域
- blockSize:检测窗口
- useHarrisDectector:是否使用Harris算法
- k :默认是0.04
import cv2
import numpy as np
img = cv2.imread('./chess.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 角点检测
corners = cv2.goodFeaturesToTrack(gray, maxCorners=1000, qualityLevel=0.01, minDistance=10,)
corners = np.int0(corners)
# Shi-Tomasi绘制角点
for i in corners:
x,y = i.ravel()
cv2.circle(img, (x,y), 3, (0,0,255),-1)
cv2.imshow('Shi-Tomasi', img)
cv2.waitKey(0)
3.1.3 检测效果展
图1 原图 图2 Harris角点检测 图3 Shi-Tomasi角点检测
3.2关键点与描述子
- 关键点:位置,大小和方向
- 关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换、光照变换等的影响
3.2.1 SIFT(Scale-Invariant Feature Transfrom)特征检测
SIFT出现的原因
- Harris 角点具有旋转不变的特性,但缩放后,原来的角点有可能就不是角点了,如下图所示:
使用SIFT的步骤
- 创建SIFT对象,sift = cv2.SIFT_create()
- 进行检测,kp = sift.detect(img,…)
- 绘制关键点,drawKeypoints(gray, kp, img)
计算描述子
- kp,des=sift.compute(img,kp)
- 其作用就是进行特征匹配
同时计算关键点和描述子的API
- kp,des=sift.detectAndCompute(img,…)
- mask:指明对img中哪个区域进行计算
3.2.2 SURF(Speeded-Up Robust Features)特征检测
SURF的优点
- SIFT最大的问题就是速度慢,因此才有SURF
使用SURF的步骤
- surf = cv2.xfeatures2d.SURF_create()
- kp, des = surf.detectAndCompute(img, mask)
3.2.3 ORB(Orirnted FAST and Rotated BRIEF)特征检测
ORB的优点
- 可以实现实时检测
- ORB = Orirnted FAST + Rotated BRIEF,即是两种技术的结合
- FAST 可以做到特征点的实时检测
-
BRIEF 对已经检测到的特征点进行描述,加快了特征点描述符建立的速度,同时也极大的降低了特征匹配的时间
使用ORB的步骤
- orb = cv2.ORB_create()
- kp,des =orb.detectAndCompute(img,mask)
3.2.4 代码及检测效果
import cv2
import numpy as np
# 读文件
img = cv2.imread('chess.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建sift对象,进行检测
sift = cv2.SIFT_create()
kp,des = sift.detectAndCompute(gray, None)
# 创建SURF对象,进行检测
# surf = cv2.xfeatures2d.SURF_create()
# kp,des = surf.detectAndCompute(gray, None)
# 创建ORB对象,进行检测
# orb = cv2.ORB_create()
# kp,des = orb.detectAndCompute(gray, None)
# print(des)
# 绘制keypoints
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)
图1 原图 图2 SIFT特征检测 图3 ORB特征检测
四、特征匹配
4.1 BF(Brute-Force)暴力特征匹配方法
暴力特征匹配方法的原理(枚举)
- 它使用第一组中的每个特征的描述子,与第二组中的所有特征描述子进行匹配
- 计算他们之间的差距,然后将最接近一个匹配返回(也即计算他们之间的相似度)
openCV特征匹配的步骤
- 创建匹配器,BFMatcher(normType, crossCheck)
- 进行特征匹配,bf.match(des1,des2)
- 绘制匹配点,cv2.drawMatches(img1,kp1,img2,k2)
import cv2
import numpy as np
# 读取图片
img1 = cv2.imread('2.jpg')
img2 = cv2.imread('1.jpg')
# # 灰度化
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 检测特征点+描述子
sift = cv2.SIFT_create() # 创建SIFT对象
kp1, des1 = sift.detectAndCompute(gray1, None) # 对整个图像进行检测,掩码设为None
kp2, des2 = sift.detectAndCompute(gray2, None) # 对整个图像进行检测,掩码设为None
# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_L1)
match = bf.match(des1, des2) # 获得匹配点
res = cv2.drawMatches(img1, kp1, img2, kp2, match, None) # 绘制匹配点
# cv.drawKeypoints(gray, kp, img) # 绘制特征点
# # 显示图像
cv2.imshow('BF', res)
cv2.waitKey(0)
4.2 FLANN最快邻近区特征匹配方法
FLANN优缺点
- 在进行批量特征匹配时,FLANN速度更快
- 由于它使用的是邻近近似值,所以精度较差
使用FLANN特征匹配的步骤
- 创建FLANN匹配器,FlannBasedMatcher(…)
- 进行特征匹配,flann.match/knnMatch(…)
- 绘制匹配点,cv.drawMatches/drawMatchesKnn(…)
import cv2
import numpy as np
# 读取图片
img1 = cv2.imread('2.jpg')
img2 = cv2.imread('1.jpg')
# 灰度化
gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
# 创建sift特征匹配器
sift = cv2.SIFT_create()
# 计算描述子与特征点
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)
# 创建匹配器
index_params = dict(algorithm=1, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 对描述子进行匹配
matches = flann.knnMatch(des1, des2, k=2)
good = []
for i, (m, n) in enumerate(matches):
if m.distance < 0.7*n.distance:
good.append(m)
# 绘制匹配点
ret = cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)
cv2.imshow('FLANN', ret)
cv2.waitKey(0)
4.3 特征匹配效果图
图1 BF暴力特征匹配 图2 FLANN特征匹配文章来源:https://www.toymoban.com/news/detail-494470.html
注:内容来自慕课网李超老师的视频课程整理。文章来源地址https://www.toymoban.com/news/detail-494470.html
到了这里,关于openCV 图像特征点检测与匹配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!