【特征匹配】SIFT原理与C源代码剖析
提取关键点和对关键点附加详细的信息(局部特征)也就是所谓的描述器可以称做是sift特征的生成,即从多幅图像中提取对尺度缩放、旋转、亮度变化无关的特征向量。•sift特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性。•sift算法是一种提取局部特征的算法,在尺度空间寻找极值点,提取位置,尺度,旋转不变量。
下图中,涉及到图像的旋转,仿射,光照等变化,SIFT算法依旧有非常好的匹配效果。
本文将下面函数为參照顺序介绍SIFT特征点提取与描写叙述方法。
1.图像预处理
2.构建高斯金字塔(不同尺度下的图像)
3.生成DOG尺度空间
4.关键点搜索与定位
5.计算特征点所在的尺度
6.为特征点分配方向角
7.构建特征描写叙述子
/** Finds SIFT features in an image using user-specified parameter values. All detected features are stored in the array pointed to by \a feat. */ int _sift_features( IplImage* img, struct feature** feat, int intvls, double sigma, double contr_thr, int curv_thr, int img_dbl, int descr_width, int descr_hist_bins ) { IplImage* init_img; IplImage*** gauss_pyr, *** dog_pyr; CvMemStorage* storage; CvSeq* features; int octvs, i, n = 0; /* check arguments */ if( ! img ) fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ ); if( ! feat ) fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ ); /* build scale space pyramid; smallest dimension of top level is ~4 pixels */ init_img = create_init_img( img, img_dbl, sigma ); //对进行图片预处理 octvs = log( MIN( init_img->width, init_img->height ) ) / log(2) - 2; //计算高斯金字塔的组数(octave),同一时候保证顶层至少有4个像素点 gauss_pyr = build_gauss_pyr( init_img, octvs, intvls, sigma ); //建立高斯金字塔 dog_pyr = build_dog_pyr( gauss_pyr, octvs, intvls ); //DOG尺度空间 storage = cvCreateMemStorage( 0 ); features = scale_space_extrema( dog_pyr, octvs, intvls, contr_thr, //极值点检測,并去除不稳定特征点 curv_thr, storage ); calc_feature_scales( features, sigma, intvls ); //计算特征点所在的尺度 if( img_dbl ) adjust_for_img_dbl( features ); //假设图像初始被扩大了2倍。全部坐标与尺度要除以2 calc_feature_oris( features, gauss_pyr ); //计算特征点所在尺度内的方向角 compute_descriptors( features, gauss_pyr, descr_width, descr_hist_bins );//计算特征描写叙述子 128维向量 /* sort features by decreasing scale and move from CvSeq to array */ cvSeqSort( features, (CvCmpFunc)feature_cmp, NULL ); //对特征点按尺度排序 n = features->total; *feat = calloc( n, sizeof(struct feature) ); *feat = cvCvtSeqToArray( features, *feat, CV_WHOLE_SEQ ); for( i = 0; i < n; i++ ) { free( (*feat)[i].feature_data ); (*feat)[i].feature_data = NULL; } cvReleaseMemStorage( &storage ); cvReleaseImage( &init_img ); release_pyr( &gauss_pyr, octvs, intvls + 3 ); release_pyr( &dog_pyr, octvs, intvls + 2 ); return n; }
—————————————————————————————————————————————————————
/************************ Functions prototyped here **************************/ /* Converts an image to 8-bit grayscale and Gaussian-smooths it. The image is optionally doubled in size prior to smoothing. @param img input image @param img_dbl if true, image is doubled in size prior to smoothing @param sigma total std of Gaussian smoothing */ static IplImage* create_init_img( IplImage* img, int img_dbl, double sigma ) { IplImage* gray, * dbl; double sig_diff; gray = convert_to_gray32( img ); //转换为32位灰度图 if( img_dbl ) // 图像被放大二倍 { sig_diff = sqrt( sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA * 4 ); // sigma = 1.6 , SIFT_INIT_SIGMA = 0.5 lowe觉得图像在尺度0.5下最清晰 dbl = cvCreateImage( cvSize( img->width*2, img->height*2 ), IPL_DEPTH_32F, 1 ); cvResize( gray, dbl, CV_INTER_CUBIC ); //双三次插值方法 放大图像 cvSmooth( dbl, dbl, CV_GAUSSIAN, 0, 0, sig_diff, sig_diff ); //高斯平滑 cvReleaseImage( &gray ); return dbl; } else { sig_diff = sqrt( sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA ); cvSmooth( gray, gray, CV_GAUSSIAN, 0, 0, sig_diff, sig_diff ); // 高斯平滑 return gray; } }
lowe建议把初始图像放大二倍。能够得到很多其它的特征点,提取到很多其它细节,而且觉得图像在尺度σ = 0.5时图像最清晰,初始高斯尺度为σ = 1.6。
☆第19行由于图像被放大二倍,此时σ = 1.0 。
由于对二倍化后的图像平滑是在σ = 0.5 上叠加的高斯模糊。
所以有模糊系数有sig_diff = sqrt (sigma *sigma - 0.5*0.5*4)=sqrt(1.6*1.6 -1) ;
构建高斯金字塔过程即构建出图像在不同尺度上图像,提取到的特征点可有具有尺度不变性。
我来说几个来自函数库的函数,例如createwindowex()函数可以用来创建一个窗体(这个函数由微软提供)直方图匹配原理,例如gaussianblur()函数可以用来对一个图像进行高斯模糊处理(这个函数由opencv提供)直方图匹配原理,再比如evhttp_new()函数可以创建一个http服务程序(这个函数由libevent提供)……。在surf算法中,用图像像素l(x,y)代替函数值f(x,y),选用二阶标准高斯函数作为滤波器,通过特定核间的卷积计算二阶偏导数,这样便能计算出h矩阵的三个矩阵元素l。在计算视觉领域,尺度空间被象征性的表述为一个图像金字塔,其中,输入图像函数反复与高斯函数的核卷积并反复对其进行二次抽样,这种方法主要用于sift算法的实现,但每层图像依赖于前一层图像,并且图像需要重设尺寸,因此,这种计算方法运算量较大,而surf算法申请增加图像核的尺寸,这也是sift算法与surf算法在使用金字塔原理方面的不同。
按照二维高斯分布(以block中心为二维高斯的中心)来决定。2.6本章小结本章介绍了计算偏晶合金第二相液滴的形核模型、模拟偏品合金两相流动的lbm控制方程、ll/l2两液相之间的相互作用势、浓度场的数值计算和相变密度增量的计算方法,建立了一个模拟在第二相液滴的形核、扩散长大、碰撞合并和ostwald熟化等因素的作用下偏晶合金液.液相分离过程的二二维lbm模型。(x,£)是一幅图像在不同解析度下的表示,可以利用高斯核g(£)与图像函数,(x)在点x一(z,y)的卷积来实现,核函数g(£)具体表示如式(5),g(£)为高斯函数,t为高斯方差,l。
☆不同的尺度空间即用不同的高斯核函数平滑图像, 平滑系数越大。图像越模糊。即模拟出动物的视觉效果,由于事先不知道物体的大小,在不同的尺度下,图像的细节会表现的不同。当尺度由小变大的过程中,是一个细节逐步简化的过程,图像中特征不够明显的物体,就模糊的多了。而有些物体还能够看得到大致的轮廓。所以要在不同尺度下。观察物体的尺度响应,提取到的特征才干具有尺度不变性。
SIFT算法採用高斯金字塔实现连续的尺度空间的图像。金字塔共分为O(octave)组。每组有S(intervals)层 ,下一组是由上一组隔点採样得到(即降2倍分辨率),这是为了减轻卷积运算的工作量。
能生虫子的食物很少了