三、sift算法的应用
1、sift的main函数
- #include "sift.h"
- #include "imgfeatures.h"
- #include "kdtree.h"
- #include "utils.h"
- #include "xform.h"
- #include <cv.h>
- #include <cxcore.h>
- #include <highgui.h>
- #include <stdio.h>
- /* the maximum number of keypoint NN candidates to check during BBF search */
- #define KDTREE_BBF_MAX_NN_CHKS 200
- /* threshold on squared ratio of distances between NN and 2nd NN */
- #define NN_SQ_DIST_RATIO_THR 0.49
- /******************************** Globals ************************************/
- char img1_file[] = "beaver.png";
- char img2_file[] = "beaver_xform.png";
- /********************************** Main *************************************/
- int main( int argc, char** argv )
- {
- IplImage* img1, * img2, * stacked;
- struct feature* feat1, * feat2, * feat;
- struct feature** nbrs;
- struct kd_node* kd_root;
- CvPoint pt1, pt2;
- double d0, d1;
- int n1, n2, k, i, m = 0;
- img1 = cvLoadImage( img1_file, 1 );
- if( ! img1 )
- fatal_error( "unable to load image from %s", img1_file );
- img2 = cvLoadImage( img2_file, 1 );
- if( ! img2 )
- fatal_error( "unable to load image from %s", img2_file );
- stacked = stack_imgs( img1, img2 );
- fprintf( stderr, "Finding features in %s...\n", img1_file );
- n1 = sift_features( img1, &feat1 );
- fprintf( stderr, "Finding features in %s...\n", img2_file );
- n2 = sift_features( img2, &feat2 );
- kd_root = kdtree_build( feat2, n2 );
- for( i = 0; i < n1; i++ )
- {
- feat = feat1 + i;
- k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );
- if( k == 2 )
- {
- d0 = descr_dist_sq( feat, nbrs[0] );
- d1 = descr_dist_sq( feat, nbrs[1] );
- if( d0 < d1 * NN_SQ_DIST_RATIO_THR )
- {
- pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
- pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );
- pt2.y += img1->height;
- cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );
- m++;
- feat1[i].fwd_match = nbrs[0];
- }
- }
- free( nbrs );
- }
- fprintf( stderr, "Found %d total matches\n", m );
- cvNamedWindow( "Matches", 1 );
- cvShowImage( "Matches", stacked );
- cvSaveImage("1.bmp",stacked,0);
- cvWaitKey( 0 );
- cvReleaseImage( &stacked );
- cvReleaseImage( &img1 );
- cvReleaseImage( &img2 );
- kdtree_release( kd_root );
- free( feat1 );
- free( feat2 );
- return 0;
- }
Sift(Scale InvariantFeature Transform)是一个很好的图像匹配算法,同时能处理亮度、平移、旋转、尺度的变化,利用特征点来提取特征描述符,最后在特征描述符之间寻找匹配。
sift库分析:
总共包含6 个文件再加上一个main.c文件。
untils.c
minpq.c
imgfeature.c
sift.c
xform.c
kdtree.c
以及其对应的.h文件
最核心的文件是sift.c 和 kdtree.c
1 sift.c 寻找图片中的特征点
主要步骤:
a、构建尺度空间,检测极值点,获得尺度不变性;
b、特征点过滤并进行精确定位,剔除不稳定的特征点;
c、在特征点处提取特征描述符,为特征点分配方向值;
d、生成特征描述子,利用特征描述符寻找匹配点;
以特征点为中心取16*16的邻域作为采样窗口,
将采样点与特征点的相对方向通过高斯加权后归入包含8个bin的方向直方图,
最后获得4*4*8的128维特征描述子。
2 kdtree.c 对两幅图像进行匹配
主要步骤:
当两幅图像的Sift特征向量生成以后,下一步就可以采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。
取图1的某个关键点,通过遍历找到图像2中的距离最近的两个关键点。在这两个关键点中,如果次近距离除以最近距离小于某个阙值,则判定为一对匹配点。
3 imgfeature.c在以上图片中画上标记。连接对应的匹配的点。