Robhess OpenSIFT 源码下载:传送门

为了进一步学习SIFT,选择论文就着代码看,在VS2013、OpenCV2.4.13下新建项目,跑一跑经典之作。由于将代码和Opencv配置好后还会有些错误提示,所以下面是代码的一些改动之处。(试了下其实还是ubuntu下更方便,因为有许多参数或者命令是linux下的,当然windows下可以进行一些修改后利用)。

大前提:opencv配置好。剩下的都可以通过修改来搞定。

首先看看解压后的文件,我们只需要头文件和源文件:

头文件:6个                                                                                                                          源文件:10个

注意直接运行肯定不行,因为有几个文件比较特殊,下面对所有头、源文件进行解释:

1)imgfeatures.c 和 imgfeatures.h:

有SIFT特征点结构struct feature的定义,除此之外还有一些特征点的导入导出以及特征点绘制函数的声明,对应的imgfeatures.c文件中是特征点的导入导出以及特征点绘制函数的实现。

2)utils.c 和 utils.h:

这两个文件中是一些图像基本操作的函数,包括:获取某位置的像素点,设置某位置的像素点(8位,32位和64位),计算两点之间的距离的平方,在图片某一点画一个“X”,将两张图片合成为一个(在特征匹配中用到),高是二者之和,宽是二者的较大者。

3)minpq.c 和 minpq.h

这两个文件中实现了最小优先级队列(Minimizing Priority Queue),也就是小顶堆,在k-d树的建立和搜索过程中要用到。

4)kdtree.c 和 kdtree.h

这两个文件中实现了k-d树的建立以及用BBF(Best Bin First)算法搜索匹配点的函数。如果需要对两个图片中的特征点进行匹配,就要用到这两个文件。

5)xform.c 和 xform.h:

这两个文件中实现了RANSAC算法(RANdom SAmple Consensus 随机抽样一致)。RANSAC算法可用来筛选两个图像间的SIFT特征匹配并计算变换矩阵。可以单利用RANSAC算法筛选两个图像间的SIFT特征匹配,以得到更好的匹配结果,很经典的算法,值得学习。

6)sift.c 和 sift.h:

论文里最主要的内容在此,里面的内容就是两个特征点检测函数sift_features()和 _sift_features(),sift_features()是用默认参数进行特征点检测, _sift_features()允许用户输入各种检测参数,其实sift_features()中也是再次调用_sift_features()函数。所以只需提供原图像和存储特征点的数组以及其他一些检测参数,然后调用sift_features()或 _sift_features()就可完成SIFT特征点检测。

7)siftfeat.c :含有main函数,用来实现特征点的检测,返回特征点数目和标记特征点的图像。(主要用到)

8)match.c 含有main函数, 检测两张图中的sift特征点,然后找到特征点的匹配对。(主要用到)

9)match_num.c 含有main函数,检测sift特征点,但是用到了linux下的多线程编程,所以这里暂时不做讨论。

10)dspfeat.c : 含有main函数,可以从预先保存的特征点文件中读取特征点并显示在图片上。

一. 修改代码

第一步:将代码中所有头文件源文件中的声明改一下:

修改前:

  1. #include <cv.h>
  2. #include <cxcore.h>
  3. #include <highgui.h>

修改后:

  1. #include <opencv/cv.h>
  2. #include <opencv/cxcore.h>
  3. #include <opencv/highgui.h>

修改原因:因为直接利用找不到opencv路径,所以调整路径。

第二步:修改源文件代码:

1. sift.c:

将函数   static IplImage*** build_gauss_pyr( IplImage* base, int octvs, int intvls, double sigma ) 中的代码进行改动:

修改前:

  1. const int _intvls = intvls;
  2. double sig[_intvls+], sig_total, sig_prev, k;

修改后:

  1. const int _intvls = intvls;
  2. double *sig = (double*)malloc(sizeof(double)*(_intvls+));
  3. double sig_total, sig_prev, k;
    ...
    free(sig); //子函数返回前释放内存

修改原因:

源代码中用变量_intvls+3作为数组的长度,但是VC的编译器不是GCC,它不允许这样做。DEV-C++使用的编译器是GCC,它允许使用变量作为数组的长度定义数组。

当然利用C++中的new或者vector也可以。参考new、delete与malloc、free区别

2. utils.c

