Dog算子,SIFT特征点, Fast角点 ,ORB特征点 有时间慢慢再来解析
SURF主要有以下几点优势
SURF是尺度不变特征变换算法(SIFT)的加速版
,一般来说它比SIFT要快好几倍,且在多幅图像下具有更好的稳定性;
SURF采用了harr特征+积分图像
的概念,大大加快了程序的运行时间。
SURF可以应用于计算机视觉的物体识别以及3D重构
1. 构建Hessian矩阵, 构造高斯金字塔尺度空间
SURF构造的金字塔图像与SIFT有很大不同,是造成SURF快很多的原因之一。
Sift采用的是Dog算子
, 而surf采用的是Hessian矩阵行列式
近似值图像, Hessian矩阵是Surf算法的核心。
但由于特征点需要具备尺度无关性,所以在在计算Hessian矩阵之前,需要对其进行高斯滤波。
首先判断该点是否为极值点,才可以决定是否选择其为特征点
判别式的就是Hessian矩阵的行列式, 缩写为det(H)
, 判别式的值就是H矩阵的的特征值,然后根据判别式的值从而可以判定该点是是不是极值点。
在SURF算法中,为了计算Hessian矩阵,我们选用二阶标准高斯函数作为滤波器, 通过特定核间的卷积计算二阶偏导数,从而可以得到H矩阵:
而 L ( x , t ) = G ( t ) ⋅ I ( x , t ) L(x, t)=G(t) \cdot I(x, t) L(x,t)=G(t)⋅I(x,t), G ( t ) = ∂ 2 g ( t ) ∂ x 2 G(t)=\frac{\partial^{2} g(t)}{\partial x^{2}} G(t)=∂x2∂2g(t).
为应用方便, 有人(Herbert Bay)提出了用近似值先代替L(x,t), 为了平衡误差引入权值
,权值随着尺度变换, 则H矩阵的判别式可表示为:
det ( H ) = D x x D y y − ( 0.9 D x y ) 2 \operatorname{det}(\text {H})=D x x D y y-\left(0.9 D_{x y}\right)^{2} det(H)=DxxDyy−(0.9Dxy)2
SURF相比对SIFT加速的两个地方
积分图(提高计算效率)
:就是当前的每个像素的灰度都是它与坐标原点(0,0)形成的对角线的矩形内的所有像素的灰度值之和。所以我们在计算某个矩阵框内的像素灰度值之和时,就可以很快得出结果。2. 利用非极大值抑制初步确定特征点
初步特征点的确定: 将经过hessian矩阵处理过的每个像素点与其3维领域的26个点(每个平面9个点再除去自身)进行大小比较,如果它是这26个点中的最大值或者最小值,则保留下来,当做初步特征点
。
3. 精确定位极值点
和sift算法类似,采用三维线性插值法得到亚像素级的特征点,同时也去掉那些值小于一定阈值的点,增加极值使检测到的特征点数量减少,最终只有几个特征最强点
会被检测出来。
4. 选取特征点的主方向
sift选取特征点主方向
采用在特征点领域内统计其梯度直方图, 取直方图bin值最大的以及超过最大bin值80%的那些方向作为其特征点的主方向。
梯度直方图不熟,记个标签,后面专门补上。
SURF选取特征点主方向
不统计其梯度直方图, 而是统计特征点领域内的harr小波特征
。即以特征点为中心,统计在一定半径范围内,以60°的扇形区域内x-y方向上的Haar小波响应
总和,并给这些响应值按照离特征点的远近赋予不同程度的权重, 最后将最大值那个扇形的作为该特征点的主方向。该过程的示意图如下:
haar小波特征不熟,记个标签2,后面补上更新
5. 构造SURF特征点描述算子
sift描述子的选取方式
在sift中,是在特征点周围取16x16的邻域, 并把该领域化为4x4个的小区域,每个小区域统计8个方向梯度,最后得到448 = 128维的向量, 将该向量作为该点的描述子
SURF描述子的选取方式
在surf中,是在特征点周围去一个正方形框,该框是有方向的,与上的一步的主方向统一。 然后将该框分为44个小区域,对每个小区域统计25个像素的水平方向和垂直方向的haar小波特征,这里的水平和垂直方向是相对主方向而言的。就可以得到4个值:该haar小波特征的水平方向值之和,水平方向绝对值之和,垂直方向之和,垂直方向绝对值之和。所以从以上可以看出,最后得到44*4=64维的向量, 该向量与sift的向量相比少了一半。
在上面讲述SURF的原理过程中,都与sift特征进行了对比, 突出了surf特征的优势所在,那么现在分析一下surf有那些缺点:
求主方向阶段太过于依赖局部区域像素的梯度方向
这有可能使得找到的主方向不准确,而后面的特征向量提取以及匹配都严重依赖于主方向,即便不大偏差角度也可以造成后面特征匹配的误差放大,从而使匹配不成功。
图像金字塔的层取得不够紧密
这会使得尺度有误差, 后面的特征向量提取同样依赖相应的尺度,研究者们在这个问题上的解决方法是取适量的层然后进行插值
int minHessian = 400; ## 检测关键点的数量
cv::Ptr<xfeatures2d::SURF> detector = xfeatures2d::SURF::create( minHessian );
cv::Ptr<xfeatures2d::SIFT> detectorSift = xfeatures2d::SIFT::create(minHessian);
## 画出关键点位置
drawKeypoints(image1, kyPoints1, img_kyPoints1, cv::Scalar::all(-1), DrawMatchesFlags::DEFAULT);
vector<DMatch> matches;
FlannBasedMatcher matcher;
matcher.match(descrip1, descrip2, matches);
# 画出匹配的关键点
drawMatches ( image1, kyPoints1, image2, kyPoints2, matches, img_matches );
且理论上, SURF比SIFT快3倍。