R=cv.cornerHarris(img,blockSize,ksize,k)
corners=cv.goodFeaturesToTrack(img,maxCorners,qualityLevel,minDistance)
array=矩阵.ravel()
矩阵.astype("int")
目录
SIFT
1.原理
2.步骤
【1】尺度空间极值检测:
【2】关键点定位(去除噪声点和边界点):
【3】关键点方向确定:
【4】关键点描述:
3.代码API
SURF
总结,这节课你学到了什么?
Harris和Shi-tomas具有旋转不变性但不具有尺度不变性,当图片缩放后角点数量会变化。
SIFT具有尺度不变性,实质是在不同尺度上检测特征点,并计算出特征点方向,SIFT查找的特征点突出,不会因为光照,仿射变换,噪声而发生变化
搜索所有尺度上的图像位置。通过高斯差分函数来识别潜在的对于尺度和旋转不变的关键点。
不同空间尺度下用不同的检测窗口,对于小关键点,用小窗口,大关键点用大窗口。
一个图像的尺度空间L(x,y,σ),定义为原始图像l(x,y)与一个可变尺度的2维高斯函数G(x,y,σ)(2维正态分布函数)卷积运算,即:
σ为标准差也称尺度空间,σ越大,图像越大尺度,越模糊。通过观察二维高斯函数,一般认为一个点上下左右3σ之内的像素起作用,所以高斯核大小为(6σ+1,6σ+1)就可以保证相关像素的影响,高斯核是唯一可以产生多尺度空间的核函数。
1.下面来构建高斯金字塔
(1)首先进行升采样,尽可能多保留原始图像信息
(2)逐步降采样(下采样),进行高斯模糊
几个模糊的图像构成一个Octave(一般为三个图像),下采样使得图片的长宽各缩小为原来一半,这个图像就是下一个Octave初始图像,依次完成整个八度构建完成金字塔构建。
3.构建高斯差分金字塔
利用LoG(高斯拉普拉斯方法),即图像的二阶导数,可以在不同的尺度下检测图像的关键点信息,从而确定图像的特征点。但LoG的计算量大,效率低。所以我们通过两个相邻高斯尺度空间的图像的相减得到DoG(高斯差分)来近似LoG。
后续SIFT特征点都是在差分金字塔上获取的。
在差分金字塔上搜索局部最大值。对于图像中的一个像素点而言,它需要与自己周围的8邻域,以及尺度空间中,上下两层中的相邻的18 (2x9) 个点相比。如果是局部最大值,它就可能是一个关键点。基本.上来说关键点是图像在相应尺度空间中的最好代表。如下图所示:
由于噪声和边缘影响,还要进一步检验确定特征点。
尺度空间的泰勒级数展开,极值点小于阈值(contrastThreshold,一般为0.03或0.04)被忽略;
DoG算法对边界即为明显,Harris算法不仅可以角点检测,也可以进行边界检测,俩个特征值比值大于莫个阈值被忽略。
图像的关键点已经确定,为实现旋转不变性,基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。
对于任一关键点,我们采集其所在高斯金字塔图像,关键点为中心,以r为半径的区域内所有像素梯度特征(幅值和幅角) ,半径r为:
梯度的幅值和方向公式:
可视化举例
完成关键点梯度和幅度计算后,进行直方图统计,像素梯度的幅值根据举例中心像素位置,进行高斯加权,方差为1.5σ,再叠加到直方图的高度y上
分配给特征点一个主方向,一个或多个辅方向,再进行插值拟合得到曲线,得到更精确的角度
主方向为直方图最高值方向,辅方向直方图高度为主方向的80%-100%
获得图像关键点主方向后,每个关键点有三个信息(x,y,σ,θ):位置x,y、尺度σ、方向θ。由此我们可以确定一个SIFT特征区域。通常使用一个带箭头的圆或直接使用箭头表示SIFT区域的三个值:中心表示特征点位置,半径表示关键点尺度,箭头表示方向。如下图所示:
在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度作为关键点的描述符,它允许比较大的局部形状的变形、光照变化、视角变化。描述符不仅具有关键点,还包括周围有贡献的点,具有可区分性。
主要思路就是通过将关键点周围图像区域分块d x d个子区域(d一般取4),每个区域大小为(3σ,3σ),考虑需要进行三次线性插值,特征点领域总大小为(3σ(d+1),3σ(d+1))
为保持旋转不变性,以特征点为中心,将坐标轴旋转到主方向的方向上
计算小区域d x d个小区域,每个小区域(3σ,3σ)的梯度直方图,σ=0.5高斯加权,生成具有特征向量,插值计算八方向个梯度,对图像信息进行抽象。
每个种子点,会落在四个区域之间,最终累加的梯度大小为:
其中k,m, n为0或为1。如上统计4*4*8 = 128个梯度信息即为该关键点的特征向量,按照特征点的对每个关键点的特征向量进行排序,就得到了SIFT特征描述向量。
#实例化sift
sift=cv.SIFT_create() (最新版本opencv)
sift=cv.xfeatures2d.SIFT_create() (低版本)
#检测关键点并计算
kp,des=sift.detectAndCompute(gray,None)
kp:关键点信息,每个点(x,y,σ,θ):位置x,y、尺度σ、方向θ
des:描述符信息,128个梯度信息即为该关键点的特征向量
sift:上一步实例化的sift
gray:灰度图像
#将关键点绘制在图像上
cv.drawKeypoints(image,keypoints,outputimage,color,flags)
image:原始图像
keypoints:关键点信息
outputimage:输出图像
color:绘制颜色
flags:
举例:
#9.1
import cv2 as cv import numpy as np import matplotlib.pyplot as plt #解决中文显示问题,固定格式,直接复制下面俩行代码就行 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False #1.读取灰度图像 pic1 =cv.imread("10.jpg") gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY) #2.SIFT实例化 sift=cv.SIFT_create() #3.检测关键点 kq,dst=sift.detectAndCompute(gray,None) #4.绘制关键点 pic2=pic1.copy() cv.drawKeypoints(pic2,kq,pic2,(0,0,255),cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)#flags=4可以替换cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS #绘制图像 fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10)) axes[0,0].set_title("原图") axes[0,0].imshow(pic1[:,:,::-1]) axes[0,1].set_title("灰度图") axes[0,1].imshow(gray,plt.cm.gray) axes[1,1].set_title("SIFT特征点检测") axes[1,1].imshow(pic2[:,:,::-1]) plt.show() cv.waitKey(0)
结果
代码API和上述SIFT算法一样,就是更换名称就行
3.4版本之后因专利版权问题移除了SIFT/SURF的相关库,因此在使用较新版本的cv库时会报错,好消息是2020年3月17日之后一代传奇算法SIFT专利到期了,但是SURF还是受版权保护。相关消息更改见以下博客,选择适合的第三方库OpenCV低版本就可以使用:
【OpenCV】2020年关于SIFT算法专利版权问题的解决办法_四季豆炒饭的博客-CSDN博客_opencv专利OpenCV 3.4之后因专利版权问题移除了SIFT/SURF的相关库,因此在使用较新版本的cv库时会报错https://blog.csdn.net/cleanlii/article/details/109561089?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166467877116800186567077%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=166467877116800186567077&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-3-109561089-null-null.142%5Ev51%5Econtrol_1,201%5Ev3%5Econtrol_1&utm_term=opencv%E5%BA%93%E5%A4%9A%E5%B0%91%E7%89%88%E6%9C%ACSURF%E5%8F%97%E7%89%88%E6%9D%83%E4%BF%9D%E6%8A%A4&spm=1018.2226.3001.4187
SURF(加速版的具有鲁棒性的特征,SpeededUp Robust Features),SURF是尺度不变特征变换算法(SIFT算法)的加速版。SURF最大的特征在于采用了harr特征以及积分图像的概念。,计算更小小,运算速度更快。区别如下
OpenCV系列之SURF简介(加速的强大功能)| 四十_woshicver的博客-CSDN博客目标在这一章当中,我们将了解SURF的基础我们将在OpenCV中看到SURF函数理论在上一章中,我们看到了SIFT用于关键点检测和描述符。但相对缓慢,人...https://blog.csdn.net/woshicver/article/details/105140920?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166467664416800180610199%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166467664416800180610199&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-105140920-null-null.142%5Ev51%5Econtrol_1,201%5Ev3%5Econtrol_1&utm_term=opencv%20SURF&spm=1018.2226.3001.4187
#实例化sift
sift=cv.SIFT_create()
#检测关键点并计算
kp,des=sift.detectAndCompute(gray,None)
#将关键点绘制在图像上
cv.drawKeypoints(image,keypoints,outputimage,color,flags)