首先删除这两行:

  1. #include <gdk/gdk.h>
  2. #include <gtk/gtk.h>

为啥删掉?

gtk是一个功能强大、设计灵活的一个通用图形库,是GNU/Linux下开发图形界面的应用程序的主流开发工具之一,GTK+也有Windows版本和Mac OS X版。在作者的源码中gtk用来调整窗口来显示图像,因为我懒于装gtk,所以直接利用opencv进行显示,所以这里需要修改一些opencv的东西。

将函数进行改动:

修改前:

  1. void display_big_img( IplImage* img, char* title )
  2. {
  3. IplImage* small;
  4. GdkScreen* scr;
  5. int scr_width, scr_height;
  6. double img_aspect, scr_aspect, scale;
  7.  
  8. /* determine screen size to see if image fits on screen */
  9. gdk_init( NULL, NULL );
  10. scr = gdk_screen_get_default();
  11. scr_width = gdk_screen_get_width( scr );
  12. scr_height = gdk_screen_get_height( scr );
  13.  
  14. if( img->width >= 0.90 * scr_width || img->height >= 0.90 * scr_height )
  15. {
  16. img_aspect = (double)(img->width) / img->height;
  17. scr_aspect = (double)(scr_width) / scr_height;
  18.  
  19. if( img_aspect > scr_aspect )
  20. scale = 0.90 * scr_width / img->width;
  21. else
  22. scale = 0.90 * scr_height / img->height;
  23.  
  24. small = cvCreateImage( cvSize( img->width * scale, img->height * scale ),
  25. img->depth, img->nChannels );
  26. cvResize( img, small, CV_INTER_AREA );
  27. }
  28. else
  29. small = cvCloneImage( img );
  30.  
  31. cvNamedWindow( title, );
  32. cvShowImage( title, small );
  33. cvReleaseImage( &small );
  34. }

修改后:

  1. void display_big_img(IplImage* img, char* title)
  2. {
  3. cvNamedWindow(title, ); //参数0表示生成的窗口大小可调整,参数1表示窗口自适应图像而用户不可调整,所以我选择参数0
  4. cvShowImage(title, img);
  5. cvReleaseImage(&img);
  6. }

3. siftfeat.c

注释掉下面一行:

  1. #include <unistd.h>

原因:顾名思义,unistd.h是unix std的意思,是POSIX标准定义的unix类系统定义符号常量的头文件,所以在windows下先注释掉。

