码迷,mamicode.com
首页 > 其他好文 > 详细

RobHess的SIFT源码分析:imgfeatures.h和imgfeatures.c文件

时间:2015-04-20 13:05:17      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

SIFT源码分析系列文章的索引在这里:RobHess的SIFT源码分析:综述

 

imgfeatures.h中有SIFT特征点结构struct feature的定义,除此之外还有一些特征点的导入导出以及特征点绘制函数的声明。

对应的imgfeatures.c文件中是特征点的导入导出以及特征点绘制函数的实现。

特征点的类型有两种,一种是是牛津大学VGG提供的源码中的特征点格式,另一种是David.Lowe提供的源码中的特征点格式。

struct feature结构可以兼容这两种特征点格式,但一般用的多的还是Lowe格式的特征点,源码中默认的特征点格式也是Lowe格式的。

特征点结构体struct feature的定义如下

 

  1. /*特征点结构体 
  2. 此结构体可存储2中类型的特征点: 
  3. FEATURE_OXFD表示是牛津大学VGG提供的源码中的特征点格式, 
  4. FEATURE_LOWE表示是David.Lowe提供的源码中的特征点格式。 
  5. 如果是OXFD类型的特征点,结构体中的a,b,c成员描述了特征点周围的仿射区域(椭圆的参数),即邻域。 
  6. 如果是LOWE类型的特征点,结构体中的scl和ori成员描述了特征点的大小和方向。 
  7. fwd_match,bck_match,mdl_match一般同时只有一个起作用,用来指明此特征点对应的匹配点 
  8. */  
  9. struct feature  
  10. {  
  11.     double x;                      /**< x coord */ //特征点的x坐标  
  12.     double y;                      /**< y coord */ //特征点的y坐标  
  13.     double a;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  14.     double b;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  15.     double c;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  16.     double scl;                    /**< scale of a Lowe-style feature *///LOWE特征点的尺度  
  17.     double ori;                    /**< orientation of a Lowe-style feature */ //LOWE特征点的方向  
  18.     int d;                         /**< descriptor length */ //特征描述子的长度,即维数,一般是128  
  19.     double descr[FEATURE_MAX_D];   /**< descriptor */ //128维的特征描述子,即一个double数组  
  20.     int type;                      /**< feature type, OXFD or LOWE */ //特征点类型  
  21.     int category;                  /**< all-purpose feature category */  
  22.     struct feature* fwd_match;     /**< matching feature from forward image */   //指明此特征点对应的匹配点  
  23.     struct feature* bck_match;     /**< matching feature from backmward image */ //指明此特征点对应的匹配点  
  24.     struct feature* mdl_match;     /**< matching feature from model */           //指明此特征点对应的匹配点  
  25.     CvPoint2D64f img_pt;           /**< location in image */ //特征点的坐标,等于(x,y)  
  26.     CvPoint2D64f mdl_pt;           /**< location in model */ //当匹配类型是mdl_match时用到  
  27.     void* feature_data;            /**< user-definable data */ //用户定义的数据:  
  28.                                                                //在SIFT极值点检测中,是detection_data结构的指针  
  29.                                                                //在k-d树搜索中,是bbf_data结构的指针  
  30.                                                                //在RANSAC算法中,是ransac_data结构的指针  
  31. };  


将Lowe格式的特征点导出到txt文件后,文件的格式如下图

 

技术分享

第一行的两个数分别是特征点的总个数(上图只截取了2个特征描述子)和特征描述子的维数(默认是128)

然后是每个特征点的数据,每个特征点的第一行的四个数分别是:特征点的y坐标,x坐标,特征点的尺度,特征点的方向

然后是128个整数,即128维的特征描述子,共7行,前6行每行20个,最后一行8个。

默认情况下,检测出的特征点是按照尺度的降序排列的。

 

下面是imgfeatures.h和imgfeatures.c文件的注释:

