1. 什么是特征
图像中的小区域,向周围小范围移动时变化最大,即特征。寻找到这些特征的过程叫做特征检测(Feature Detection)。
比如一个白色背景的矩形图像,位于四个角落的小区域是特征点,位于边线上的次要特征,位于纯色区域的没有特征
2. Harris 角落检测
寻找在全方向的(u,v)位移的亮度变化,形成函数,使用泰勒展开,推为矩阵M。创建一个分数R,取决于矩阵M的两个特征值之间的相对大小关系,判断为平区域、边界、角点
R = det(M) - k(trace(M))2
其中
- det(M) = λ1λ2
- trace(M) = λ1 + λ2
- λ1和λ2是M的特征值
代码使用cv.cornerHarris()
- img -输入图像,灰度float32
- blockSize -角点检测考虑的邻域大小
- kSize -Sobel 微分使用的Aperture参数
- k -Harris检测公式中的自由参数
1 | import numpy as np |
如果要获得亚像素精度的焦点,使用cv.cornerSubPix()
1 | # find centroids |
3. Shi-Tomasi 角点检测 Good Features to Track
将分数定义为了
R = min(λ1, λ2)
若R大于某个阈值,则认为是角点。
使用cv.goodFeaturesToTrack()
- 输入图像
- 需要寻找的角点数目
- 0-1之间的质量等级
- 角点之间的最小欧式距离
1
2
3
4
5
6corners = cv.goodFeaturesToTrack(gray,250,0.01,20)
corners = np.int0(corners)
for i in corners:
x,y = i.ravel()
cv.circle(img,(x,y),3,255,-1)
4. SIFT 尺度不变特征转换
小窗口中的角点图被放大后,用同样大的窗口观察看起来变得平滑了。SIFT中,分别进行尺度空间极值检测、关键点定位、方向赋值、关键点描述、关键点匹配。这个算法在2020年专利已经到期,可放心使用。
1 | import numpy as np |
sift.detect()
可以输入mask指定寻找区域cv.drawKeyPoints()
用于绘制关键点的圆圈,如果传入flag=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
,会绘制关键点直径的圆圈并显示其方向。
1 | img=cv.drawKeypoints(gray,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) |
计算特征描述(Descriptor)
- 已知关键点kp,用sift.compute(),``kp, des = sift.compute(gray, kp)
- 一步到位,用sift.detectdAndCompute()kp是关键点列表,des是numpy数组形状是(关键点数)*128
1
2sift = cv.SIFT_create()
kp, des = sift.detectAndCompute(gray,None)
通常获得了关键点和描述,我们就可以在之后的操作中匹配不同图片中的关键点了。
5. SURF 快速鲁棒特征
SURF在每个步骤增加了很多特征,达到同样效果比SIFT快3倍,适用于带有模糊和旋转的图片,但不适用视角转变和光线变化的情况。
如何在OpenCV中还处于专利保护阶段,要想使用,需要卸载当前高版本,重新安装opencv-contrib-python==3.4.2.17
1 | # 寻找SURF关键点和描述符并绘制 |
代码来自这
6. FAST 快速角点检测方法
比前几种方法快几倍,但对高噪音不鲁棒。有一个阈值参数。
1 | import numpy as np |
7. BRIEF 二元鲁棒独立基本特征
一种更快的特征描述与匹配方法,需要使用其他的方法检测到关键点,适用于CenSurE(STAR)方法
1 | import numpy as np |
8. ORB(Oriented FAST and Rotated BRIEF)
没有专利,安全使用,更快更好。
1 | import numpy as np |
具体使用直接看官方教程