然后注释掉下面这两个函数:static void arg_parse( int argc, char** argv ) 和 static void usage( char* name )

  1. static void arg_parse( int argc, char** argv )
  2. {
  3. //extract program name from command line (remove path, if present)
  4. pname = basename( argv[] );
  5.  
  6. //parse commandline options
  7. while( )
  8. {
  9. char* arg_check;
  10. int arg = getopt( argc, argv, OPTIONS );
  11. if( arg == - )
  12. break;
  13.  
  14. switch( arg )
  15. {
  16. // catch unsupplied required arguments and exit
  17. case ':':
  18. fatal_error( "-%c option requires an argument\n" \
  19. "Try '%s -h' for help.", optopt, pname );
  20. break;
  21.  
  22. // read out_file_name
  23. case 'o':
  24. if( ! optarg )
  25. fatal_error( "error parsing arguments at -%c\n" \
  26. "Try '%s -h' for help.", arg, pname );
  27. out_file_name = optarg;
  28. break;
  29.  
  30. // read out_img_name
  31. case 'm':
  32. if( ! optarg )
  33. fatal_error( "error parsing arguments at -%c\n" \
  34. "Try '%s -h' for help.", arg, pname );
  35. out_img_name = optarg;
  36. break;
  37.  
  38. // read intervals
  39. case 'i':
  40. // ensure argument provided
  41. if( ! optarg )
  42. fatal_error( "error parsing arguments at -%c\n" \
  43. "Try '%s -h' for help.", arg, pname );
  44.  
  45. // parse argument and ensure it is an integer
  46. intvls = strtol( optarg, &arg_check, );
  47. if( arg_check == optarg || *arg_check != '\0' )
  48. fatal_error( "-%c option requires an integer argument\n" \
  49. "Try '%s -h' for help.", arg, pname );
  50. break;
  51.  
  52. // read sigma
  53. case 's' :
  54. // ensure argument provided
  55. if( ! optarg )
  56. fatal_error( "error parsing arguments at -%c\n" \
  57. "Try '%s -h' for help.", arg, pname );
  58.  
  59. // parse argument and ensure it is a floating point number
  60. sigma = strtod( optarg, &arg_check );
  61. if( arg_check == optarg || *arg_check != '\0' )
  62. fatal_error( "-%c option requires a floating point argument\n" \
  63. "Try '%s -h' for help.", arg, pname );
  64. break;
  65.  
  66. // read contrast_thresh
  67. case 'c' :
  68. // ensure argument provided
  69. if( ! optarg )
  70. fatal_error( "error parsing arguments at -%c\n" \
  71. "Try '%s -h' for help.", arg, pname );
  72.  
  73. // parse argument and ensure it is a floating point number
  74. contr_thr = strtod( optarg, &arg_check );
  75. if( arg_check == optarg || *arg_check != '\0' )
  76. fatal_error( "-%c option requires a floating point argument\n" \
  77. "Try '%s -h' for help.", arg, pname );
  78. break;
  79.  
  80. // read curvature_thresh
  81. case 'r' :
  82. // ensure argument provided
  83. if( ! optarg )
  84. fatal_error( "error parsing arguments at -%c\n" \
  85. "Try '%s -h' for help.", arg, pname );
  86.  
  87. // parse argument and ensure it is a floating point number
  88. curv_thr = strtol( optarg, &arg_check, );
  89. if( arg_check == optarg || *arg_check != '\0' )
  90. fatal_error( "-%c option requires an integer argument\n" \
  91. "Try '%s -h' for help.", arg, pname );
  92. break;
  93.  
  94. // read descr_width
  95. case 'n' :
  96. // ensure argument provided
  97. if( ! optarg )
  98. fatal_error( "error parsing arguments at -%c\n" \
  99. "Try '%s -h' for help.", arg, pname );
  100.  
  101. // parse argument and ensure it is a floating point number
  102. descr_width = strtol( optarg, &arg_check, );
  103. if( arg_check == optarg || *arg_check != '\0' )
  104. fatal_error( "-%c option requires an integer argument\n" \
  105. "Try '%s -h' for help.", arg, pname );
  106. break;
  107.  
  108. // read descr_histo_bins
  109. case 'b' :
  110. // ensure argument provided
  111. if( ! optarg )
  112. fatal_error( "error parsing arguments at -%c\n" \
  113. "Try '%s -h' for help.", arg, pname );
  114.  
  115. // parse argument and ensure it is a floating point number
  116. descr_hist_bins = strtol( optarg, &arg_check, );
  117. if( arg_check == optarg || *arg_check != '\0' )
  118. fatal_error( "-%c option requires an integer argument\n" \
  119. "Try '%s -h' for help.", arg, pname );
  120. break;
  121.  
  122. // read double_image
  123. case 'd' :
  124. img_dbl = ( img_dbl == )? : ;
  125. break;
  126.  
  127. // read display
  128. case 'x' :
  129. display = ;
  130. break;
  131.  
  132. // user asked for help
  133. case 'h':
  134. usage( pname );
  135. exit();
  136. break;
  137.  
  138. // catch invalid arguments
  139. default:
  140. fatal_error( "-%c: invalid option.\nTry '%s -h' for help.",
  141. optopt, pname );
  142. }
  143. }
  144.  
  145. // make sure an input file is specified
  146. if( argc - optind < )
  147. fatal_error( "no input file specified.\nTry '%s -h' for help.", pname );
  148.  
  149. // make sure there aren't too many arguments
  150. if( argc - optind > )
  151. fatal_error( "too many arguments.\nTry '%s -h' for help.", pname );
  152.  
  153. // copy image file name from command line argument
  154. img_file_name = argv[optind];
  155. }
  1. static void usage( char* name )
  2. {
  3. fprintf(stderr, "%s: detect SIFT keypoints in an image\n\n", name);
  4. fprintf(stderr, "Usage: %s [options] <img_file>\n", name);
  5. fprintf(stderr, "Options:\n");
  6. fprintf(stderr, " -h Display this message and exit\n");
  7. fprintf(stderr, " -o <out_file> Output keypoints to text file\n");
  8. fprintf(stderr, " -m <out_img> Output keypoint image file (format" \
  9. " determined by extension)\n");
  10. fprintf(stderr, " -i <intervals> Set number of sampled intervals per" \
  11. " octave in scale space\n");
  12. fprintf(stderr, " pyramid (default %d)\n",
  13. SIFT_INTVLS);
  14. fprintf(stderr, " -s <sigma> Set sigma for initial gaussian" \
  15. " smoothing at each octave\n");
  16. fprintf(stderr, " (default %06.4f)\n", SIFT_SIGMA);
  17. fprintf(stderr, " -c <thresh> Set threshold on keypoint contrast" \
  18. " |D(x)| based on [0,1]\n");
  19. fprintf(stderr, " pixel values (default %06.4f)\n",
  20. SIFT_CONTR_THR);
  21. fprintf(stderr, " -r <thresh> Set threshold on keypoint ratio of" \
  22. " principle curvatures\n");
  23. fprintf(stderr, " (default %d)\n", SIFT_CURV_THR);
  24. fprintf(stderr, " -n <width> Set width of descriptor histogram" \
  25. " array (default %d)\n", SIFT_DESCR_WIDTH);
  26. fprintf(stderr, " -b <bins> Set number of bins per histogram" \
  27. " in descriptor array\n");
  28. fprintf(stderr, " (default %d)\n", SIFT_DESCR_HIST_BINS);
  29. fprintf(stderr, " -d Toggle image doubling (default %s)\n",
  30. SIFT_IMG_DBL == ? "off" : "on");
  31. fprintf(stderr, " -x Turn off keypoint display\n");
  32. }