imgfeatures.h

 

  1. /**@file 
  2. Functions and structures for dealing with image features 
  3.  
  4. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  5.  
  6. @version 1.1.2-20100521 
  7. */  
  8.   
  9. /* 
  10.   此文件中定义了存储特征点的结构体feature,以及几个函数原型的声明: 
  11. 1、特征点的导入导出 
  12. 2、特征点绘制 
  13. */  
  14.   
  15.   
  16. #ifndef IMGFEATURES_H  
  17. #define IMGFEATURES_H  
  18.   
  19. #include "cxcore.h"  
  20.   
  21. /*特征点的类型: 
  22. FEATURE_OXFD表示是牛津大学VGG提供的源码中的特征点格式, 
  23. FEATURE_LOWE表示是David.Lowe提供的源码中的特征点格式 
  24. */  
  25. /** FEATURE_OXFD <BR> FEATURE_LOWE */  
  26. enum feature_type  
  27. {  
  28.     FEATURE_OXFD,  
  29.     FEATURE_LOWE,  
  30. };  
  31.   
  32. /*特征点匹配类型: 
  33. FEATURE_FWD_MATCH:表明feature结构中的fwd_match域是对应的匹配点 
  34. FEATURE_BCK_MATCH:表明feature结构中的bck_match域是对应的匹配点 
  35. FEATURE_MDL_MATCH:表明feature结构中的mdl_match域是对应的匹配点 
  36. */  
  37. /** FEATURE_FWD_MATCH <BR> FEATURE_BCK_MATCH <BR> FEATURE_MDL_MATCH */  
  38. enum feature_match_type  
  39. {  
  40.     FEATURE_FWD_MATCH,  
  41.     FEATURE_BCK_MATCH,  
  42.     FEATURE_MDL_MATCH,  
  43. };  
  44.   
  45. /*画出的特征点的颜色*/  
  46. /* colors in which to display different feature types */  
  47. #define FEATURE_OXFD_COLOR CV_RGB(255,255,0)  
  48. #define FEATURE_LOWE_COLOR CV_RGB(255,0,255)  
  49.   
  50. /*最大特征描述子长度,定为128*/  
  51. /** max feature descriptor length */  
  52. #define FEATURE_MAX_D 128  
  53.   
  54. /*特征点结构体 
  55. 此结构体可存储2中类型的特征点: 
  56. FEATURE_OXFD表示是牛津大学VGG提供的源码中的特征点格式, 
  57. FEATURE_LOWE表示是David.Lowe提供的源码中的特征点格式。 
  58. 如果是OXFD类型的特征点,结构体中的a,b,c成员描述了特征点周围的仿射区域(椭圆的参数),即邻域。 
  59. 如果是LOWE类型的特征点,结构体中的scl和ori成员描述了特征点的大小和方向。 
  60. fwd_match,bck_match,mdl_match一般同时只有一个起作用,用来指明此特征点对应的匹配点 
  61. */  
  62. /** 
  63. Structure to represent an affine invariant image feature.  The fields 
  64. x, y, a, b, c represent the affine region around the feature: 
  65. a(x-u)(x-u) + 2b(x-u)(y-v) + c(y-v)(y-v) = 1 
  66. */  
  67. struct feature  
  68. {  
  69.     double x;                      /**< x coord */ //特征点的x坐标  
  70.     double y;                      /**< y coord */ //特征点的y坐标  
  71.     double a;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  72.     double b;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  73.     double c;                      /**< Oxford-type affine region parameter */ //OXFD特征点中椭圆的参数  
  74.     double scl;                    /**< scale of a Lowe-style feature *///LOWE特征点的尺度  
  75.     double ori;                    /**< orientation of a Lowe-style feature */ //LOWE特征点的方向  
  76.     int d;                         /**< descriptor length */ //特征描述子的长度,即维数,一般是128  
  77.     double descr[FEATURE_MAX_D];   /**< descriptor */ //128维的特征描述子,即一个double数组  
  78.     int type;                      /**< feature type, OXFD or LOWE */ //特征点类型  
  79.     int category;                  /**< all-purpose feature category */  
  80.     struct feature* fwd_match;     /**< matching feature from forward image */   //指明此特征点对应的匹配点  
  81.     struct feature* bck_match;     /**< matching feature from backmward image */ //指明此特征点对应的匹配点  
  82.     struct feature* mdl_match;     /**< matching feature from model */           //指明此特征点对应的匹配点  
  83.     CvPoint2D64f img_pt;           /**< location in image */ //特征点的坐标,等于(x,y)  
  84.     CvPoint2D64f mdl_pt;           /**< location in model */ //当匹配类型是mdl_match时用到  
  85.     void* feature_data;            /**< user-definable data */ //用户定义的数据:  
  86.                                                                //在SIFT极值点检测中,是detection_data结构的指针  
  87.                                                                //在k-d树搜索中,是bbf_data结构的指针  
  88.                                                                //在RANSAC算法中,是ransac_data结构的指针  
  89. };  
  90.   
  91.   
  92. /*从文件中读入图像特征 
  93. 文件中的特征点格式必须是FEATURE_OXFD或FEATURE_LOWE格式 
  94. 参数: 
  95. filename:文件名 
  96. type:特征点类型 
  97. feat:用来存储特征点的feature数组的指针 
  98. 返回值:导入的特征点个数 
  99. */  
  100. /** 
  101. Reads image features from file.  The file should be formatted as from 
  102. the code provided by the Visual Geometry Group at Oxford or from the 
  103. code provided by David Lowe. 
  104. @param filename location of a file containing image features 
  105. @param type determines how features are input.  If \a type is FEATURE_OXFD, 
  106.     the input file is treated as if it is from the code provided by the VGG 
  107.     at Oxford: http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  108.     <BR><BR> 
  109.     If \a type is FEATURE_LOWE, the input file is treated as if it is from 
  110.     David Lowe‘s SIFT code: http://www.cs.ubc.ca/~lowe/keypoints   
  111. @param feat pointer to an array in which to store imported features; memory for 
  112.     this array is allocated by this function and must be freed by the caller using free(*feat) 
  113. @return Returns the number of features imported from filename or -1 on error 
  114. */  
  115. extern int import_features( char* filename, int type, struct feature** feat );  
  116.   
  117.   
  118. /*导出feature数组到文件 
  119. 参数: 
  120. filename:文件名 
  121. feat:特征数组 
  122. n:特征点个数 
  123. 返回值:0:成功;1:失败 
  124. */  
  125. /** 
  126. Exports a feature set to a file formatted depending on the type of 
  127. features, as specified in the feature struct‘s type field. 
  128. @param filename name of file to which to export features 
  129. @param feat feature array 
  130. @param n number of features  
  131. @return Returns 0 on success or 1 on error 
  132. */  
  133. extern int export_features( char* filename, struct feature* feat, int n );  
  134.   
  135.   
  136. /*在图片上画出特征点 
  137. 参数: 
  138. img:图像 
  139. feat:特征点数组 
  140. n:特征点个数 
  141. */  
  142. /** 
  143. Displays a set of features on an image 
  144. @param img image on which to display features 
  145. @param feat array of Oxford-type features 
  146. @param n number of features 
  147. */  
  148. extern void draw_features( IplImage* img, struct feature* feat, int n );  
  149.   
  150.   
  151. /*计算两个特征描述子间的欧氏距离的平方 
  152. 参数: 
  153. f1:第一个特征点 
  154. f2:第二个特征点 
  155. 返回值:欧氏距离的平方 
  156. */  
  157. /** 
  158. Calculates the squared Euclidian distance between two feature descriptors. 
  159. @param f1 first feature 
  160. @param f2 second feature 
  161. @return Returns the squared Euclidian distance between the descriptors of 
  162. \a f1 and \a f2. 
  163. */  
  164. extern double descr_dist_sq( struct feature* f1, struct feature* f2 );  
  165.   
  166.   
  167. #endif  

 

 

