本文主要是介绍特征点检测之SURF,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
一、surf原理
二、特征检测步骤
1.盒子滤波器
1.1 积分图像
1.1 box filter
2.Hessian的构建
3.尺度空间的构建
3.1 hessian行列式
3.2 空间金字塔
3.3 特征点过滤
4.确定主方向
5.生成特征描述
三、sift和surf对比
总结
一、surf原理
surf(speed up robust features)是对sift的改进,特征点的检测和匹配包括:
A. 构建Hessian矩阵。
B. 构建尺度空间,特征点的过滤和定位。
C. 主方向确定。
D. 生成特征描述。
与sift相比较如下改进:
A. sift在构造dog金字塔以及求dog局部空间极值比较耗时, surf使用Hessian检测极值,使用盒状filter求高斯模糊近似值。sift使用dog对log进行了简化, 提高了搜索速度surt是dog的近似和简化。
B. surf不使用降采样改变盒状滤波器的大小来构建尺度金字塔。
C. surf使用haar小波转换,sift使用的是直方图统计找关键点的方向。
二、特征检测步骤
1.盒子滤波器
1.1 积分图像
图像的积分其实就是求和,图像积分图中每个点的值是原图像中该点左上角的所有像素值之和。首先建立一个数组 A 作为积分图像,其宽高与原图像相等。然后对这个数组赋值,每个点存储的是该点与图像原点所构成的矩形中所有像素的和。
积分图像可以采用增量的方式计算:
可以看到sat(x-1, y)+sat(x, y-1)后,有一部分重合的区域,即sat(x-1, y-1),所以需减掉,最后还需要将当前坐标(x,y)的像素值包含进来。
计算某个矩形像素的和, 比如Rd所有的像素和:
Sum(Rd) = sat1+ sat4 - sat2 -sat4
所以无论矩形的尺寸大小,只需查找积分图像 4 次就可以快速计算任意矩形内像素值的和, 即算法复杂度为 O(4)。
1.2 box filter
Harr-like的特征: 模板内有白色和黑色两种矩形,并定义该模板的特征值为黑色矩形像素和减去白色矩形像和。
对一个灰度图而言,事先将其积分图构建好,当需要计算灰度图某个区域内所有像素点的像素值之和的时候,利用积分图,通过查表运算,可以迅速得到结果使复杂度为O(MN)的求和。求方差等运算降低到O(1)或近似于O(1)的复杂度,它的缺点是不支持多尺度。
初始化步骤如下:
A. 给定一张图像,宽高为(M,N),确定待求矩形模板的宽高(m,n),如图紫色矩形。图中每个黑色方块代表一个像素,红色方块是假想像素。
B. 开辟一段大小为 M 的数组,记为 buff, 用来存储计算过程的中间变量,用红色方块表示。
C. 将矩形模板(紫色)从左上角(0,0)开始,逐像素向右滑动,到达行末时,矩形移动到下一行的开头(0,1),如此反复,每移动到一个新位置时,计算矩形内的像素和,保存在数组 A 中。
每次紫色矩形向右移动时,实际上就是求对应的蓝色矩形的像素和,此时只要把上一次的求和结果减去蓝色矩形内的第一个红色块,再加上它右面的一个红色块,就是当前位置的和了,用公式表示 sum[i] = sum[i-1] - buff[j] + buff[j+m]。
void Boxfilter::init(int width, int height, int mwidth, int mheight)
{this->mwidth = mwidth;this->mheight = mheight;this->width = width;this->height = height;boxwidth = width - mwidth;boxheight = height - mheight;f_sum = new int[boxwidth *boxheight];buff = new int[width];
}void Boxfilter::boxfilter (unsigned char* img)
{int j,x,y;//初始化设置0memset(buff, 0, width *sizeof(int));memset(f_sum, 0, boxwidth *boxheight);//x方向单个像素求和for(y=0; y<mheight; y++){for(x=0; x<width; x++){uchar pixel = img[y *width + x];buff[x] += pixel;}}//x和y方向求和for(y=0; y<height - mheight;y++){int Xsum=0;//x方向subSum求和for(j=0; j<mwidth; j++){Xsum += buff[j];}for(x=0; x<width - mwidth; x++){if(x!=0){ //sum[i] = sum[i-1] - buff[j] + buff[j+m].Xsum = Xsum-buff[x-1]+buff[mwidth-1+x];}f_sum[y*(width - mwidth)+x] = (float) Xsum ; }for(x=0; x<width; x++){uchar pixel = img[y *width + x]; uchar pixel2 = img[(y+mheight) *width + x]; buff[x] = buff[x] - pixel + pixel2; }}
}int Boxfilter::getSum(int x, int y)
{if(y>mheight/2 && y<height - mheight/2 && x>mwidth/2 && x<width - mwidth/2)return f_sum[(y - mheight/2) *boxwidth + (x - mwidth/2)];elsereturn -1;
}
2.Hessian的构建
Hessian矩阵的目的是为了生成图像极值点,当hessian行列式的局部值最大的时候,检测出的就是感兴趣点。surf构造的金字塔图像与sift有很大不同,Sift采用的是DOG图像,而surf采用的是Hessian矩阵行列式近似值图像。黑森矩阵(Hessian Matrix)是由一个多元函数的二阶偏导数构成的方阵,描述了函数的局部曲率。
滤波的Hessian的表达式,Hessian矩阵的判别式,其实就是当前点对水平方向二阶偏导数乘以垂直方向二阶偏导数再减去当前水平、垂直二阶偏导的二次方。
离散图像, 二阶导数是对一阶导数的再次求导:
boxfilter对图像的滤波转化成计算图像上不同区域间像素和的加减运算问题,只需要简单几次查找积分图就可以完成。高斯函数的高阶微分与离散的图像函数I(x,y)做卷积运算时相当于使用高斯滤波模板对图像做滤波处理。实际运用中,高斯二阶微分进行离散化和裁剪处理得到盒子滤波器近似代替高斯滤波板进行卷积计算。我们需要对高斯二阶微分模板进行简化,使得简化后的模板只是由几个矩形区域组成,矩形区域内填充同一值,把图像中的模板区域与图像的卷积运算转化为盒子滤波器的运算,如下图所示:
Hession矩阵判别式中的L(x,y)是原始图像的高斯卷积为了提高运算速度,SURF算法使用了盒式滤波器来替代高斯滤波器L,所以在Lxy上乘了一个加权系数0.9,目的是为了平衡因使用盒式滤波器近似所带来的误差,则H矩阵判别式可表示为:
对于不同的σ的值和对应尺寸的模板尺寸,w值是不同的,但为了简化起见,可以认为它是同一个常数。 使用近似的Hessian矩阵行列式来表示图像中某一点x处的斑点响应值,遍历图像中所有的像元点,便形成了在某一尺度下任意点检测的响应图像。
3.尺度空间的构建
3.1 hessian行列式
在surf算法的尺度空间中,每一组中任意一层包括D{xx},D{yy},D{xy}三种盒子滤波器。对一幅输入图像进行滤波后通过Hessian行列式计算公式可以得到对应尺度坐标下的Hessian行列式的值,所有Hessian行列式值构成一幅Hessian行列式图像。
3.2 空间金字塔
通常想要获取不同尺度的极值点,必须建立图像的尺度空间金字塔。一般的方法是通过不同σ的高斯函数,对图像进行平滑滤波,然后重采样图像以获得更高一层的金字塔图像。sift特征检测算法中就是通过相邻两层图像金字塔相减得到dog图像,然同sift算法一样,surf算法的尺度空间由O组S层组成,sift算法下一组图像的长宽均是上一组的一半,同一组不同层图像之间尺寸一样,但是所使用的尺度空间因子(高斯模糊系数σ)逐渐增大;而在surf算法中,不同组间图像的尺寸都是一致的,不同的是不同组间使用的盒式滤波器的模板尺寸逐渐增大,同一组不同层图像使用相同尺寸的滤波器,但是滤波器的尺度空间因子逐渐增大。
3.3 特征点过滤
定位过程和SIFT算法一致,将经过Hessian矩阵处理的每个像素点(即获得每个像素点Hessian矩阵的判别式值)与其周围的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。如图所示,中间的检测点要和其所在图像的3×33×3邻域8个像素点,以及其相邻的上下两层3×33×3邻域18个像素点,共26个像素点进行比较。
4.确定主方向
为了保证特征矢量具有旋转不变性,与sift特征一样,需要对每个特征点分配一个主方向。为些,我们需要以特征点为中心,以6σ为半径的圆形区域,对图像进行Haar小波响应运算。这样做实际就是对图像进行梯度运算只不过是我们需要利用积分图像,提高计算图像梯度的效率。
SIFT算法特征点的主方向是采用在特征点邻域内统计其梯度直方图,横轴是梯度方向的角度,纵轴是梯度方向对应梯度幅值的累加,取直方图bin最大的以及超过最大80%的那些方向作为特征点的主方向, 考虑到Haar小波的模板带宽,实际计算梯度的图像区域是相同的。用于计算梯度的Harr小波的尺度为4s。
Harr特征值反应了图像灰度变化的情况,那么这个主方向就是描述那些灰度变化特别剧烈的区域方向。以特征点为中心,张角为π/3的扇形滑动,计算窗口内的Harr小波响应值dx、dy的累加:
for(int i = -6; i <= 6; ++i) { for(int j = -6; j <= 6; ++j) {if(i*i + j*j < 36) {gauss = static_cast<float>(gauss25[id[i+6]][id[j+6]]);resX[idx] = gauss * haarX(r+j*s, c+i*s, 4*s);resY[idx] = gauss * haarY(r+j*s, c+i*s, 4*s);Ang[idx] = getAngle(resX[idx], resY[idx]);++idx;}}
}
5.生成特征描述
生成特征点描述子与确定特征点方向有些类似,它需要计算图像的Haar小波响应, 沿主方向将20s×20s的图像划分为4s×4s个子块,每个子块利用尺寸2s的Harr模板进行响应值进行响应值计算然后对响应值进行统计∑dx ∑|dx| ∑dy ∑|dy|形成特征矢量于共有4×4个子块,因此,特征描述子共由4×4×4=64维特征矢量组成。
为了充分利用积分图像进行Haar小波的响应计算,并不直接旋转Haar小波模板求得其响应值,而是在积图像上先使用水平和垂直的Haar模板求得响应值dy和dx,然后根据主方向旋转dx和dy与主方向操持一致
利用积分图像与水平、垂直Harr小波,求得水平与垂直两个方向的响应值dx和dy。对dx和dy进行高斯加权处理,并根据主方向的角度,对dx和dy进行旋转变换
三、sift和surf对比
(1)在生成尺度空间方面,SIFT算法利用的是差分高斯金字塔与不同层级的空间图像相互卷积生成。SURF算法采用的是不同尺度的box filters与原图像卷积
(2)在特征点检验时,SIFT算子是先对图像进行非极大值抑制,再去除对比度较低的点。然后通过Hessian矩阵去除边缘的点。而SURF算法是先通过Hessian矩阵来检测候选特征点,然后再对非极大值的点进行抑制
(3)在特征向量的方向确定上,SIFT算法是在正方形区域内统计梯度的幅值的直方图,找到最大梯度幅值所对应的方向。SIFT算子确定的特征点可以有一个或一个以上方向,其中包括一个主方向与多个辅方向。SURF算法则是在圆形邻域内,检测各个扇形范围内水平、垂直方向上的Haar小波响应,找到模值最大的扇形指向,且该算法的方向只有一个。
(4)SIFT算法生成描述子时,是将16*16的采样点划分为4*4的区域,从而计算每个分区种子点的幅值并确定其方向,共计4*4*8=128维。
总结
哈哈
这篇关于特征点检测之SURF的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!