注释原因:此函数是一些控制台操作,其中有许多Unix标准库提供的函数,而我们不需要。

注释掉main函数中的:

  1. arg_parse( argc, argv );

注释原因:调用了上面那个arg_parse函数。

4. imgfeatures.c

在首行加入宏定义:

  1. #define M_PI 3.14159265358979323846

原因:报错“M_PI”未声明。

暂时这么多,可能还有些细节问题,但是很容易解决。

  1.  

二. 运行程序

好了到目前为止可以进行试验了,因为上文提到有4个main函数,所以可以分别运行来看看他们到底实现了什么功能。

1. siftfeat.c

利用siftfeat.c进行特征点的检测,返回检测到的特征点数目并在图中标记出。

       

配置好的siftfeat.c文件:

  1. /*
  2. This program detects image features using SIFT keypoints. For more info,
  3. refer to:
  4.  
  5. Lowe, D. Distinctive image features from scale-invariant keypoints.
  6. International Journal of Computer Vision, 60, 2 (2004), pp.91--110.
  7.  
  8. Copyright (C) 2006-2012 Rob Hess <rob@iqengines.com>
  9.  
  10. Note: The SIFT algorithm is patented in the United States and cannot be
  11. used in commercial products without a license from the University of
  12. British Columbia. For more information, refer to the file LICENSE.ubc
  13. that accompanied this distribution.
  14.  
  15. Version: 1.1.2-20100521
  16. */
  17.  
  18. #include "sift.h"
  19. #include "imgfeatures.h"
  20. #include "utils.h"
  21.  
  22. #include <opencv/highgui.h>
  23.  
  24. //#include <unistd.h> //unix 标准头文件
  25.  
  26. #define OPTIONS ":o:m:i:s:c:r:n:b:dxh"
  27.  
  28. /*************************** Function Prototypes *****************************/
  29.  
  30. static void usage( char* );
  31. static void arg_parse( int, char** );
  32.  
  33. /******************************** Globals ************************************/
  34.  
  35. char* pname;
  36. char* img_file_name = "G:\\360downloads\\pc.jpg"; //待检测图片的绝对路径
  37. char* out_file_name = NULL; //导出特征点到此文件中
  38. char* out_img_name = NULL; //导出图片的文件名
  39. int intvls = SIFT_INTVLS;
  40. double sigma = SIFT_SIGMA;
  41. double contr_thr = SIFT_CONTR_THR;
  42. int curv_thr = SIFT_CURV_THR;
  43. int img_dbl = SIFT_IMG_DBL;
  44. int descr_width = SIFT_DESCR_WIDTH;
  45. int descr_hist_bins = SIFT_DESCR_HIST_BINS;
  46. int display = ;
  47.  
  48. /********************************** Main *************************************/
  49.  
  50. int main( int argc, char** argv )
  51. {
  52. IplImage* img;
  53. struct feature* features;
  54. int n = ;
  55.  
  56. //arg_parse( argc, argv );
  57.  
  58. fprintf( stderr, "Finding SIFT features...\n" );
  59. img = cvLoadImage( img_file_name, );
  60. if( ! img )
  61. fatal_error( "unable to load image from %s", img_file_name );
  62. n = _sift_features( img, &features, intvls, sigma, contr_thr, curv_thr,
  63. img_dbl, descr_width, descr_hist_bins );
  64. fprintf( stderr, "Found %d features.\n", n );
  65.  
  66. if( display )
  67. {
  68. draw_features( img, features, n );
  69. display_big_img( img, img_file_name );
  70. cvWaitKey( );
  71. }
  72.  
  73. if( out_file_name != NULL )
  74. export_features( out_file_name, features, n );
  75.  
  76. if( out_img_name != NULL )
  77. cvSaveImage( out_img_name, img, NULL );
  78. return ;
  79. }