imgfeatures.c文件

  1. /* 
  2. Functions and structures for dealing with image features 
  3.  
  4. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  5.  
  6. @version 1.1.2-20100521 
  7. */  
  8.   
  9. /* 
  10.   此文件中有几个函数的实现:特征点的导入导出,特征点的绘制 
  11. */  
  12.   
  13. #include "utils.h"  
  14. #include "imgfeatures.h"  
  15.   
  16. #include <cxcore.h>  
  17.   
  18. #include <math.h>  
  19.   
  20. /************************ 未暴露接口的一些本地函数的声明 **************************/  
  21. static int import_oxfd_features( char*, struct feature** );//导入OXFD格式特征点  
  22. static int export_oxfd_features( char*, struct feature*, int );//导出OXFD格式特征点  
  23. static void draw_oxfd_features( IplImage*, struct feature*, int );//画OXFD格式特征点  
  24. static void draw_oxfd_feature( IplImage*, struct feature*, CvScalar );//画单个点  
  25.   
  26. static int import_lowe_features( char*, struct feature** );//导入LOWE格式特征点  
  27. static int export_lowe_features( char*, struct feature*, int );//导出LOWE格式特征点  
  28. static void draw_lowe_features( IplImage*, struct feature*, int );//画LOWE格式特征点  
  29. static void draw_lowe_feature( IplImage*, struct feature*, CvScalar );//画单个点  
  30.   
  31.   
  32. /*从文件中读入图像特征 
  33. 文件中的特征点格式必须是FEATURE_OXFD或FEATURE_LOWE格式 
  34. 参数: 
  35. filename:文件名 
  36. type:特征点类型 
  37. feat:用来存储特征点的feature数组的指针 
  38. 返回值:导入的特征点个数 
  39. */  
  40. /* 
  41. Reads image features from file.  The file should be formatted as from 
  42. the code provided by the Visual Geometry Group at Oxford: 
  43. @param filename location of a file containing image features 
  44. @param type determines how features are input.  If \a type is FEATURE_OXFD, 
  45.     the input file is treated as if it is from the code provided by the VGG 
  46.     at Oxford:http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  47.     If \a type is FEATURE_LOWE, the input file is treated as if it is from 
  48.     David Lowe‘s SIFT code:http://www.cs.ubc.ca/~lowe/keypoints   
  49. @param feat pointer to an array in which to store features 
  50. @return Returns the number of features imported from filename or -1 on error 
  51. */  
  52. int import_features( char* filename, int type, struct feature** feat )  
  53. {  
  54.     int n;  
  55.   
  56.     //根据特征点类型,调用不同的函数完成导入功能  
  57.     switch( type )  
  58.     {  
  59.     case FEATURE_OXFD:  
  60.         n = import_oxfd_features( filename, feat );//调用函数,导入OXFD格式特征点  
  61.         break;  
  62.     case FEATURE_LOWE:  
  63.         n = import_lowe_features( filename, feat );//调用函数,导入LOWE格式特征点  
  64.         break;  
  65.     default: //特征点格式无法识别  
  66.         fprintf( stderr, "Warning: import_features(): unrecognized feature" \  
  67.                 "type, %s, line %d\n", __FILE__, __LINE__ );  
  68.         return -1;  
  69.     }  
  70.   
  71.     //导入失败  
  72.     if( n == -1 )  
  73.         fprintf( stderr, "Warning: unable to import features from %s,"  \  
  74.             " %s, line %d\n", filename, __FILE__, __LINE__ );  
  75.     return n;  
  76. }  
  77.   
  78.   
  79. /*导出feature数组到文件 
  80. 参数: 
  81. filename:文件名 
  82. feat:特征数组 
  83. n:特征点个数 
  84. 返回值:0:成功;1:失败 
  85. */  
  86. /* 
  87. Exports a feature set to a file formatted depending on the type of 
  88. features, as specified in the feature struct‘s type field. 
  89. @param filename name of file to which to export features 
  90. @param feat feature array 
  91. @param n number of features  
  92. @return Returns 0 on success or 1 on error 
  93. */  
  94. int export_features( char* filename, struct feature* feat, int n )  
  95. {  
  96.     int r, type;  
  97.   
  98.     //参数合法性检查  
  99.     if( n <= 0  ||  ! feat )  
  100.     {  
  101.         fprintf( stderr, "Warning: no features to export, %s line %d\n",  
  102.                 __FILE__, __LINE__ );  
  103.         return 1;  
  104.     }  
  105.     type = feat[0].type;//特征点的类型、  
  106.   
  107.     //根据特征点类型,调用不同的函数完成导出功能  
  108.     switch( type )  
  109.     {  
  110.     case FEATURE_OXFD:  
  111.         r = export_oxfd_features( filename, feat, n );//调用函数,导出OXFD格式特征点  
  112.         break;  
  113.     case FEATURE_LOWE:  
  114.         r = export_lowe_features( filename, feat, n );//调用函数,导出LOWE格式特征点  
  115.         break;  
  116.     default:  
  117.         fprintf( stderr, "Warning: export_features(): unrecognized feature" \  
  118.                 "type, %s, line %d\n", __FILE__, __LINE__ );  
  119.         return -1;  
  120.     }  
  121.   
  122.     if( r ) //导出函数返回值非0,表示导出失败  
  123.         fprintf( stderr, "Warning: unable to export features to %s,"    \  
  124.                 " %s, line %d\n", filename, __FILE__, __LINE__ );  
  125.     return r;  
  126. }  
  127.   
  128.   
  129. /*在图片上画出特征点 
  130. 参数: 
  131. img:图像 
  132. feat:特征点数组 
  133. n:特征点个数 
  134. */  
  135. /* 
  136. Draws a set of features on an image 
  137. @param img image on which to draw features 
  138. @param feat array of features 
  139. @param n number of features 
  140. */  
  141. void draw_features( IplImage* img, struct feature* feat, int n )  
  142. {  
  143.     int type;  
  144.   
  145.     //参数合法性检查  
  146.     if( n <= 0  ||  ! feat )  
  147.     {  
  148.         fprintf( stderr, "Warning: no features to draw, %s line %d\n",  
  149.                 __FILE__, __LINE__ );  
  150.         return;  
  151.     }  
  152.     type = feat[0].type;//特征点的类型  
  153.   
  154.     //根据特征点类型,调用不同的函数完成绘图功能  
  155.     switch( type )  
  156.     {  
  157.     case FEATURE_OXFD:  
  158.         draw_oxfd_features( img, feat, n );//调用函数,在图像上画OXFD格式特征点  
  159.         break;  
  160.     case FEATURE_LOWE:  
  161.         draw_lowe_features( img, feat, n );//调用函数,在图像上画LOWE格式特征点  
  162.         break;  
  163.     default:  
  164.         fprintf( stderr, "Warning: draw_features(): unrecognized feature" \  
  165.             " type, %s, line %d\n", __FILE__, __LINE__ );  
  166.         break;  
  167.     }  
  168. }  
  169.   
  170.   
  171. /*计算两个特征描述子间的欧氏距离的平方 
  172. 参数: 
  173. f1:第一个特征点 
  174. f2:第二个特征点 
  175. 返回值:欧氏距离的平方 
  176. */  
  177. /* 
  178. Calculates the squared Euclidian distance between two feature descriptors. 
  179. @param f1 first feature 
  180. @param f2 second feature 
  181. @return Returns the squared Euclidian distance between the descriptors off1 and f2. 
  182. */  
  183. double descr_dist_sq( struct feature* f1, struct feature* f2 )  
  184. {  
  185.     double diff, dsq = 0;  
  186.     double* descr1, * descr2;  
  187.     int i, d;  
  188.   
  189.     d = f1->d;//f1的特征描述子的长度  
  190.     if( f2->d != d )//若f1和f2的特征描述子长度不同,返回  
  191.         return DBL_MAX;  
  192.     descr1 = f1->descr;//f1的特征描述子,一个double数组  
  193.     descr2 = f2->descr;//f2的特征描述子,一个double数组  
  194.   
  195.     //计算欧氏距离的平方,即对应元素的差的平方和  
  196.     for( i = 0; i < d; i++ )  
  197.     {  
  198.         diff = descr1[i] - descr2[i];  
  199.         dsq += diff*diff;  
  200.     }  
  201.     return dsq;  
  202. }  
  203.   
  204.   
  205. /***************************** 一些未暴露接口的内部函数 *******************************/  
  206. /***************************** Local Functions *******************************/  
  207.   
  208.   
  209. /*从文件中读入OXFD格式的图像特征 
  210. 参数: 
  211. filename:文件名 
  212. features:用来存储特征点的feature数组的指针 
  213. 返回值:导入的特征点个数 
  214. */  
  215. /* 
  216. Reads image features from file.  The file should be formatted as from 
  217. the code provided by the Visual Geometry Group at Oxford: 
  218. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  219. @param filename location of a file containing image features 
  220. @param features pointer to an array in which to store features 
  221. @return Returns the number of features imported from filename or -1 on error 
  222. */  
  223. static int import_oxfd_features( char* filename, struct feature** features )  
  224. {  
  225.     struct feature* f;//第一个特征点的指针  
  226.     int i, j, n, d;  
  227.     double x, y, a, b, c, dv;  
  228.     FILE* file;//文件指针  
  229.   
  230.     if( ! features )  
  231.         fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );  
  232.   
  233.     //打开文件  
  234.     if( ! ( file = fopen( filename, "r" ) ) )  
  235.     {  
  236.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  237.                 filename, __FILE__, __LINE__ );  
  238.         return -1;  
  239.     }  
  240.   
  241.     //读入特征描述子维数和特征点个数  
  242.     /* read dimension and number of features */  
  243.     if( fscanf( file, " %d %d ", &d, &n ) != 2 )  
  244.     {  
  245.         fprintf( stderr, "Warning: file read error, %s, line %d\n",  
  246.                 __FILE__, __LINE__ );  
  247.         return -1;  
  248.     }  
  249.     //特征描述子维数大于定义的最大维数,出错  
  250.     if( d > FEATURE_MAX_D )  
  251.     {  
  252.         fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",  
  253.                 __FILE__, __LINE__ );  
  254.         return -1;  
  255.     }  
  256.   
  257.     //分配内存,n个feature结构大小,返回首地址给f  
  258.     f = calloc( n, sizeof(struct feature) );  
  259.   
  260.     //遍历文件中的n个特征点  
  261.     for( i = 0; i < n; i++ )  
  262.     {  
  263.         //读入仿射区域参数  
  264.         /* read affine region parameters */  
  265.         if( fscanf( file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c ) != 5 )  
  266.         {  
  267.             fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",  
  268.                     i+1, __FILE__, __LINE__ );  
  269.             free( f );//发生错误后释放内存  
  270.             return -1;  
  271.         }  
  272.         //给第i个特征点赋值  
  273.         f[i].img_pt.x = f[i].x = x;//特征点的x坐标  
  274.         f[i].img_pt.y = f[i].y = y;//特征点的y坐标  
  275.         f[i].a = a;  
  276.         f[i].b = b;  
  277.         f[i].c = c;  
  278.         f[i].d = d;  
  279.         f[i].type = FEATURE_OXFD;//特征点类型  
  280.   
  281.         //读入特征描述子  
  282.         /* read descriptor */  
  283.         for( j = 0; j < d; j++ )  
  284.         {  
  285.             if( ! fscanf( file, " %lf ", &dv ) )  
  286.             {  
  287.                 fprintf( stderr, "Warning: error reading feature descriptor" \  
  288.                         " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );  
  289.                 free( f );//发生错误后释放内存  
  290.                 return -1;  
  291.             }  
  292.             f[i].descr[j] = dv;//赋给第i个特征点的第j个特征描述符  
  293.         }  
  294.   
  295.         //其他一些没什么用的参数  
  296.         f[i].scl = f[i].ori = 0;//OXFD特征点无此参数  
  297.         f[i].category = 0;  
  298.         f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;  
  299.         f[i].mdl_pt.x = f[i].mdl_pt.y = -1;  
  300.         f[i].feature_data = NULL;  
  301.     }  
  302.   
  303.     //关闭文件  
  304.     if( fclose(file) )  
  305.     {  
  306.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  307.                 __FILE__, __LINE__ );  
  308.         free( f );//发生错误后释放内存  
  309.         return -1;  
  310.     }  
  311.   
  312.     *features = f;//将第一个特征点的指针赋给*feature  
  313.     return n;//返回读入的特征点个数  
  314. }  
  315.   
  316.   
  317. /*导出OXFD格式的特征点集到文件 
  318. 参数: 
  319. filename:文件名 
  320. feat:特征数组 
  321. n:特征点个数 
  322. 返回值:0:成功;1:失败 
  323. */  
  324. /* 
  325. Exports a feature set to a file formatted as one from the code provided 
  326. by the Visual Geometry Group at Oxford: 
  327. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  328. @param filename name of file to which to export features 
  329. @param feat feature array 
  330. @param n number of features 
  331. @return Returns 0 on success or 1 on error 
  332. */  
  333. static int export_oxfd_features( char* filename, struct feature* feat, int n )  
  334. {  
  335.     FILE* file;  
  336.     int i, j, d;  
  337.   
  338.     if( n <= 0 )  
  339.     {  
  340.         fprintf( stderr, "Warning: feature count %d, %s, line %s\n",  
  341.                 n, __FILE__, __LINE__ );  
  342.         return 1;  
  343.     }  
  344.     //打开文件  
  345.     if( ! ( file = fopen( filename, "w" ) ) )  
  346.     {  
  347.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  348.                 filename, __FILE__, __LINE__ );  
  349.         return 1;  
  350.     }  
  351.   
  352.     d = feat[0].d;//特征描述子的维数  
  353.     fprintf( file, "%d\n%d\n", d, n );//首先写入特征描述子的维数和特征点个数  
  354.   
  355.     //依次写入每个特征点的信息  
  356.     for( i = 0; i < n; i++ )  
  357.     {  
  358.         //写入仿射区域参数  
  359.         fprintf( file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,  
  360.                 feat[i].b, feat[i].c );  
  361.         //写入d个特征描述子的元素  
  362.         for( j = 0; j < d; j++ )  
  363.             fprintf( file, " %f", feat[i].descr[j] );  
  364.         fprintf( file, "\n" );//换行  
  365.     }  
  366.   
  367.     //关闭文件  
  368.     if( fclose(file) )  
  369.     {  
  370.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  371.                 __FILE__, __LINE__ );  
  372.         return 1;  
  373.     }  
  374.   
  375.     return 0;  
  376. }  
  377.   
  378.   
  379. /*在图像上画出OXFD类型的特征点 
  380. 参数: 
  381. img:图像指针 
  382. feat:特征数组 
  383. n:特征个数 
  384. */  
  385. /* 
  386. Draws Oxford-type affine features 
  387. @param img image on which to draw features 
  388. @param feat array of Oxford-type features 
  389. @param n number of features 
  390. */  
  391. static void draw_oxfd_features( IplImage* img, struct feature* feat, int n )  
  392. {  
  393.     CvScalar color = CV_RGB( 255, 255, 255 );//颜色  
  394.     int i;  
  395.   
  396.     if( img-> nChannels > 1 )  
  397.         color = FEATURE_OXFD_COLOR;  
  398.   
  399.     //调用函数,依次画出每个特征点  
  400.     for( i = 0; i < n; i++ )  
  401.         draw_oxfd_feature( img, feat + i, color );  
  402. }  
  403.   
  404.   
  405. /*在图像上画单个OXFD特征点 
  406. 参数: 
  407. img:图像指针 
  408. feat:要画的特征点 
  409. color:颜色 
  410. */  
  411. /* 
  412. Draws a single Oxford-type feature 
  413. @param img image on which to draw 
  414. @param feat feature to be drawn 
  415. @param color color in which to draw 
  416. */  
  417. static void draw_oxfd_feature( IplImage* img, struct feature* feat, CvScalar color )  
  418. {  
  419.     double m[4] = { feat->a, feat->b, feat->b, feat->c };  
  420.     double v[4] = { 0 };//特征向量的数据  
  421.     double e[2] = { 0 };//特征值的数据  
  422.     CvMat M, V, E;  
  423.     double alpha, l1, l2;  
  424.   
  425.     //计算椭圆的轴线和方向  
  426.     /* compute axes and orientation of ellipse surrounding affine region */  
  427.     cvInitMatHeader( &M, 2, 2, CV_64FC1, m, CV_AUTOSTEP );//矩阵  
  428.     cvInitMatHeader( &V, 2, 2, CV_64FC1, v, CV_AUTOSTEP );//2个2*1的特征向量组成的矩阵  
  429.     cvInitMatHeader( &E, 2, 1, CV_64FC1, e, CV_AUTOSTEP );//特征值  
  430.     cvEigenVV( &M, &V, &E, DBL_EPSILON, 0, 0 );//计算特征值和特征向量  
  431.     l1 = 1 / sqrt( e[1] );  
  432.     l2 = 1 / sqrt( e[0] );  
  433.     alpha = -atan2( v[1], v[0] );  
  434.     alpha *= 180 / CV_PI;  
  435.   
  436.     //画椭圆和十字星  
  437.     cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,  
  438.                 0, 360, CV_RGB(0,0,0), 3, 8, 0 );  
  439.     cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,  
  440.                 0, 360, color, 1, 8, 0 );  
  441.     cvLine( img, cvPoint( feat->x+2, feat->y ), cvPoint( feat->x-2, feat->y ),  
  442.             color, 1, 8, 0 );  
  443.     cvLine( img, cvPoint( feat->x, feat->y+2 ), cvPoint( feat->x, feat->y-2 ),  
  444.             color, 1, 8, 0 );  
  445. }  
  446.   
  447.   
  448. /*从文件中读入LOWE特征点 
  449. 参数: 
  450. filename:文件名 
  451. features:存放特征点的特征数组的指针 
  452. 返回值:读入的特征点个数 
  453. */  
  454. /* 
  455. Reads image features from file.  The file should be formatted as from 
  456. the code provided by David Lowe:http://www.cs.ubc.ca/~lowe/keypoints/ 
  457. @param filename location of a file containing image features 
  458. @param features pointer to an array in which to store features 
  459. @return Returns the number of features imported from filename or -1 on error 
  460. */  
  461. static int import_lowe_features( char* filename, struct feature** features )  
  462. {  
  463.     struct feature* f;//第一个特征点的指针  
  464.     int i, j, n, d;  
  465.     double x, y, s, o, dv;  
  466.     FILE* file;  
  467.   
  468.     if( ! features )  
  469.         fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );  
  470.   
  471.     //打开文件  
  472.     if( ! ( file = fopen( filename, "r" ) ) )  
  473.     {  
  474.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  475.             filename, __FILE__, __LINE__ );  
  476.         return -1;  
  477.     }  
  478.   
  479.     //首先读入特征点个数和特征描述子维数  
  480.     /* read number of features and dimension */  
  481.     if( fscanf( file, " %d %d ", &n, &d ) != 2 )  
  482.     {  
  483.         fprintf( stderr, "Warning: file read error, %s, line %d\n",  
  484.                 __FILE__, __LINE__ );  
  485.         return -1;  
  486.     }  
  487.   
  488.     //特征描述子维数大于定义的最大维数,出错  
  489.     if( d > FEATURE_MAX_D )  
  490.     {  
  491.         fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",  
  492.                 __FILE__, __LINE__ );  
  493.         return -1;  
  494.     }  
  495.   
  496.     //分配内存,n个feature结构大小,返回首地址给f  
  497.     f = calloc( n, sizeof(struct feature) );  
  498.   
  499.     //依次读入n个特征点  
  500.     for( i = 0; i < n; i++ )  
  501.     {  
  502.         //读入特征点的坐标(注意x,y顺序),尺度和方向  
  503.         /* read affine region parameters */  
  504.         if( fscanf( file, " %lf %lf %lf %lf ", &y, &x, &s, &o ) != 4 )  
  505.         {  
  506.             fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",  
  507.                     i+1, __FILE__, __LINE__ );  
  508.             free( f );//出错后释放内存  
  509.             return -1;  
  510.         }  
  511.         //给第i个特征点赋值  
  512.         f[i].img_pt.x = f[i].x = x;//特征点的x坐标  
  513.         f[i].img_pt.y = f[i].y = y;//特征点的y坐标  
  514.         f[i].scl = s;//特征点的大小,即其主方向的梯度的模值  
  515.         f[i].ori = o;//特征点的方向,即其主方向  
  516.         f[i].d = d;//特征描述子的维数  
  517.         f[i].type = FEATURE_LOWE;//类型  
  518.   
  519.         //读入特征描述子  
  520.         /* read descriptor */  
  521.         for( j = 0; j < d; j++ )  
  522.         {  
  523.             if( ! fscanf( file, " %lf ", &dv ) )  
  524.             {  
  525.                 fprintf( stderr, "Warning: error reading feature descriptor" \  
  526.                         " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );  
  527.                 free( f );//出错后释放内存  
  528.                 return -1;  
  529.             }  
  530.             f[i].descr[j] = dv;  
  531.         }  
  532.   
  533.         //其他一些没什么用的参数  
  534.         f[i].a = f[i].b = f[i].c = 0;  
  535.         f[i].category = 0;  
  536.         f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;  
  537.         f[i].mdl_pt.x = f[i].mdl_pt.y = -1;  
  538.     }  
  539.   
  540.     //关闭文件  
  541.     if( fclose(file) )  
  542.     {  
  543.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  544.                 __FILE__, __LINE__ );  
  545.         free( f );//出错后释放内存  
  546.         return -1;  
  547.     }  
  548.   
  549.     *features = f;//首地址赋给*features  
  550.     return n;//返回读入的特征点个数  
  551. }  
  552.   
  553.   
  554. /*导出LOWE格式特征点集合到文件 
  555. 参数: 
  556. filename:文件名 
  557. feat:特征点数组 
  558. n:特征点个数 
  559. 返回值:0:成功;1:失败 
  560. */  
  561. /* 
  562. Exports a feature set to a file formatted as one from the code provided 
  563. by David Lowe:http://www.cs.ubc.ca/~lowe/keypoints/ 
  564.  
  565. @param filename name of file to which to export features 
  566. @param feat feature array 
  567. @param n number of features 
  568.  
  569. @return Returns 0 on success or 1 on error 
  570. */  
  571. static int export_lowe_features( char* filename, struct feature* feat, int n )  
  572. {  
  573.     FILE* file;  
  574.     int i, j, d;  
  575.   
  576.     if( n <= 0 )  
  577.     {  
  578.         fprintf( stderr, "Warning: feature count %d, %s, line %s\n",  
  579.                 n, __FILE__, __LINE__ );  
  580.         return 1;  
  581.     }  
  582.   
  583.     //打开文件  
  584.     if( ! ( file = fopen( filename, "w" ) ) )  
  585.     {  
  586.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  587.                 filename, __FILE__, __LINE__ );  
  588.         return 1;  
  589.     }  
  590.   
  591.     d = feat[0].d;//特征描述子维数  
  592.     fprintf( file, "%d %d\n", n, d );//首先写入特征点个数和特征描述子维数  
  593.   
  594.     //依次写入每个特征点的信息  
  595.     for( i = 0; i < n; i++ )  
  596.     {  
  597.         //写入特征点坐标(注意x,y顺序),尺度,方向  
  598.         fprintf( file, "%f %f %f %f", feat[i].y, feat[i].x,  
  599.                 feat[i].scl, feat[i].ori );  
  600.         //写入特征描述子  
  601.         for( j = 0; j < d; j++ )  
  602.         {  
  603.             //每行20个元素  
  604.             /* write 20 descriptor values per line */  
  605.             if( j % 20 == 0 )  
  606.                 fprintf( file, "\n" );  
  607.             fprintf( file, " %d", (int)(feat[i].descr[j]) );  
  608.         }  
  609.         fprintf( file, "\n" );  
  610.     }  
  611.   
  612.     //关闭文件  
  613.     if( fclose(file) )  
  614.     {  
  615.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  616.                 __FILE__, __LINE__ );  
  617.         return 1;  
  618.     }  
  619.   
  620.     return 0;  
  621. }  
  622.   
  623.   
  624. /*在图像上画LOWE特征点 
  625. 参数: 
  626. img:图像指针 
  627. feat:特征点数组 
  628. n:特征点个数 
  629. */  
  630. /* 
  631. Draws Lowe-type features 
  632. @param img image on which to draw features 
  633. @param feat array of Oxford-type features 
  634. @param n number of features 
  635. */  
  636. static void draw_lowe_features( IplImage* img, struct feature* feat, int n )  
  637. {  
  638.     CvScalar color = CV_RGB( 255, 255, 255 );//颜色  
  639.     int i;  
  640.   
  641.     if( img-> nChannels > 1 )  
  642.         color = FEATURE_LOWE_COLOR;  
  643.   
  644.     //调用函数,依次画n个特征点  
  645.     for( i = 0; i < n; i++ )  
  646.         draw_lowe_feature( img, feat + i, color );  
  647. }  
  648.   
  649.   
  650. /*画单个LOWE特征点 
  651. 参数: 
  652. img:图像指针 
  653. feat:要画的特征点 
  654. color:颜色 
  655. */  
  656. /* 
  657. Draws a single Lowe-type feature 
  658. @param img image on which to draw 
  659. @param feat feature to be drawn 
  660. @param color color in which to draw 
  661. */  
  662. static void draw_lowe_feature( IplImage* img, struct feature* feat, CvScalar color )  
  663. {  
  664.     int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;  
  665.     double scl, ori;  
  666.     double scale = 5.0;  
  667.     double hscale = 0.75;  
  668.     CvPoint start, end, h1, h2;  
  669.   
  670.     /* compute points for an arrow scaled and rotated by feat‘s scl and ori */  
  671.     //箭头杆的起点的坐标  
  672.     start_x = cvRound( feat->x );  
  673.     start_y = cvRound( feat->y );  
  674.     scl = feat->scl;//特征点的大小  
  675.     ori = feat->ori;//特征点的方向,弧度  
  676.     len = cvRound( scl * scale );//箭头杆的长度  
  677.     hlen = cvRound( scl * hscale );//箭头分叉的长度  
  678.     blen = len - hlen;  
  679.     //箭头杆的终点的坐标  
  680.     end_x = cvRound( len *  cos( ori ) ) + start_x;  
  681.     end_y = cvRound( len * -sin( ori ) ) + start_y;  
  682.     //箭头的右分叉的起点的坐标  
  683.     h1_x = cvRound( blen *  cos( ori + CV_PI / 18.0 ) ) + start_x;  
  684.     h1_y = cvRound( blen * -sin( ori + CV_PI / 18.0 ) ) + start_y;  
  685.     //箭头的左分叉的起点的坐标  
  686.     h2_x = cvRound( blen *  cos( ori - CV_PI / 18.0 ) ) + start_x;  
  687.     h2_y = cvRound( blen * -sin( ori - CV_PI / 18.0 ) ) + start_y;  
  688.     start = cvPoint( start_x, start_y );//箭头杆的起点  
  689.     end = cvPoint( end_x, end_y );//箭头杆的终点  
  690.     h1 = cvPoint( h1_x, h1_y );//箭头的右分叉的起点  
  691.     h2 = cvPoint( h2_x, h2_y );//箭头的左分叉的起点  
  692.   
  693.     cvLine( img, start, end, color, 1, 8, 0 );//画箭头杆  
  694.     cvLine( img, end, h1, color, 1, 8, 0 );//画右分叉  
  695.     cvLine( img, end, h2, color, 1, 8, 0 );//画左分叉  
  696. }  

RobHess的SIFT源码分析:imgfeatures.h和imgfeatures.c文件

标签:

原文地址:http://www.cnblogs.com/ywsoftware/p/4441014.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!