直接运行得到结果:

         

输入图像                                                                                                                                               输出图像

可以看到找到了3001个特征点。

2. match.c

注意这次调用match中的main函数,所以暂时将siftfeat.c移除。

            

配置好的match.c文件:

  1. /*
  2. Detects SIFT features in two images and finds matches between them.
  3.  
  4. Copyright (C) 2006-2012 Rob Hess <rob@iqengines.com>
  5.  
  6. @version 1.1.2-20100521
  7. */
  8.  
  9. #include "sift.h"
  10. #include "imgfeatures.h"
  11. #include "kdtree.h"
  12. #include "utils.h"
  13. #include "xform.h"
  14.  
  15. #include <opencv/cv.h>
  16. #include <opencv/cxcore.h>
  17. #include <opencv/highgui.h>
  18.  
  19. #include <stdio.h>
  20.  
  21. /* the maximum number of keypoint NN candidates to check during BBF search */
  22. #define KDTREE_BBF_MAX_NN_CHKS 200
  23.  
  24. /* threshold on squared ratio of distances between NN and 2nd NN */
  25. #define NN_SQ_DIST_RATIO_THR 0.49
  26.  
  27. int main( int argc, char** argv )
  28. {
  29. IplImage* img1, * img2, * stacked;
  30. struct feature* feat1, * feat2, * feat;
  31. struct feature** nbrs;
  32. struct kd_node* kd_root;
  33. CvPoint pt1, pt2;
  34. double d0, d1;
  35. int n1, n2, k, i, m = ;
  36.  
  37. if( argc != )
  38. fatal_error( "usage: %s <img1> <img2>", argv[] );
  39.  
  40. img1 = cvLoadImage( argv[], );
  41. if( ! img1 )
  42. fatal_error( "unable to load image from %s", argv[] );
  43. img2 = cvLoadImage( argv[], );
  44. if( ! img2 )
  45. fatal_error( "unable to load image from %s", argv[] );
  46. stacked = stack_imgs( img1, img2 );
  47.  
  48. fprintf( stderr, "Finding features in %s...\n", argv[] );
  49. n1 = sift_features( img1, &feat1 );
  50. fprintf( stderr, "Finding features in %s...\n", argv[] );
  51. n2 = sift_features( img2, &feat2 );
  52. fprintf( stderr, "Building kd tree...\n" );
  53. kd_root = kdtree_build( feat2, n2 );
  54. for( i = ; i < n1; i++ )
  55. {
  56. feat = feat1 + i;
  57. k = kdtree_bbf_knn( kd_root, feat, , &nbrs, KDTREE_BBF_MAX_NN_CHKS );
  58. if( k == )
  59. {
  60. d0 = descr_dist_sq( feat, nbrs[] );
  61. d1 = descr_dist_sq( feat, nbrs[] );
  62. if( d0 < d1 * NN_SQ_DIST_RATIO_THR )
  63. {
  64. pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
  65. pt2 = cvPoint( cvRound( nbrs[]->x ), cvRound( nbrs[]->y ) );
  66. pt2.y += img1->height;
  67. cvLine( stacked, pt1, pt2, CV_RGB(,,), , , );
  68. m++;
  69. feat1[i].fwd_match = nbrs[];
  70. }
  71. }
  72. free( nbrs );
  73. }
  74.  
  75. fprintf( stderr, "Found %d total matches\n", m );
  76. display_big_img( stacked, "Matches" );
  77. cvWaitKey( );
  78.  
  79. /*
  80. UNCOMMENT BELOW TO SEE HOW RANSAC FUNCTION WORKS
  81.  
  82. Note that this line above:
  83.  
  84. feat1[i].fwd_match = nbrs[0];
  85.  
  86. is important for the RANSAC function to work.
  87. */
  88. /*
  89. {
  90. CvMat* H;
  91. IplImage* xformed;
  92. H = ransac_xform( feat1, n1, FEATURE_FWD_MATCH, lsq_homog, 4, 0.01,
  93. homog_xfer_err, 3.0, NULL, NULL );
  94. if( H )
  95. {
  96. xformed = cvCreateImage( cvGetSize( img2 ), IPL_DEPTH_8U, 3 );
  97. cvWarpPerspective( img1, xformed, H,
  98. CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,
  99. cvScalarAll( 0 ) );
  100. cvNamedWindow( "Xformed", 1 );
  101. cvShowImage( "Xformed", xformed );
  102. cvWaitKey( 0 );
  103. cvReleaseImage( &xformed );
  104. cvReleaseMat( &H );
  105. }
  106. }
  107. */
  108.  
  109. cvReleaseImage( &stacked );
  110. cvReleaseImage( &img1 );
  111. cvReleaseImage( &img2 );
  112. kdtree_release( kd_root );
  113. free( feat1 );
  114. free( feat2 );
  115. return ;
  116. }

match.c

注意运行此程序的方法,以及图片的存放路径,具体步骤见博客

例如我的两张图片为:pc1.jpg 和 pc2.jpg,此外我都是在debug形式下调试,所以不要搞错为release。

       

pc1.jpg                                                                                                             pc2.jpg

直接运行结果:

      

可以看到总共找出1018对匹配点对。

此外其实注意到在match.c中的main函数有一部分代码被注释掉了,而这段代码调用了xform.c,即(RANSAC算法(RANdom SAmple Consensus 随机抽样一致))的结果,所以将这部分代码取消注释后,直接执行:

  1. /*
  2. Detects SIFT features in two images and finds matches between them.
  3.  
  4. Copyright (C) 2006-2012 Rob Hess <rob@iqengines.com>
  5.  
  6. @version 1.1.2-20100521
  7. */
  8.  
  9. #include "sift.h"
  10. #include "imgfeatures.h"
  11. #include "kdtree.h"
  12. #include "utils.h"
  13. #include "xform.h"
  14.  
  15. #include <opencv/cv.h>
  16. #include <opencv/cxcore.h>
  17. #include <opencv/highgui.h>
  18.  
  19. #include <stdio.h>
  20.  
  21. /* the maximum number of keypoint NN candidates to check during BBF search */
  22. #define KDTREE_BBF_MAX_NN_CHKS 200
  23.  
  24. /* threshold on squared ratio of distances between NN and 2nd NN */
  25. #define NN_SQ_DIST_RATIO_THR 0.49
  26.  
  27. int main( int argc, char** argv )
  28. {
  29. IplImage* img1, * img2, * stacked;
  30. struct feature* feat1, * feat2, * feat;
  31. struct feature** nbrs;
  32. struct kd_node* kd_root;
  33. CvPoint pt1, pt2;
  34. double d0, d1;
  35. int n1, n2, k, i, m = ;
  36.  
  37. if( argc != )
  38. fatal_error( "usage: %s <img1> <img2>", argv[] );
  39.  
  40. img1 = cvLoadImage( argv[], );
  41. if( ! img1 )
  42. fatal_error( "unable to load image from %s", argv[] );
  43. img2 = cvLoadImage( argv[], );
  44. if( ! img2 )
  45. fatal_error( "unable to load image from %s", argv[] );
  46. stacked = stack_imgs( img1, img2 );
  47.  
  48. fprintf( stderr, "Finding features in %s...\n", argv[] );
  49. n1 = sift_features( img1, &feat1 );
  50. fprintf( stderr, "Finding features in %s...\n", argv[] );
  51. n2 = sift_features( img2, &feat2 );
  52. fprintf( stderr, "Building kd tree...\n" );
  53. kd_root = kdtree_build( feat2, n2 );
  54. for( i = ; i < n1; i++ )
  55. {
  56. feat = feat1 + i;
  57. k = kdtree_bbf_knn( kd_root, feat, , &nbrs, KDTREE_BBF_MAX_NN_CHKS );
  58. if( k == )
  59. {
  60. d0 = descr_dist_sq( feat, nbrs[] );
  61. d1 = descr_dist_sq( feat, nbrs[] );
  62. if( d0 < d1 * NN_SQ_DIST_RATIO_THR )
  63. {
  64. pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
  65. pt2 = cvPoint( cvRound( nbrs[]->x ), cvRound( nbrs[]->y ) );
  66. pt2.y += img1->height;
  67. cvLine( stacked, pt1, pt2, CV_RGB(,,), , , );
  68. m++;
  69. feat1[i].fwd_match = nbrs[];
  70. }
  71. }
  72. free( nbrs );
  73. }
  74.  
  75. fprintf( stderr, "Found %d total matches\n", m );
  76. display_big_img( stacked, "Matches" );
  77. cvWaitKey( );
  78.  
  79. /*
  80. UNCOMMENT BELOW TO SEE HOW RANSAC FUNCTION WORKS
  81.  
  82. Note that this line above:
  83.  
  84. feat1[i].fwd_match = nbrs[0];
  85.  
  86. is important for the RANSAC function to work.
  87. */
  88.  
  89. {
  90. CvMat* H;
  91. IplImage* xformed;
  92. H = ransac_xform( feat1, n1, FEATURE_FWD_MATCH, lsq_homog, , 0.01,
  93. homog_xfer_err, 3.0, NULL, NULL );
  94. if( H )
  95. {
  96. xformed = cvCreateImage( cvGetSize( img2 ), IPL_DEPTH_8U, );
  97. cvWarpPerspective( img1, xformed, H,
  98. CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,
  99. cvScalarAll( ) );
  100. cvNamedWindow( "Xformed", );
  101. cvShowImage( "Xformed", xformed );
  102. cvWaitKey( );
  103. cvReleaseImage( &xformed );
  104. cvReleaseMat( &H );
  105. }
  106. }
  107.  
  108. cvReleaseImage( &stacked );
  109. cvReleaseImage( &img1 );
  110. cvReleaseImage( &img2 );
  111. kdtree_release( kd_root );
  112. free( feat1 );
  113. free( feat2 );
  114. return ;
  115. }

match.c

匹配结果

3. match_num.c

以下头文件用到了linux下的多线程编程:

  1. #include <pthread.h>

Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。暂时不讨论。

4.dspfeat.c

以下头文件用到了linux标准库:

  1. #include <unistd.h>

这个文件主要作用是可以从预先保存的特征点文件中读取特征点并显示在图片上。暂时用不到不做讨论。

源码中除了论文中步骤的实现以外,还有kdtree以及ransac等经典算法值得一看,先挖个坑,待填。

综上,可以利用sift源码来实现图像匹配,其实还可以用来作目标识别、全景图像拼接、视频跟踪等等。

附上我改好的源码链接,可以参考此文,直接运行: sift_c

参考:

RobHess的SIFT源码分析:综述

结合OPENSIFT源码详解SIFT算法

Windows下 Robhess SIFT源码配置的更多相关文章

  1. 比特币学习笔记(二)---在windows下调试比特币源码

    根据我一贯的学习经验,学习开源代码的话,单单看是不够的,必须一边看一边调试才能尽快理解,所以我们要想法搭建windows下bitcoin源码的调试环境. 紧接着昨天的进度,想要调试linux下的比特币 ...

  2. Windows下编译live555源码

    Windos下编译live555源码 环境 Win7 64位 + VS2012 步骤 1)源码下载并解压 在官网上下载最新live555源码,并对其进行解压. 2)VS下建立工程项目 新建Win32项 ...

  3. <转>windows下编译lua源码

    因为之前一直使用 lua for windows 来搭建lua的使用环境,但是最新的 lua for windows 还没有lua5.2,我又想用这个版本的lua,所以被逼无奈只能自己编一下lua源码 ...

  4. windows下编译lua源码

    所有的lua源码都放在了 src 文件夹下,当然,不同的lua版本目录结构有可能不一样,但是都会有 src 这个文件夹,只有这个才是我们编译必须的.而且lua越做越精简了,5.1的版本里面还有一些te ...

  5. Nginx (一)Windows下编译Nginx源码以及安装 nginx for windows方法步骤

    转载自: http://apps.hi.baidu.com/share/detail/11192699#content Nginx介绍: Nginx ("engine x")是一个 ...

  6. 《Lucene in Action第二版》学习总结---如何在Windows下编译luceneinAction2Edition源码包

    1. 下载此源码包,位置是: www.manning.com/hatcher3,得到:lia2e.tar.gz,然后解压缩得到目录:lia2e,为了以后能辨识,我将此目录改名为:luceneinAct ...

  7. Windows,linux下编译qt源码(比较简单)

    一.linux下静态编译qt源码 1.取到qt源码并解压到文件夹 2.cd到qt目录下 3.使用configure生成makefile ./configure–prefix /opt/qtstatic ...

  8. 阅读《RobHess的SIFT源码分析:综述》笔记

    今天总算是机缘巧合的找到了照样一篇纲要性质的文章. 如是能早一些找到就好了.不过“在你认为为时已晚的时候,其实还为时未晚”倒是也能聊以自慰,不过不能经常这样迷惑自己,毕竟我需要开始跑了! 就照着这个大 ...

  9. Windows 10 x64 下编译 Hadoop 源码

    Windows 10 x64 下编译 Hadoop 源码 环境准备 Hadoop并没有提供官方的 Windows 10 下的安装包,所以需要自己手动来编译,官方文档中 BUILDING.txt 文件中 ...

随机推荐

  1. 使用FreeRTOS在SD卡驱动使用非系统延时导致上电重启不工作的情况

    一.问题描述在一个使用FreeRTOS的工程中,只做了SD卡的驱动,由于RTOS使用了Systick,故非系统延时函数使用的是 DWT中的时钟周期(CYCCNT)计数功能,但是在SD卡驱动中使用了这个 ...

  2. Luogu 2668 NOIP 2015 斗地主(搜索,动态规划)

    Luogu 2668 NOIP 2015 斗地主(搜索,动态规划) Description 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来 ...

  3. Luogu 1351 NOIP 2014 联合权值(贪心,计数原理)

    Luogu 1351 NOIP 2014 联合权值(贪心,计数原理) Description 无向连通图 G 有 n 个点,n-1 条边.点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi, ...

  4. 记录一次react相关总结

    背景说明:元旦接到一个管理后台的项目,是一个关于自定义专题的项目.通过后台的配置自定义专题,前端根据专题模块进行渲染数据.由于管理后台是react做的前后分离,对于一个后端的我来说写写js也算是浅尝一 ...

  5. 外显子分析报错解决方案bin field of BAM record does not equal value computed based on alignment start and end, and length of sequence to which read is aligned

    以下链接给出了解决方案:https://gatkforums.broadinstitute.org/gatk/discussion/4290/sam-bin-field-error-for-the-g ...

  6. CentOS/Linux下设置IP地址

    CentOS/Linux下设置IP地址 1:临时修改:1.1:修改IP地址# ifconfig eth0 192.168.100.100 1.2:修改网关地址# route add default g ...

  7. mac burp suite https证书安装

    1. 下载burp suite 2.安装,设置并代理上 3. 打开http://burp并且下载证书 4. 点击打开选择始终信任并且导出桌面 5. 火狐打开设置至证书一栏[证书机构]导入切信任 6.大 ...

  8. 易捷支付完整业务流程的lr脚本编写

    业务流程:1.注册2.登录3.重置支付密码4.下订单5.支付订单6.查看订单列表 通用md5.h代码如下: #ifndef MD5_H #define MD5_H #ifdef __alpha typ ...

  9. div无法触发blur事件解决办法

    默认情况下div无法获取焦点,无法触发focus与blur事件,猜测span,a等标签也无法触发焦点事件(input:button,及button标签可以触发) 如何使div触发blur事件:可以给d ...

  10. jenkins+gitlab webhooks 实现自动触发打包

    说明:实现代码在gitlab上的提交后立马自动进行jenkins的job构建 安装插件: Gitlab Hook Plugin  Build Authorization Token Root Plug ...