因为在前两天的学习中发现。在opencv环境中跑动sift特征点提取还是比较困难的。

所以在此,进行记述。

遇到的问题分别有,csdn不愿意花费积分、配置gtk困难、教程海量然而能跑者鲜。描述不详尽等。

【然后我却是发现这个borwhess实在是不知道叫先生何名为好。】

话归正题。

以下跑动具体过程:

首先去:

http://blog.csdn.net/masibuaa/article/details/9246493

发现main.cpp

也就是:检测sift的部分。

这个回头慢慢凿。先跑起来:

sift主体:

  1. img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
  2. img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
  3.  
  4. //默认提取的是LOWE格式的SIFT特征点
  5. //提取并显示第1幅图片上的特征点
  6. n1 = sift_features( img1, &feat1 );//检测图1中的SIFT特征点,n1是图1的特征点个数
  7. export_features("feature1.txt",feat1,n1);//将特征向量数据写入到文件
  8. draw_features( img1_Feat, feat1, n1 );//画出特征点
  9. cvNamedWindow(IMG1_FEAT);//创建窗口
  10. cvShowImage(IMG1_FEAT,img1_Feat);//显示
  11.  
  12. //提取并显示第2幅图片上的特征点
  13. n2 = sift_features( img2, &feat2 );//检测图2中的SIFT特征点,n2是图2的特征点个数
  14. export_features("feature2.txt",feat2,n2);//将特征向量数据写入到文件
  15. draw_features( img2_Feat, feat2, n2 );//画出特征点
  16. cvNamedWindow(IMG2_FEAT);//创建窗口
  17. cvShowImage(IMG2_FEAT,img2_Feat);//显示

这个基本算是函数主体,也就是要运行的主程。

由于调试过程中,调动多次:次序依然蒙蔽。

主体来自:

https://github.com/robwhess/opensift

然而,现在的win7装载gtk并不容易,我在读了2/5之后没有打算继续安装的想法。

遂西凑东拼,

勉强实现这样的结果:

算是sift,检测出来了。

调用函数主体:

http://www.cnblogs.com/freedomshe/archive/2012/04/28/2475057.html

一共七个文件:imgfeatures.h sift.h utils.h imgfeatures.c main.cpp sift.c utils.c 以下源代码。

sift.h:

  1. /**@file
  2. Functions for detecting SIFT image features.
  3.  
  4. For more information, refer to:
  5.  
  6. Lowe, D. Distinctive image features from scale-invariant keypoints.
  7. <EM>International Journal of Computer Vision, 60</EM>, 2 (2004),
  8. pp.91--110.
  9.  
  10. Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
  11. Note: The SIFT algorithm is patented in the United States and cannot be
  12. used in commercial products without a license from the University of
  13. British Columbia. For more information, refer to the file LICENSE.ubc
  14. that accompanied this distribution.
  15.  
  16. @version 1.1.2-20100521
  17. */
  18.  
  19. #ifndef SIFT_H
  20. #define SIFT_H
  21.  
  22. #include "cxcore.h"
  23.  
  24. /******************************** Structures *********************************/
  25.  
  26. /** holds feature data relevant to detection */
  27. struct detection_data
  28. {
  29. int r;
  30. int c;
  31. int octv;
  32. int intvl;
  33. double subintvl;
  34. double scl_octv;
  35. };
  36.  
  37. struct feature;
  38.  
  39. /******************************* Defs and macros *****************************/
  40.  
  41. /** default number of sampled intervals per octave */
  42. #define SIFT_INTVLS 3
  43.  
  44. /** default sigma for initial gaussian smoothing */
  45. #define SIFT_SIGMA 1.6
  46.  
  47. /** default threshold on keypoint contrast |D(x)| */
  48. #define SIFT_CONTR_THR 0.04
  49.  
  50. /** default threshold on keypoint ratio of principle curvatures */
  51. #define SIFT_CURV_THR 10
  52.  
  53. /** double image size before pyramid construction? */
  54. #define SIFT_IMG_DBL 1
  55.  
  56. /** default width of descriptor histogram array */
  57. #define SIFT_DESCR_WIDTH 4
  58.  
  59. /** default number of bins per histogram in descriptor array */
  60. #define SIFT_DESCR_HIST_BINS 8
  61.  
  62. /* assumed gaussian blur for input image */
  63. #define SIFT_INIT_SIGMA 0.5
  64.  
  65. /* width of border in which to ignore keypoints */
  66. #define SIFT_IMG_BORDER 5
  67.  
  68. /* maximum steps of keypoint interpolation before failure */
  69. #define SIFT_MAX_INTERP_STEPS 5
  70.  
  71. /* default number of bins in histogram for orientation assignment */
  72. #define SIFT_ORI_HIST_BINS 36
  73.  
  74. /* determines gaussian sigma for orientation assignment */
  75. #define SIFT_ORI_SIG_FCTR 1.5
  76.  
  77. /* determines the radius of the region used in orientation assignment */
  78. #define SIFT_ORI_RADIUS 3.0 * SIFT_ORI_SIG_FCTR
  79.  
  80. /* number of passes of orientation histogram smoothing */
  81. #define SIFT_ORI_SMOOTH_PASSES 2
  82.  
  83. /* orientation magnitude relative to max that results in new feature */
  84. #define SIFT_ORI_PEAK_RATIO 0.8
  85.  
  86. /* determines the size of a single descriptor orientation histogram */
  87. #define SIFT_DESCR_SCL_FCTR 3.0
  88.  
  89. /* threshold on magnitude of elements of descriptor vector */
  90. #define SIFT_DESCR_MAG_THR 0.2
  91.  
  92. /* factor used to convert floating-point descriptor to unsigned char */
  93. #define SIFT_INT_DESCR_FCTR 512.0
  94.  
  95. /* returns a feature's detection data */
  96. #define feat_detection_data(f) ( (struct detection_data*)(f->feature_data) )
  97.  
  98. /*************************** Function Prototypes *****************************/
  99.  
  100. #ifdef __cplusplus
  101. extern "C" {
  102. #endif
  103.  
  104. /**
  105. Finds SIFT features in an image using default parameter values. All
  106. detected features are stored in the array pointed to by \a feat.
  107.  
  108. @param img the image in which to detect features
  109. @param feat a pointer to an array in which to store detected features; memory
  110. for this array is allocated by this function and must be freed by the caller
  111. using free(*feat)
  112.  
  113. @return Returns the number of features stored in \a feat or -1 on failure
  114. @see _sift_features()
  115. */
  116. extern int sift_features(IplImage* img, struct feature** feat);
  117.  
  118. /**
  119. Finda SIFT features in an image using user-specified parameter values. All
  120. detected features are stored in the array pointed to by \a feat.
  121.  
  122. @param img the image in which to detect features
  123. @param feat a pointer to an array in which to store detected features; memory
  124. for this array is allocated by this function and must be freed by the caller
  125. using free(*feat)
  126. @param intvls the number of intervals sampled per octave of scale space
  127. @param sigma the amount of Gaussian smoothing applied to each image level
  128. before building the scale space representation for an octave
  129. @param contr_thr a threshold on the value of the scale space function
  130. \f$\left|D(\hat{x})\right|\f$, where \f$\hat{x}\f$ is a vector specifying
  131. feature location and scale, used to reject unstable features; assumes
  132. pixel values in the range [0, 1]
  133. @param curv_thr threshold on a feature's ratio of principle curvatures
  134. used to reject features that are too edge-like
  135. @param img_dbl should be 1 if image doubling prior to scale space
  136. construction is desired or 0 if not
  137. @param descr_width the width, \f$n\f$, of the \f$n \times n\f$ array of
  138. orientation histograms used to compute a feature's descriptor
  139. @param descr_hist_bins the number of orientations in each of the
  140. histograms in the array used to compute a feature's descriptor
  141.  
  142. @return Returns the number of keypoints stored in \a feat or -1 on failure
  143. @see sift_features()
  144. */
  145. extern int _sift_features(IplImage* img, struct feature** feat, int intvls,
  146. double sigma, double contr_thr, int curv_thr,
  147. int img_dbl, int descr_width, int descr_hist_bins);
  148.  
  149. #ifdef __cplusplus
  150. }
  151. #endif
  152.  
  153. #endif

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. #ifndef IMGFEATURES_H
  10. #define IMGFEATURES_H
  11.  
  12. #include "cxcore.h"
  13.  
  14. /** FEATURE_OXFD <BR> FEATURE_LOWE */
  15. enum feature_type
  16. {
  17. FEATURE_OXFD,
  18. FEATURE_LOWE,
  19. };
  20.  
  21. /** FEATURE_FWD_MATCH <BR> FEATURE_BCK_MATCH <BR> FEATURE_MDL_MATCH */
  22. enum feature_match_type
  23. {
  24. FEATURE_FWD_MATCH,
  25. FEATURE_BCK_MATCH,
  26. FEATURE_MDL_MATCH,
  27. };
  28.  
  29. /* colors in which to display different feature types */
  30. #define FEATURE_OXFD_COLOR CV_RGB(255,255,0)
  31. #define FEATURE_LOWE_COLOR CV_RGB(255,0,255)
  32.  
  33. /** max feature descriptor length */
  34. #define FEATURE_MAX_D 128
  35.  
  36. /**
  37. Structure to represent an affine invariant image feature. The fields
  38. x, y, a, b, c represent the affine region around the feature:
  39.  
  40. a(x-u)(x-u) + 2b(x-u)(y-v) + c(y-v)(y-v) = 1
  41. */
  42. struct feature
  43. {
  44. double x; /**< x coord */
  45. double y; /**< y coord */
  46. double a; /**< Oxford-type affine region parameter */
  47. double b; /**< Oxford-type affine region parameter */
  48. double c; /**< Oxford-type affine region parameter */
  49. double scl; /**< scale of a Lowe-style feature */
  50. double ori; /**< orientation of a Lowe-style feature */
  51. int d; /**< descriptor length */
  52. double descr[FEATURE_MAX_D]; /**< descriptor */
  53. int type; /**< feature type, OXFD or LOWE */
  54. int category; /**< all-purpose feature category */
  55. struct feature* fwd_match; /**< matching feature from forward image */
  56. struct feature* bck_match; /**< matching feature from backmward image */
  57. struct feature* mdl_match; /**< matching feature from model */
  58. CvPoint2D64f img_pt; /**< location in image */
  59. CvPoint2D64f mdl_pt; /**< location in model */
  60. void* feature_data; /**< user-definable data */
  61. };
  62.  
  63. #ifdef __cplusplus
  64. extern "C" {
  65. #endif
  66.  
  67. /**
  68. Reads image features from file. The file should be formatted as from
  69. the code provided by the Visual Geometry Group at Oxford or from the
  70. code provided by David Lowe.
  71.  
  72. @param filename location of a file containing image features
  73. @param type determines how features are input. If \a type is FEATURE_OXFD,
  74. the input file is treated as if it is from the code provided by the VGG
  75. at Oxford: http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  76. <BR><BR>
  77. If \a type is FEATURE_LOWE, the input file is treated as if it is from
  78. David Lowe's SIFT code: http://www.cs.ubc.ca/~lowe/keypoints
  79. @param feat pointer to an array in which to store imported features; memory for
  80. this array is allocated by this function and must be freed by the caller using
  81. free(*feat)
  82.  
  83. @return Returns the number of features imported from filename or -1 on error
  84. */
  85. extern int import_features(char* filename, int type, struct feature** feat);
  86.  
  87. /**
  88. Exports a feature set to a file formatted depending on the type of
  89. features, as specified in the feature struct's type field.
  90.  
  91. @param filename name of file to which to export features
  92. @param feat feature array
  93. @param n number of features
  94.  
  95. @return Returns 0 on success or 1 on error
  96. */
  97. extern int export_features(char* filename, struct feature* feat, int n);
  98.  
  99. /**
  100. Displays a set of features on an image
  101.  
  102. @param img image on which to display features
  103. @param feat array of Oxford-type features
  104. @param n number of features
  105. */
  106. extern void draw_features(IplImage* img, struct feature* feat, int n);
  107.  
  108. /**
  109. Calculates the squared Euclidian distance between two feature descriptors.
  110.  
  111. @param f1 first feature
  112. @param f2 second feature
  113.  
  114. @return Returns the squared Euclidian distance between the descriptors of
  115. \a f1 and \a f2.
  116. */
  117. extern double descr_dist_sq(struct feature* f1, struct feature* f2);
  118.  
  119. #ifdef __cplusplus
  120. }
  121. #endif
  122.  
  123. #endif

utils.h

  1. /**@file
  2. Miscellaneous utility functions.
  3.  
  4. Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
  5.  
  6. @version 1.1.2-20100521
  7. */
  8.  
  9. #ifndef UTILS_H
  10. #define UTILS_H
  11.  
  12. #include "cxcore.h"
  13.  
  14. #include <stdio.h>
  15.  
  16. /* absolute value */
  17. #ifndef ABS
  18. #define ABS(x) ( ( (x) < 0 )? -(x) : (x) )
  19. #endif
  20.  
  21. /***************************** Inline Functions ******************************/
  22.  
  23. /**
  24. A function to get a pixel value from an 8-bit unsigned image.
  25.  
  26. @param img an image
  27. @param r row
  28. @param c column
  29. @return Returns the value of the pixel at (\a r, \a c) in \a img
  30. */
  31. static __inline int pixval8(IplImage* img, int r, int c)
  32. {
  33. return (int)(((uchar*)(img->imageData + img->widthStep*r))[c]);
  34. }
  35.  
  36. /**
  37. A function to set a pixel value in an 8-bit unsigned image.
  38.  
  39. @param img an image
  40. @param r row
  41. @param c column
  42. @param val pixel value
  43. */
  44. static __inline void setpix8(IplImage* img, int r, int c, uchar val)
  45. {
  46. ((uchar*)(img->imageData + img->widthStep*r))[c] = val;
  47. }
  48.  
  49. /**
  50. A function to get a pixel value from a 32-bit floating-point image.
  51.  
  52. @param img an image
  53. @param r row
  54. @param c column
  55. @return Returns the value of the pixel at (\a r, \a c) in \a img
  56. */
  57. static __inline float pixval32f(IplImage* img, int r, int c)
  58. {
  59. return ((float*)(img->imageData + img->widthStep*r))[c];
  60. }
  61.  
  62. /**
  63. A function to set a pixel value in a 32-bit floating-point image.
  64.  
  65. @param img an image
  66. @param r row
  67. @param c column
  68. @param val pixel value
  69. */
  70. static __inline void setpix32f(IplImage* img, int r, int c, float val)
  71. {
  72. ((float*)(img->imageData + img->widthStep*r))[c] = val;
  73. }
  74.  
  75. /**
  76. A function to get a pixel value from a 64-bit floating-point image.
  77.  
  78. @param img an image
  79. @param r row
  80. @param c column
  81. @return Returns the value of the pixel at (\a r, \a c) in \a img
  82. */
  83. static __inline double pixval64f(IplImage* img, int r, int c)
  84. {
  85. return (double)(((double*)(img->imageData + img->widthStep*r))[c]);
  86. }
  87.  
  88. /**
  89. A function to set a pixel value in a 64-bit floating-point image.
  90.  
  91. @param img an image
  92. @param r row
  93. @param c column
  94. @param val pixel value
  95. */
  96. static __inline void setpix64f(IplImage* img, int r, int c, double val)
  97. {
  98. ((double*)(img->imageData + img->widthStep*r))[c] = val;
  99. }
  100.  
  101. /**************************** Function Prototypes ****************************/
  102.  
  103. /**
  104. Prints an error message and aborts the program. The error message is
  105. of the form "Error: ...", where the ... is specified by the \a format
  106. argument
  107.  
  108. @param format an error message format string (as with \c printf(3)).
  109. */
  110. extern void fatal_error(char* format, ...);
  111.  
  112. /**
  113. Replaces a file's extension, which is assumed to be everything after the
  114. last dot ('.') character.
  115.  
  116. @param file the name of a file
  117.  
  118. @param extn a new extension for \a file; should not include a dot (i.e.
  119. \c "jpg", not \c ".jpg") unless the new file extension should contain
  120. two dots.
  121.  
  122. @return Returns a new string formed as described above. If \a file does
  123. not have an extension, this function simply adds one.
  124. */
  125. extern char* replace_extension(const char* file, const char* extn);
  126.  
  127. /**
  128. A function that removes the path from a filename. Similar to the Unix
  129. basename command.
  130.  
  131. @param pathname a (full) path name
  132.  
  133. @return Returns the basename of \a pathname.
  134. */
  135. extern char* basename(const char* pathname);
  136.  
  137. /**
  138. Displays progress in the console with a spinning pinwheel. Every time this
  139. function is called, the state of the pinwheel is incremented. The pinwheel
  140. has four states that loop indefinitely: '|', '/', '-', '\'.
  141.  
  142. @param done if 0, this function simply increments the state of the pinwheel;
  143. otherwise it prints "done"
  144. */
  145. extern void progress(int done);
  146.  
  147. /**
  148. Erases a specified number of characters from a stream.
  149.  
  150. @param stream the stream from which to erase characters
  151. @param n the number of characters to erase
  152. */
  153. extern void erase_from_stream(FILE* stream, int n);
  154.  
  155. /**
  156. Doubles the size of an array with error checking
  157.  
  158. @param array pointer to an array whose size is to be doubled
  159. @param n number of elements allocated for \a array
  160. @param size size in bytes of elements in \a array
  161.  
  162. @return Returns the new number of elements allocated for \a array. If no
  163. memory is available, returns 0 and frees array.
  164. */
  165. extern int array_double(void** array, int n, int size);
  166.  
  167. /**
  168. Calculates the squared distance between two points.
  169.  
  170. @param p1 a point
  171. @param p2 another point
  172. */
  173. extern double dist_sq_2D(CvPoint2D64f p1, CvPoint2D64f p2);
  174.  
  175. /**
  176. Draws an x on an image.
  177.  
  178. @param img an image
  179. @param pt the center point of the x
  180. @param r the x's radius
  181. @param w the x's line weight
  182. @param color the color of the x
  183. */
  184. extern void draw_x(IplImage* img, CvPoint pt, int r, int w, CvScalar color);
  185.  
  186. /**
  187. Combines two images by scacking one on top of the other
  188.  
  189. @param img1 top image
  190. @param img2 bottom image
  191.  
  192. @return Returns the image resulting from stacking \a img1 on top if \a img2
  193. */
  194. extern IplImage* stack_imgs(IplImage* img1, IplImage* img2);
  195.  
  196. /**
  197. Allows user to view an array of images as a video. Keyboard controls
  198. are as follows:
  199.  
  200. <ul>
  201. <li>Space - start and pause playback</li>
  202. <li>Page Up - skip forward 10 frames</li>
  203. <li>Page Down - jump back 10 frames</li>
  204. <li>Right Arrow - skip forward 1 frame</li>
  205. <li>Left Arrow - jump back 1 frame</li>
  206. <li>Backspace - jump back to beginning</li>
  207. <li>Esc - exit playback</li>
  208. <li>Closing the window also exits playback</li>
  209. </ul>
  210.  
  211. @param imgs an array of images
  212. @param n number of images in \a imgs
  213. @param win_name name of window in which images are displayed
  214. */
  215. extern void vid_view(IplImage** imgs, int n, char* win_name);
  216.  
  217. /**
  218. Checks if a HighGUI window is still open or not
  219.  
  220. @param name the name of the window we're checking
  221.  
  222. @return Returns 1 if the window named \a name has been closed or 0 otherwise
  223. */
  224. extern int win_closed(char* name);
  225.  
  226. #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. #include "utils.h"
  10. #include "imgfeatures.h"
  11.  
  12. #include <cxcore.h>
  13.  
  14. #include <math.h>
  15.  
  16. static int import_oxfd_features(char*, struct feature**);
  17. static int export_oxfd_features(char*, struct feature*, int);
  18. static void draw_oxfd_features(IplImage*, struct feature*, int);
  19. static void draw_oxfd_feature(IplImage*, struct feature*, CvScalar);
  20.  
  21. static int import_lowe_features(char*, struct feature**);
  22. static int export_lowe_features(char*, struct feature*, int);
  23. static void draw_lowe_features(IplImage*, struct feature*, int);
  24. static void draw_lowe_feature(IplImage*, struct feature*, CvScalar);
  25.  
  26. /*
  27. Reads image features from file. The file should be formatted as from
  28. the code provided by the Visual Geometry Group at Oxford:
  29.  
  30. @param filename location of a file containing image features
  31. @param type determines how features are input. If \a type is FEATURE_OXFD,
  32. the input file is treated as if it is from the code provided by the VGG
  33. at Oxford:
  34.  
  35. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  36.  
  37. If \a type is FEATURE_LOWE, the input file is treated as if it is from
  38. David Lowe's SIFT code:
  39.  
  40. http://www.cs.ubc.ca/~lowe/keypoints
  41. @param features pointer to an array in which to store features
  42.  
  43. @return Returns the number of features imported from filename or -1 on error
  44. */
  45. int import_features(char* filename, int type, struct feature** feat)
  46. {
  47. int n;
  48.  
  49. switch (type)
  50. {
  51. case FEATURE_OXFD:
  52. n = import_oxfd_features(filename, feat);
  53. break;
  54. case FEATURE_LOWE:
  55. n = import_lowe_features(filename, feat);
  56. break;
  57. default:
  58. fprintf(stderr, "Warning: import_features(): unrecognized feature" \
  59. "type, %s, line %d\n", __FILE__, __LINE__);
  60. return -;
  61. }
  62.  
  63. if (n == -)
  64. fprintf(stderr, "Warning: unable to import features from %s," \
  65. " %s, line %d\n", filename, __FILE__, __LINE__);
  66. return n;
  67. }
  68.  
  69. /*
  70. Exports a feature set to a file formatted depending on the type of
  71. features, as specified in the feature struct's type field.
  72.  
  73. @param filename name of file to which to export features
  74. @param feat feature array
  75. @param n number of features
  76.  
  77. @return Returns 0 on success or 1 on error
  78. */
  79. int export_features(char* filename, struct feature* feat, int n)
  80. {
  81. int r, type;
  82.  
  83. if (n <= || !feat)
  84. {
  85. fprintf(stderr, "Warning: no features to export, %s line %d\n",
  86. __FILE__, __LINE__);
  87. return ;
  88. }
  89. type = feat[].type;
  90. switch (type)
  91. {
  92. case FEATURE_OXFD:
  93. r = export_oxfd_features(filename, feat, n);
  94. break;
  95. case FEATURE_LOWE:
  96. r = export_lowe_features(filename, feat, n);
  97. break;
  98. default:
  99. fprintf(stderr, "Warning: export_features(): unrecognized feature" \
  100. "type, %s, line %d\n", __FILE__, __LINE__);
  101. return -;
  102. }
  103.  
  104. if (r)
  105. fprintf(stderr, "Warning: unable to export features to %s," \
  106. " %s, line %d\n", filename, __FILE__, __LINE__);
  107. return r;
  108. }
  109.  
  110. /*
  111. Draws a set of features on an image
  112.  
  113. @param img image on which to draw features
  114. @param feat array of Oxford-type features
  115. @param n number of features
  116. */
  117. void draw_features(IplImage* img, struct feature* feat, int n)
  118. {
  119. int type;
  120.  
  121. if (n <= || !feat)
  122. {
  123. fprintf(stderr, "Warning: no features to draw, %s line %d\n",
  124. __FILE__, __LINE__);
  125. return;
  126. }
  127. type = feat[].type;
  128. switch (type)
  129. {
  130. case FEATURE_OXFD:
  131. draw_oxfd_features(img, feat, n);
  132. break;
  133. case FEATURE_LOWE:
  134. draw_lowe_features(img, feat, n);
  135. break;
  136. default:
  137. fprintf(stderr, "Warning: draw_features(): unrecognized feature" \
  138. " type, %s, line %d\n", __FILE__, __LINE__);
  139. break;
  140. }
  141. }
  142.  
  143. /*
  144. Calculates the squared Euclidian distance between two feature descriptors.
  145.  
  146. @param f1 first feature
  147. @param f2 second feature
  148.  
  149. @return Returns the squared Euclidian distance between the descriptors of
  150. f1 and f2.
  151. */
  152. double descr_dist_sq(struct feature* f1, struct feature* f2)
  153. {
  154. double diff, dsq = ;
  155. double* descr1, *descr2;
  156. int i, d;
  157.  
  158. d = f1->d;
  159. if (f2->d != d)
  160. return DBL_MAX;
  161. descr1 = f1->descr;
  162. descr2 = f2->descr;
  163.  
  164. for (i = ; i < d; i++)
  165. {
  166. diff = descr1[i] - descr2[i];
  167. dsq += diff*diff;
  168. }
  169. return dsq;
  170. }
  171.  
  172. /***************************** Local Functions *******************************/
  173.  
  174. /*
  175. Reads image features from file. The file should be formatted as from
  176. the code provided by the Visual Geometry Group at Oxford:
  177.  
  178. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  179.  
  180. @param filename location of a file containing image features
  181. @param features pointer to an array in which to store features
  182.  
  183. @return Returns the number of features imported from filename or -1 on error
  184. */
  185. static int import_oxfd_features(char* filename, struct feature** features)
  186. {
  187. struct feature* f;
  188. int i, j, n, d;
  189. double x, y, a, b, c, dv;
  190. FILE* file;
  191.  
  192. if (!features)
  193. fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
  194.  
  195. if (!(file = fopen(filename, "r")))
  196. {
  197. fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
  198. filename, __FILE__, __LINE__);
  199. return -;
  200. }
  201.  
  202. /* read dimension and number of features */
  203. if (fscanf(file, " %d %d ", &d, &n) != )
  204. {
  205. fprintf(stderr, "Warning: file read error, %s, line %d\n",
  206. __FILE__, __LINE__);
  207. return -;
  208. }
  209. if (d > FEATURE_MAX_D)
  210. {
  211. fprintf(stderr, "Warning: descriptor too long, %s, line %d\n",
  212. __FILE__, __LINE__);
  213. return -;
  214. }
  215.  
  216. f = calloc(n, sizeof(struct feature));
  217. for (i = ; i < n; i++)
  218. {
  219. /* read affine region parameters */
  220. if (fscanf(file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c) != )
  221. {
  222. fprintf(stderr, "Warning: error reading feature #%d, %s, line %d\n",
  223. i + , __FILE__, __LINE__);
  224. free(f);
  225. return -;
  226. }
  227. f[i].img_pt.x = f[i].x = x;
  228. f[i].img_pt.y = f[i].y = y;
  229. f[i].a = a;
  230. f[i].b = b;
  231. f[i].c = c;
  232. f[i].d = d;
  233. f[i].type = FEATURE_OXFD;
  234.  
  235. /* read descriptor */
  236. for (j = ; j < d; j++)
  237. {
  238. if (!fscanf(file, " %lf ", &dv))
  239. {
  240. fprintf(stderr, "Warning: error reading feature descriptor" \
  241. " #%d, %s, line %d\n", i + , __FILE__, __LINE__);
  242. free(f);
  243. return -;
  244. }
  245. f[i].descr[j] = dv;
  246. }
  247.  
  248. f[i].scl = f[i].ori = ;
  249. f[i].category = ;
  250. f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
  251. f[i].mdl_pt.x = f[i].mdl_pt.y = -;
  252. f[i].feature_data = NULL;
  253. }
  254.  
  255. if (fclose(file))
  256. {
  257. fprintf(stderr, "Warning: file close error, %s, line %d\n",
  258. __FILE__, __LINE__);
  259. free(f);
  260. return -;
  261. }
  262.  
  263. *features = f;
  264. return n;
  265. }
  266.  
  267. /*
  268. Exports a feature set to a file formatted as one from the code provided
  269. by the Visual Geometry Group at Oxford:
  270.  
  271. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  272.  
  273. @param filename name of file to which to export features
  274. @param feat feature array
  275. @param n number of features
  276.  
  277. @return Returns 0 on success or 1 on error
  278. */
  279. static int export_oxfd_features(char* filename, struct feature* feat, int n)
  280. {
  281. FILE* file;
  282. int i, j, d;
  283.  
  284. if (n <= )
  285. {
  286. fprintf(stderr, "Warning: feature count %d, %s, line %s\n",
  287. n, __FILE__, __LINE__);
  288. return ;
  289. }
  290. if (!(file = fopen(filename, "w")))
  291. {
  292. fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
  293. filename, __FILE__, __LINE__);
  294. return ;
  295. }
  296.  
  297. d = feat[].d;
  298. fprintf(file, "%d\n%d\n", d, n);
  299. for (i = ; i < n; i++)
  300. {
  301. fprintf(file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,
  302. feat[i].b, feat[i].c);
  303. for (j = ; j < d; j++)
  304. fprintf(file, " %f", feat[i].descr[j]);
  305. fprintf(file, "\n");
  306. }
  307.  
  308. if (fclose(file))
  309. {
  310. fprintf(stderr, "Warning: file close error, %s, line %d\n",
  311. __FILE__, __LINE__);
  312. return ;
  313. }
  314.  
  315. return ;
  316. }
  317.  
  318. /*
  319. Draws Oxford-type affine features
  320.  
  321. @param img image on which to draw features
  322. @param feat array of Oxford-type features
  323. @param n number of features
  324. */
  325. static void draw_oxfd_features(IplImage* img, struct feature* feat, int n)
  326. {
  327. CvScalar color = CV_RGB(, , );
  328. int i;
  329.  
  330. if (img->nChannels > )
  331. color = FEATURE_OXFD_COLOR;
  332. for (i = ; i < n; i++)
  333. draw_oxfd_feature(img, feat + i, color);
  334. }
  335.  
  336. /*
  337. Draws a single Oxford-type feature
  338.  
  339. @param img image on which to draw
  340. @param feat feature to be drawn
  341. @param color color in which to draw
  342. */
  343. static void draw_oxfd_feature(IplImage* img, struct feature* feat, CvScalar color)
  344. {
  345. double m[] = { feat->a, feat->b, feat->b, feat->c };
  346. double v[] = { };
  347. double e[] = { };
  348. CvMat M, V, E;
  349. double alpha, l1, l2;
  350.  
  351. /* compute axes and orientation of ellipse surrounding affine region */
  352. cvInitMatHeader(&M, , , CV_64FC1, m, CV_AUTOSTEP);
  353. cvInitMatHeader(&V, , , CV_64FC1, v, CV_AUTOSTEP);
  354. cvInitMatHeader(&E, , , CV_64FC1, e, CV_AUTOSTEP);
  355. cvEigenVV(&M, &V, &E, DBL_EPSILON, , );
  356. l1 = / sqrt(e[]);
  357. l2 = / sqrt(e[]);
  358. alpha = -atan2(v[], v[]);
  359. alpha *= / CV_PI;
  360.  
  361. cvEllipse(img, cvPoint(feat->x, feat->y), cvSize(l2, l1), alpha,
  362. , , CV_RGB(, , ), , , );
  363. cvEllipse(img, cvPoint(feat->x, feat->y), cvSize(l2, l1), alpha,
  364. , , color, , , );
  365. cvLine(img, cvPoint(feat->x + , feat->y), cvPoint(feat->x - , feat->y),
  366. color, , , );
  367. cvLine(img, cvPoint(feat->x, feat->y + ), cvPoint(feat->x, feat->y - ),
  368. color, , , );
  369. }
  370.  
  371. /*
  372. Reads image features from file. The file should be formatted as from
  373. the code provided by David Lowe:
  374.  
  375. http://www.cs.ubc.ca/~lowe/keypoints/
  376.  
  377. @param filename location of a file containing image features
  378. @param features pointer to an array in which to store features
  379.  
  380. @return Returns the number of features imported from filename or -1 on error
  381. */
  382. static int import_lowe_features(char* filename, struct feature** features)
  383. {
  384. struct feature* f;
  385. int i, j, n, d;
  386. double x, y, s, o, dv;
  387. FILE* file;
  388.  
  389. if (!features)
  390. fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
  391.  
  392. if (!(file = fopen(filename, "r")))
  393. {
  394. fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
  395. filename, __FILE__, __LINE__);
  396. return -;
  397. }
  398.  
  399. /* read number of features and dimension */
  400. if (fscanf(file, " %d %d ", &n, &d) != )
  401. {
  402. fprintf(stderr, "Warning: file read error, %s, line %d\n",
  403. __FILE__, __LINE__);
  404. return -;
  405. }
  406. if (d > FEATURE_MAX_D)
  407. {
  408. fprintf(stderr, "Warning: descriptor too long, %s, line %d\n",
  409. __FILE__, __LINE__);
  410. return -;
  411. }
  412.  
  413. f = calloc(n, sizeof(struct feature));
  414. for (i = ; i < n; i++)
  415. {
  416. /* read affine region parameters */
  417. if (fscanf(file, " %lf %lf %lf %lf ", &y, &x, &s, &o) != )
  418. {
  419. fprintf(stderr, "Warning: error reading feature #%d, %s, line %d\n",
  420. i + , __FILE__, __LINE__);
  421. free(f);
  422. return -;
  423. }
  424. f[i].img_pt.x = f[i].x = x;
  425. f[i].img_pt.y = f[i].y = y;
  426. f[i].scl = s;
  427. f[i].ori = o;
  428. f[i].d = d;
  429. f[i].type = FEATURE_LOWE;
  430.  
  431. /* read descriptor */
  432. for (j = ; j < d; j++)
  433. {
  434. if (!fscanf(file, " %lf ", &dv))
  435. {
  436. fprintf(stderr, "Warning: error reading feature descriptor" \
  437. " #%d, %s, line %d\n", i + , __FILE__, __LINE__);
  438. free(f);
  439. return -;
  440. }
  441. f[i].descr[j] = dv;
  442. }
  443.  
  444. f[i].a = f[i].b = f[i].c = ;
  445. f[i].category = ;
  446. f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
  447. f[i].mdl_pt.x = f[i].mdl_pt.y = -;
  448. }
  449.  
  450. if (fclose(file))
  451. {
  452. fprintf(stderr, "Warning: file close error, %s, line %d\n",
  453. __FILE__, __LINE__);
  454. free(f);
  455. return -;
  456. }
  457.  
  458. *features = f;
  459. return n;
  460. }
  461.  
  462. /*
  463. Exports a feature set to a file formatted as one from the code provided
  464. by David Lowe:
  465.  
  466. http://www.cs.ubc.ca/~lowe/keypoints/
  467.  
  468. @param filename name of file to which to export features
  469. @param feat feature array
  470. @param n number of features
  471.  
  472. @return Returns 0 on success or 1 on error
  473. */
  474. static int export_lowe_features(char* filename, struct feature* feat, int n)
  475. {
  476. FILE* file;
  477. int i, j, d;
  478.  
  479. if (n <= )
  480. {
  481. fprintf(stderr, "Warning: feature count %d, %s, line %s\n",
  482. n, __FILE__, __LINE__);
  483. return ;
  484. }
  485. if (!(file = fopen(filename, "w")))
  486. {
  487. fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
  488. filename, __FILE__, __LINE__);
  489. return ;
  490. }
  491.  
  492. d = feat[].d;
  493. fprintf(file, "%d %d\n", n, d);
  494. for (i = ; i < n; i++)
  495. {
  496. fprintf(file, "%f %f %f %f", feat[i].y, feat[i].x,
  497. feat[i].scl, feat[i].ori);
  498. for (j = ; j < d; j++)
  499. {
  500. /* write 20 descriptor values per line */
  501. if (j % == )
  502. fprintf(file, "\n");
  503. fprintf(file, " %d", (int)(feat[i].descr[j]));
  504. }
  505. fprintf(file, "\n");
  506. }
  507.  
  508. if (fclose(file))
  509. {
  510. fprintf(stderr, "Warning: file close error, %s, line %d\n",
  511. __FILE__, __LINE__);
  512. return ;
  513. }
  514.  
  515. return ;
  516. }
  517.  
  518. /*
  519. Draws Lowe-type features
  520.  
  521. @param img image on which to draw features
  522. @param feat array of Oxford-type features
  523. @param n number of features
  524. */
  525. static void draw_lowe_features(IplImage* img, struct feature* feat, int n)
  526. {
  527. CvScalar color = CV_RGB(, , );
  528. int i;
  529.  
  530. if (img->nChannels > )
  531. color = FEATURE_LOWE_COLOR;
  532. for (i = ; i < n; i++)
  533. draw_lowe_feature(img, feat + i, color);
  534. }
  535.  
  536. /*
  537. Draws a single Lowe-type feature
  538.  
  539. @param img image on which to draw
  540. @param feat feature to be drawn
  541. @param color color in which to draw
  542. */
  543. static void draw_lowe_feature(IplImage* img, struct feature* feat, CvScalar color)
  544. {
  545. int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;
  546. double scl, ori;
  547. double scale = 5.0;
  548. double hscale = 0.75;
  549. CvPoint start, end, h1, h2;
  550.  
  551. /* compute points for an arrow scaled and rotated by feat's scl and ori */
  552. start_x = cvRound(feat->x);
  553. start_y = cvRound(feat->y);
  554. scl = feat->scl;
  555. ori = feat->ori;
  556. len = cvRound(scl * scale);
  557. hlen = cvRound(scl * hscale);
  558. blen = len - hlen;
  559. end_x = cvRound(len * cos(ori)) + start_x;
  560. end_y = cvRound(len * -sin(ori)) + start_y;
  561. h1_x = cvRound(blen * cos(ori + CV_PI / 18.0)) + start_x;
  562. h1_y = cvRound(blen * -sin(ori + CV_PI / 18.0)) + start_y;
  563. h2_x = cvRound(blen * cos(ori - CV_PI / 18.0)) + start_x;
  564. h2_y = cvRound(blen * -sin(ori - CV_PI / 18.0)) + start_y;
  565. start = cvPoint(start_x, start_y);
  566. end = cvPoint(end_x, end_y);
  567. h1 = cvPoint(h1_x, h1_y);
  568. h2 = cvPoint(h2_x, h2_y);
  569.  
  570. cvLine(img, start, end, color, , , );
  571. cvLine(img, end, h1, color, , , );
  572. cvLine(img, end, h2, color, , , );
  573. }

main.cpp

  1. #include "opencv2/highgui/highgui.hpp"//这个是基本类库,高级图形用户接口,必须要引入
  2. #include "sift.h"//解决了没有sift_features函数的问题
  3. #include "imgfeatures.h"//解决了找不到export_features 和draw_features 的问题
  4. #include "utils.h"
  5.  
  6. int main(){
  7.  
  8. IplImage * img1 = cvLoadImage("a.png");
  9. IplImage * img2 = cvLoadImage("b.png");
  10.  
  11. IplImage *img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
  12. IplImage *img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
  13.  
  14. img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
  15. img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
  16.  
  17. //默认提取的是LOWE格式的SIFT特征点
  18. //提取并显示第1幅图片上的特征点
  19.  
  20. feature *feat1, *feat2;
  21.  
  22. int n1 = sift_features(img1, &feat1);//检测图1中的SIFT特征点,n1是图1的特征点个数
  23. export_features("feature1.txt", feat1, n1);//将特征向量数据写入到文件
  24. draw_features(img1_Feat, feat1, n1);//画出特征点
  25. cvNamedWindow("IMG1_FEAT");//创建窗口
  26. cvShowImage("IMG1_FEAT", img1_Feat);//显示
  27.  
  28. //提取并显示第2幅图片上的特征点
  29. int n2 = sift_features(img2, &feat2);//检测图2中的SIFT特征点,n2是图2的特征点个数
  30. export_features("feature2.txt", feat2, n2);//将特征向量数据写入到文件
  31. draw_features(img2_Feat, feat2, n2);//画出特征点
  32. cvNamedWindow("IMG2_FEAT");//创建窗口
  33. cvShowImage("IMG2_FEAT", img2_Feat);//显示
  34.  
  35. cvWaitKey();
  36.  
  37. }

sift.c

  1. /*
  2. Functions for detecting SIFT image features.
  3.  
  4. For more information, refer to:
  5.  
  6. Lowe, D. Distinctive image features from scale-invariant keypoints.
  7. <EM>International Journal of Computer Vision, 60</EM>, 2 (2004),
  8. pp.91--110.
  9.  
  10. Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
  11.  
  12. Note: The SIFT algorithm is patented in the United States and cannot be
  13. used in commercial products without a license from the University of
  14. British Columbia. For more information, refer to the file LICENSE.ubc
  15. that accompanied this distribution.
  16.  
  17. @version 1.1.2-20100521
  18. */
  19.  
  20. #include "sift.h"
  21. #include "imgfeatures.h"
  22. #include "utils.h"
  23.  
  24. #include <cxcore.h>
  25. #include <cv.h>
  26.  
  27. /************************* Local Function Prototypes *************************/
  28.  
  29. static IplImage* create_init_img(IplImage*, int, double);
  30. static IplImage* convert_to_gray32(IplImage*);
  31. static IplImage*** build_gauss_pyr(IplImage*, int, int, double);
  32. static IplImage* downsample(IplImage*);
  33. static IplImage*** build_dog_pyr(IplImage***, int, int);
  34. static CvSeq* scale_space_extrema(IplImage***, int, int, double, int, CvMemStorage*);
  35. static int is_extremum(IplImage***, int, int, int, int);
  36. static struct feature* interp_extremum(IplImage***, int, int, int, int, int, double);
  37. static void interp_step(IplImage***, int, int, int, int, double*, double*, double*);
  38. static CvMat* deriv_3D(IplImage***, int, int, int, int);
  39. static CvMat* hessian_3D(IplImage***, int, int, int, int);
  40. static double interp_contr(IplImage***, int, int, int, int, double, double, double);
  41. static struct feature* new_feature(void);
  42. static int is_too_edge_like(IplImage*, int, int, int);
  43. static void calc_feature_scales(CvSeq*, double, int);
  44. static void adjust_for_img_dbl(CvSeq*);
  45. static void calc_feature_oris(CvSeq*, IplImage***);
  46. static double* ori_hist(IplImage*, int, int, int, int, double);
  47. static int calc_grad_mag_ori(IplImage*, int, int, double*, double*);
  48. static void smooth_ori_hist(double*, int);
  49. static double dominant_ori(double*, int);
  50. static void add_good_ori_features(CvSeq*, double*, int, double, struct feature*);
  51. static struct feature* clone_feature(struct feature*);
  52. static void compute_descriptors(CvSeq*, IplImage***, int, int);
  53. static double*** descr_hist(IplImage*, int, int, double, double, int, int);
  54. static void interp_hist_entry(double***, double, double, double, double, int, int);
  55. static void hist_to_descr(double***, int, int, struct feature*);
  56. static void normalize_descr(struct feature*);
  57. static int feature_cmp(void*, void*, void*);
  58. static void release_descr_hist(double****, int);
  59. static void release_pyr(IplImage****, int, int);
  60.  
  61. /*********************** Functions prototyped in sift.h **********************/
  62.  
  63. /**
  64. Finds SIFT features in an image using default parameter values. All
  65. detected features are stored in the array pointed to by \a feat.
  66.  
  67. @param img the image in which to detect features
  68. @param feat a pointer to an array in which to store detected features
  69.  
  70. @return Returns the number of features stored in \a feat or -1 on failure
  71. @see _sift_features()
  72. */
  73. int sift_features(IplImage* img, struct feature** feat)
  74. {
  75. return _sift_features(img, feat, SIFT_INTVLS, SIFT_SIGMA, SIFT_CONTR_THR,
  76. SIFT_CURV_THR, SIFT_IMG_DBL, SIFT_DESCR_WIDTH,
  77. SIFT_DESCR_HIST_BINS);
  78. }
  79.  
  80. /**
  81. Finds SIFT features in an image using user-specified parameter values. All
  82. detected features are stored in the array pointed to by \a feat.
  83.  
  84. @param img the image in which to detect features
  85. @param fea a pointer to an array in which to store detected features
  86. @param intvls the number of intervals sampled per octave of scale space
  87. @param sigma the amount of Gaussian smoothing applied to each image level
  88. before building the scale space representation for an octave
  89. @param cont_thr a threshold on the value of the scale space function
  90. \f$\left|D(\hat{x})\right|\f$, where \f$\hat{x}\f$ is a vector specifying
  91. feature location and scale, used to reject unstable features; assumes
  92. pixel values in the range [0, 1]
  93. @param curv_thr threshold on a feature's ratio of principle curvatures
  94. used to reject features that are too edge-like
  95. @param img_dbl should be 1 if image doubling prior to scale space
  96. construction is desired or 0 if not
  97. @param descr_width the width, \f$n\f$, of the \f$n \times n\f$ array of
  98. orientation histograms used to compute a feature's descriptor
  99. @param descr_hist_bins the number of orientations in each of the
  100. histograms in the array used to compute a feature's descriptor
  101.  
  102. @return Returns the number of keypoints stored in \a feat or -1 on failure
  103. @see sift_keypoints()
  104. */
  105. int _sift_features(IplImage* img, struct feature** feat, int intvls,
  106. double sigma, double contr_thr, int curv_thr,
  107. int img_dbl, int descr_width, int descr_hist_bins)
  108. {
  109. IplImage* init_img;
  110. IplImage*** gauss_pyr, *** dog_pyr;
  111. CvMemStorage* storage;
  112. CvSeq* features;
  113. int octvs, i, n = ;
  114.  
  115. /* check arguments */
  116. if (!img)
  117. fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
  118.  
  119. if (!feat)
  120. fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
  121.  
  122. /* build scale space pyramid; smallest dimension of top level is ~4 pixels */
  123. init_img = create_init_img(img, img_dbl, sigma);
  124. octvs = log(MIN(init_img->width, init_img->height)) / log() - ;
  125. gauss_pyr = build_gauss_pyr(init_img, octvs, intvls, sigma);
  126. dog_pyr = build_dog_pyr(gauss_pyr, octvs, intvls);
  127.  
  128. storage = cvCreateMemStorage();
  129. features = scale_space_extrema(dog_pyr, octvs, intvls, contr_thr,
  130. curv_thr, storage);
  131. calc_feature_scales(features, sigma, intvls);
  132. if (img_dbl)
  133. adjust_for_img_dbl(features);
  134. calc_feature_oris(features, gauss_pyr);
  135. compute_descriptors(features, gauss_pyr, descr_width, descr_hist_bins);
  136.  
  137. /* sort features by decreasing scale and move from CvSeq to array */
  138. cvSeqSort(features, (CvCmpFunc)feature_cmp, NULL);
  139. n = features->total;
  140. *feat = calloc(n, sizeof(struct feature));
  141. *feat = cvCvtSeqToArray(features, *feat, CV_WHOLE_SEQ);
  142. for (i = ; i < n; i++)
  143. {
  144. free((*feat)[i].feature_data);
  145. (*feat)[i].feature_data = NULL;
  146. }
  147.  
  148. cvReleaseMemStorage(&storage);
  149. cvReleaseImage(&init_img);
  150. release_pyr(&gauss_pyr, octvs, intvls + );
  151. release_pyr(&dog_pyr, octvs, intvls + );
  152. return n;
  153. }
  154.  
  155. /************************ Functions prototyped here **************************/
  156.  
  157. /*
  158. Converts an image to 8-bit grayscale and Gaussian-smooths it. The image is
  159. optionally doubled in size prior to smoothing.
  160.  
  161. @param img input image
  162. @param img_dbl if true, image is doubled in size prior to smoothing
  163. @param sigma total std of Gaussian smoothing
  164. */
  165. static IplImage* create_init_img(IplImage* img, int img_dbl, double sigma)
  166. {
  167. IplImage* gray, *dbl;
  168. float sig_diff;
  169.  
  170. gray = convert_to_gray32(img);
  171. if (img_dbl)
  172. {
  173. sig_diff = sqrt(sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA * );
  174. dbl = cvCreateImage(cvSize(img->width * , img->height * ),
  175. IPL_DEPTH_32F, );
  176. cvResize(gray, dbl, CV_INTER_CUBIC);
  177. cvSmooth(dbl, dbl, CV_GAUSSIAN, , , sig_diff, sig_diff);
  178. cvReleaseImage(&gray);
  179. return dbl;
  180. }
  181. else
  182. {
  183. sig_diff = sqrt(sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA);
  184. cvSmooth(gray, gray, CV_GAUSSIAN, , , sig_diff, sig_diff);
  185. return gray;
  186. }
  187. }
  188.  
  189. /*
  190. Converts an image to 32-bit grayscale
  191.  
  192. @param img a 3-channel 8-bit color (BGR) or 8-bit gray image
  193.  
  194. @return Returns a 32-bit grayscale image
  195. */
  196. static IplImage* convert_to_gray32(IplImage* img)
  197. {
  198. IplImage* gray8, *gray32;
  199.  
  200. gray32 = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, );
  201. if (img->nChannels == )
  202. gray8 = cvClone(img);
  203. else
  204. {
  205. gray8 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, );
  206. cvCvtColor(img, gray8, CV_BGR2GRAY);
  207. }
  208. cvConvertScale(gray8, gray32, 1.0 / 255.0, );
  209.  
  210. cvReleaseImage(&gray8);
  211. return gray32;
  212. }
  213.  
  214. /*
  215. Builds Gaussian scale space pyramid from an image
  216.  
  217. @param base base image of the pyramid
  218. @param octvs number of octaves of scale space
  219. @param intvls number of intervals per octave
  220. @param sigma amount of Gaussian smoothing per octave
  221.  
  222. @return Returns a Gaussian scale space pyramid as an octvs x (intvls + 3) array
  223. */
  224. static IplImage*** build_gauss_pyr(IplImage* base, int octvs,
  225. int intvls, double sigma)
  226. {
  227. IplImage*** gauss_pyr;
  228. double* sig = calloc(intvls + , sizeof(double));
  229. double sig_total, sig_prev, k;
  230. int i, o;
  231.  
  232. gauss_pyr = calloc(octvs, sizeof(IplImage**));
  233. for (i = ; i < octvs; i++)
  234. gauss_pyr[i] = calloc(intvls + , sizeof(IplImage*));
  235.  
  236. /*
  237. precompute Gaussian sigmas using the following formula:
  238.  
  239. \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2
  240. */
  241. sig[] = sigma;
  242. k = pow(2.0, 1.0 / intvls);
  243. for (i = ; i < intvls + ; i++)
  244. {
  245. sig_prev = pow(k, i - ) * sigma;
  246. sig_total = sig_prev * k;
  247. sig[i] = sqrt(sig_total * sig_total - sig_prev * sig_prev);
  248. }
  249.  
  250. for (o = ; o < octvs; o++)
  251. for (i = ; i < intvls + ; i++)
  252. {
  253. if (o == && i == )
  254. gauss_pyr[o][i] = cvCloneImage(base);
  255.  
  256. /* base of new octvave is halved image from end of previous octave */
  257. else if (i == )
  258. gauss_pyr[o][i] = downsample(gauss_pyr[o - ][intvls]);
  259.  
  260. /* blur the current octave's last image to create the next one */
  261. else
  262. {
  263. gauss_pyr[o][i] = cvCreateImage(cvGetSize(gauss_pyr[o][i - ]),
  264. IPL_DEPTH_32F, );
  265. cvSmooth(gauss_pyr[o][i - ], gauss_pyr[o][i],
  266. CV_GAUSSIAN, , , sig[i], sig[i]);
  267. }
  268. }
  269.  
  270. free(sig);
  271. return gauss_pyr;
  272. }
  273.  
  274. /*
  275. Downsamples an image to a quarter of its size (half in each dimension)
  276. using nearest-neighbor interpolation
  277.  
  278. @param img an image
  279.  
  280. @return Returns an image whose dimensions are half those of img
  281. */
  282. static IplImage* downsample(IplImage* img)
  283. {
  284. IplImage* smaller = cvCreateImage(cvSize(img->width / , img->height / ),
  285. img->depth, img->nChannels);
  286. cvResize(img, smaller, CV_INTER_NN);
  287.  
  288. return smaller;
  289. }
  290.  
  291. /*
  292. Builds a difference of Gaussians scale space pyramid by subtracting adjacent
  293. intervals of a Gaussian pyramid
  294.  
  295. @param gauss_pyr Gaussian scale-space pyramid
  296. @param octvs number of octaves of scale space
  297. @param intvls number of intervals per octave
  298.  
  299. @return Returns a difference of Gaussians scale space pyramid as an
  300. octvs x (intvls + 2) array
  301. */
  302. static IplImage*** build_dog_pyr(IplImage*** gauss_pyr, int octvs, int intvls)
  303. {
  304. IplImage*** dog_pyr;
  305. int i, o;
  306.  
  307. dog_pyr = calloc(octvs, sizeof(IplImage**));
  308. for (i = ; i < octvs; i++)
  309. dog_pyr[i] = calloc(intvls + , sizeof(IplImage*));
  310.  
  311. for (o = ; o < octvs; o++)
  312. for (i = ; i < intvls + ; i++)
  313. {
  314. dog_pyr[o][i] = cvCreateImage(cvGetSize(gauss_pyr[o][i]),
  315. IPL_DEPTH_32F, );
  316. cvSub(gauss_pyr[o][i + ], gauss_pyr[o][i], dog_pyr[o][i], NULL);
  317. }
  318.  
  319. return dog_pyr;
  320. }
  321.  
  322. /*
  323. Detects features at extrema in DoG scale space. Bad features are discarded
  324. based on contrast and ratio of principal curvatures.
  325.  
  326. @param dog_pyr DoG scale space pyramid
  327. @param octvs octaves of scale space represented by dog_pyr
  328. @param intvls intervals per octave
  329. @param contr_thr low threshold on feature contrast
  330. @param curv_thr high threshold on feature ratio of principal curvatures
  331. @param storage memory storage in which to store detected features
  332.  
  333. @return Returns an array of detected features whose scales, orientations,
  334. and descriptors are yet to be determined.
  335. */
  336. static CvSeq* scale_space_extrema(IplImage*** dog_pyr, int octvs, int intvls,
  337. double contr_thr, int curv_thr,
  338. CvMemStorage* storage)
  339. {
  340. CvSeq* features;
  341. double prelim_contr_thr = 0.5 * contr_thr / intvls;
  342. struct feature* feat;
  343. struct detection_data* ddata;
  344. int o, i, r, c;
  345.  
  346. features = cvCreateSeq(, sizeof(CvSeq), sizeof(struct feature), storage);
  347. for (o = ; o < octvs; o++)
  348. for (i = ; i <= intvls; i++)
  349. for (r = SIFT_IMG_BORDER; r < dog_pyr[o][]->height - SIFT_IMG_BORDER; r++)
  350. for (c = SIFT_IMG_BORDER; c < dog_pyr[o][]->width - SIFT_IMG_BORDER; c++)
  351. /* perform preliminary check on contrast */
  352. if (ABS(pixval32f(dog_pyr[o][i], r, c)) > prelim_contr_thr)
  353. if (is_extremum(dog_pyr, o, i, r, c))
  354. {
  355. feat = interp_extremum(dog_pyr, o, i, r, c, intvls, contr_thr);
  356. if (feat)
  357. {
  358. ddata = feat_detection_data(feat);
  359. if (!is_too_edge_like(dog_pyr[ddata->octv][ddata->intvl],
  360. ddata->r, ddata->c, curv_thr))
  361. {
  362. cvSeqPush(features, feat);
  363. }
  364. else
  365. free(ddata);
  366. free(feat);
  367. }
  368. }
  369.  
  370. return features;
  371. }
  372.  
  373. /*
  374. Determines whether a pixel is a scale-space extremum by comparing it to it's
  375. 3x3x3 pixel neighborhood.
  376.  
  377. @param dog_pyr DoG scale space pyramid
  378. @param octv pixel's scale space octave
  379. @param intvl pixel's within-octave interval
  380. @param r pixel's image row
  381. @param c pixel's image col
  382.  
  383. @return Returns 1 if the specified pixel is an extremum (max or min) among
  384. it's 3x3x3 pixel neighborhood.
  385. */
  386. static int is_extremum(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
  387. {
  388. float val = pixval32f(dog_pyr[octv][intvl], r, c);
  389. int i, j, k;
  390.  
  391. /* check for maximum */
  392. if (val > )
  393. {
  394. for (i = -; i <= ; i++)
  395. for (j = -; j <= ; j++)
  396. for (k = -; k <= ; k++)
  397. if (val < pixval32f(dog_pyr[octv][intvl + i], r + j, c + k))
  398. return ;
  399. }
  400.  
  401. /* check for minimum */
  402. else
  403. {
  404. for (i = -; i <= ; i++)
  405. for (j = -; j <= ; j++)
  406. for (k = -; k <= ; k++)
  407. if (val > pixval32f(dog_pyr[octv][intvl + i], r + j, c + k))
  408. return ;
  409. }
  410.  
  411. return ;
  412. }
  413.  
  414. /*
  415. Interpolates a scale-space extremum's location and scale to subpixel
  416. accuracy to form an image feature. Rejects features with low contrast.
  417. Based on Section 4 of Lowe's paper.
  418.  
  419. @param dog_pyr DoG scale space pyramid
  420. @param octv feature's octave of scale space
  421. @param intvl feature's within-octave interval
  422. @param r feature's image row
  423. @param c feature's image column
  424. @param intvls total intervals per octave
  425. @param contr_thr threshold on feature contrast
  426.  
  427. @return Returns the feature resulting from interpolation of the given
  428. parameters or NULL if the given location could not be interpolated or
  429. if contrast at the interpolated loation was too low. If a feature is
  430. returned, its scale, orientation, and descriptor are yet to be determined.
  431. */
  432. static struct feature* interp_extremum(IplImage*** dog_pyr, int octv, int intvl,
  433. int r, int c, int intvls, double contr_thr)
  434. {
  435. struct feature* feat;
  436. struct detection_data* ddata;
  437. double xi, xr, xc, contr;
  438. int i = ;
  439.  
  440. while (i < SIFT_MAX_INTERP_STEPS)
  441. {
  442. interp_step(dog_pyr, octv, intvl, r, c, &xi, &xr, &xc);
  443. if (ABS(xi) < 0.5 && ABS(xr) < 0.5 && ABS(xc) < 0.5)
  444. break;
  445.  
  446. c += cvRound(xc);
  447. r += cvRound(xr);
  448. intvl += cvRound(xi);
  449.  
  450. if (intvl < ||
  451. intvl > intvls ||
  452. c < SIFT_IMG_BORDER ||
  453. r < SIFT_IMG_BORDER ||
  454. c >= dog_pyr[octv][]->width - SIFT_IMG_BORDER ||
  455. r >= dog_pyr[octv][]->height - SIFT_IMG_BORDER)
  456. {
  457. return NULL;
  458. }
  459.  
  460. i++;
  461. }
  462.  
  463. /* ensure convergence of interpolation */
  464. if (i >= SIFT_MAX_INTERP_STEPS)
  465. return NULL;
  466.  
  467. contr = interp_contr(dog_pyr, octv, intvl, r, c, xi, xr, xc);
  468. if (ABS(contr) < contr_thr / intvls)
  469. return NULL;
  470.  
  471. feat = new_feature();
  472. ddata = feat_detection_data(feat);
  473. feat->img_pt.x = feat->x = (c + xc) * pow(2.0, octv);
  474. feat->img_pt.y = feat->y = (r + xr) * pow(2.0, octv);
  475. ddata->r = r;
  476. ddata->c = c;
  477. ddata->octv = octv;
  478. ddata->intvl = intvl;
  479. ddata->subintvl = xi;
  480.  
  481. return feat;
  482. }
  483.  
  484. /*
  485. Performs one step of extremum interpolation. Based on Eqn. (3) in Lowe's
  486. paper.
  487.  
  488. @param dog_pyr difference of Gaussians scale space pyramid
  489. @param octv octave of scale space
  490. @param intvl interval being interpolated
  491. @param r row being interpolated
  492. @param c column being interpolated
  493. @param xi output as interpolated subpixel increment to interval
  494. @param xr output as interpolated subpixel increment to row
  495. @param xc output as interpolated subpixel increment to col
  496. */
  497.  
  498. static void interp_step(IplImage*** dog_pyr, int octv, int intvl, int r, int c,
  499. double* xi, double* xr, double* xc)
  500. {
  501. CvMat* dD, *H, *H_inv, X;
  502. double x[] = { };
  503.  
  504. dD = deriv_3D(dog_pyr, octv, intvl, r, c);
  505. H = hessian_3D(dog_pyr, octv, intvl, r, c);
  506. H_inv = cvCreateMat(, , CV_64FC1);
  507. cvInvert(H, H_inv, CV_SVD);
  508. cvInitMatHeader(&X, , , CV_64FC1, x, CV_AUTOSTEP);
  509. cvGEMM(H_inv, dD, -, NULL, , &X, );
  510.  
  511. cvReleaseMat(&dD);
  512. cvReleaseMat(&H);
  513. cvReleaseMat(&H_inv);
  514.  
  515. *xi = x[];
  516. *xr = x[];
  517. *xc = x[];
  518. }
  519.  
  520. /*
  521. Computes the partial derivatives in x, y, and scale of a pixel in the DoG
  522. scale space pyramid.
  523.  
  524. @param dog_pyr DoG scale space pyramid
  525. @param octv pixel's octave in dog_pyr
  526. @param intvl pixel's interval in octv
  527. @param r pixel's image row
  528. @param c pixel's image col
  529.  
  530. @return Returns the vector of partial derivatives for pixel I
  531. { dI/dx, dI/dy, dI/ds }^T as a CvMat*
  532. */
  533. static CvMat* deriv_3D(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
  534. {
  535. CvMat* dI;
  536. double dx, dy, ds;
  537.  
  538. dx = (pixval32f(dog_pyr[octv][intvl], r, c + ) -
  539. pixval32f(dog_pyr[octv][intvl], r, c - )) / 2.0;
  540. dy = (pixval32f(dog_pyr[octv][intvl], r + , c) -
  541. pixval32f(dog_pyr[octv][intvl], r - , c)) / 2.0;
  542. ds = (pixval32f(dog_pyr[octv][intvl + ], r, c) -
  543. pixval32f(dog_pyr[octv][intvl - ], r, c)) / 2.0;
  544.  
  545. dI = cvCreateMat(, , CV_64FC1);
  546. cvmSet(dI, , , dx);
  547. cvmSet(dI, , , dy);
  548. cvmSet(dI, , , ds);
  549.  
  550. return dI;
  551. }
  552.  
  553. /*
  554. Computes the 3D Hessian matrix for a pixel in the DoG scale space pyramid.
  555.  
  556. @param dog_pyr DoG scale space pyramid
  557. @param octv pixel's octave in dog_pyr
  558. @param intvl pixel's interval in octv
  559. @param r pixel's image row
  560. @param c pixel's image col
  561.  
  562. @return Returns the Hessian matrix (below) for pixel I as a CvMat*
  563.  
  564. / Ixx Ixy Ixs \ <BR>
  565. | Ixy Iyy Iys | <BR>
  566. \ Ixs Iys Iss /
  567. */
  568. static CvMat* hessian_3D(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
  569. {
  570. CvMat* H;
  571. double v, dxx, dyy, dss, dxy, dxs, dys;
  572.  
  573. v = pixval32f(dog_pyr[octv][intvl], r, c);
  574. dxx = (pixval32f(dog_pyr[octv][intvl], r, c + ) +
  575. pixval32f(dog_pyr[octv][intvl], r, c - ) - * v);
  576. dyy = (pixval32f(dog_pyr[octv][intvl], r + , c) +
  577. pixval32f(dog_pyr[octv][intvl], r - , c) - * v);
  578. dss = (pixval32f(dog_pyr[octv][intvl + ], r, c) +
  579. pixval32f(dog_pyr[octv][intvl - ], r, c) - * v);
  580. dxy = (pixval32f(dog_pyr[octv][intvl], r + , c + ) -
  581. pixval32f(dog_pyr[octv][intvl], r + , c - ) -
  582. pixval32f(dog_pyr[octv][intvl], r - , c + ) +
  583. pixval32f(dog_pyr[octv][intvl], r - , c - )) / 4.0;
  584. dxs = (pixval32f(dog_pyr[octv][intvl + ], r, c + ) -
  585. pixval32f(dog_pyr[octv][intvl + ], r, c - ) -
  586. pixval32f(dog_pyr[octv][intvl - ], r, c + ) +
  587. pixval32f(dog_pyr[octv][intvl - ], r, c - )) / 4.0;
  588. dys = (pixval32f(dog_pyr[octv][intvl + ], r + , c) -
  589. pixval32f(dog_pyr[octv][intvl + ], r - , c) -
  590. pixval32f(dog_pyr[octv][intvl - ], r + , c) +
  591. pixval32f(dog_pyr[octv][intvl - ], r - , c)) / 4.0;
  592.  
  593. H = cvCreateMat(, , CV_64FC1);
  594. cvmSet(H, , , dxx);
  595. cvmSet(H, , , dxy);
  596. cvmSet(H, , , dxs);
  597. cvmSet(H, , , dxy);
  598. cvmSet(H, , , dyy);
  599. cvmSet(H, , , dys);
  600. cvmSet(H, , , dxs);
  601. cvmSet(H, , , dys);
  602. cvmSet(H, , , dss);
  603.  
  604. return H;
  605. }
  606.  
  607. /*
  608. Calculates interpolated pixel contrast. Based on Eqn. (3) in Lowe's paper.
  609.  
  610. @param dog_pyr difference of Gaussians scale space pyramid
  611. @param octv octave of scale space
  612. @param intvl within-octave interval
  613. @param r pixel row
  614. @param c pixel column
  615. @param xi interpolated subpixel increment to interval
  616. @param xr interpolated subpixel increment to row
  617. @param xc interpolated subpixel increment to col
  618.  
  619. @param Returns interpolated contrast.
  620. */
  621. static double interp_contr(IplImage*** dog_pyr, int octv, int intvl, int r,
  622. int c, double xi, double xr, double xc)
  623. {
  624. CvMat* dD, X, T;
  625. double t[], x[] = { xc, xr, xi };
  626.  
  627. cvInitMatHeader(&X, , , CV_64FC1, x, CV_AUTOSTEP);
  628. cvInitMatHeader(&T, , , CV_64FC1, t, CV_AUTOSTEP);
  629. dD = deriv_3D(dog_pyr, octv, intvl, r, c);
  630. cvGEMM(dD, &X, , NULL, , &T, CV_GEMM_A_T);
  631. cvReleaseMat(&dD);
  632.  
  633. return pixval32f(dog_pyr[octv][intvl], r, c) + t[] * 0.5;
  634. }
  635.  
  636. /*
  637. Allocates and initializes a new feature
  638.  
  639. @return Returns a pointer to the new feature
  640. */
  641. static struct feature* new_feature(void)
  642. {
  643. struct feature* feat;
  644. struct detection_data* ddata;
  645.  
  646. feat = malloc(sizeof(struct feature));
  647. memset(feat, , sizeof(struct feature));
  648. ddata = malloc(sizeof(struct detection_data));
  649. memset(ddata, , sizeof(struct detection_data));
  650. feat->feature_data = ddata;
  651. feat->type = FEATURE_LOWE;
  652.  
  653. return feat;
  654. }
  655.  
  656. /*
  657. Determines whether a feature is too edge like to be stable by computing the
  658. ratio of principal curvatures at that feature. Based on Section 4.1 of
  659. Lowe's paper.
  660.  
  661. @param dog_img image from the DoG pyramid in which feature was detected
  662. @param r feature row
  663. @param c feature col
  664. @param curv_thr high threshold on ratio of principal curvatures
  665.  
  666. @return Returns 0 if the feature at (r,c) in dog_img is sufficiently
  667. corner-like or 1 otherwise.
  668. */
  669. static int is_too_edge_like(IplImage* dog_img, int r, int c, int curv_thr)
  670. {
  671. double d, dxx, dyy, dxy, tr, det;
  672.  
  673. /* principal curvatures are computed using the trace and det of Hessian */
  674. d = pixval32f(dog_img, r, c);
  675. dxx = pixval32f(dog_img, r, c + ) + pixval32f(dog_img, r, c - ) - * d;
  676. dyy = pixval32f(dog_img, r + , c) + pixval32f(dog_img, r - , c) - * d;
  677. dxy = (pixval32f(dog_img, r + , c + ) - pixval32f(dog_img, r + , c - ) -
  678. pixval32f(dog_img, r - , c + ) + pixval32f(dog_img, r - , c - )) / 4.0;
  679. tr = dxx + dyy;
  680. det = dxx * dyy - dxy * dxy;
  681.  
  682. /* negative determinant -> curvatures have different signs; reject feature */
  683. if (det <= )
  684. return ;
  685.  
  686. if (tr * tr / det < (curv_thr + 1.0)*(curv_thr + 1.0) / curv_thr)
  687. return ;
  688. return ;
  689. }
  690.  
  691. /*
  692. Calculates characteristic scale for each feature in an array.
  693.  
  694. @param features array of features
  695. @param sigma amount of Gaussian smoothing per octave of scale space
  696. @param intvls intervals per octave of scale space
  697. */
  698. static void calc_feature_scales(CvSeq* features, double sigma, int intvls)
  699. {
  700. struct feature* feat;
  701. struct detection_data* ddata;
  702. double intvl;
  703. int i, n;
  704.  
  705. n = features->total;
  706. for (i = ; i < n; i++)
  707. {
  708. feat = CV_GET_SEQ_ELEM(struct feature, features, i);
  709. ddata = feat_detection_data(feat);
  710. intvl = ddata->intvl + ddata->subintvl;
  711. feat->scl = sigma * pow(2.0, ddata->octv + intvl / intvls);
  712. ddata->scl_octv = sigma * pow(2.0, intvl / intvls);
  713. }
  714. }
  715.  
  716. /*
  717. Halves feature coordinates and scale in case the input image was doubled
  718. prior to scale space construction.
  719.  
  720. @param features array of features
  721. */
  722. static void adjust_for_img_dbl(CvSeq* features)
  723. {
  724. struct feature* feat;
  725. int i, n;
  726.  
  727. n = features->total;
  728. for (i = ; i < n; i++)
  729. {
  730. feat = CV_GET_SEQ_ELEM(struct feature, features, i);
  731. feat->x /= 2.0;
  732. feat->y /= 2.0;
  733. feat->scl /= 2.0;
  734. feat->img_pt.x /= 2.0;
  735. feat->img_pt.y /= 2.0;
  736. }
  737. }
  738.  
  739. /*
  740. Computes a canonical orientation for each image feature in an array. Based
  741. on Section 5 of Lowe's paper. This function adds features to the array when
  742. there is more than one dominant orientation at a given feature location.
  743.  
  744. @param features an array of image features
  745. @param gauss_pyr Gaussian scale space pyramid
  746. */
  747. static void calc_feature_oris(CvSeq* features, IplImage*** gauss_pyr)
  748. {
  749. struct feature* feat;
  750. struct detection_data* ddata;
  751. double* hist;
  752. double omax;
  753. int i, j, n = features->total;
  754.  
  755. for (i = ; i < n; i++)
  756. {
  757. feat = malloc(sizeof(struct feature));
  758. cvSeqPopFront(features, feat);
  759. ddata = feat_detection_data(feat);
  760. hist = ori_hist(gauss_pyr[ddata->octv][ddata->intvl],
  761. ddata->r, ddata->c, SIFT_ORI_HIST_BINS,
  762. cvRound(SIFT_ORI_RADIUS * ddata->scl_octv),
  763. SIFT_ORI_SIG_FCTR * ddata->scl_octv);
  764. for (j = ; j < SIFT_ORI_SMOOTH_PASSES; j++)
  765. smooth_ori_hist(hist, SIFT_ORI_HIST_BINS);
  766. omax = dominant_ori(hist, SIFT_ORI_HIST_BINS);
  767. add_good_ori_features(features, hist, SIFT_ORI_HIST_BINS,
  768. omax * SIFT_ORI_PEAK_RATIO, feat);
  769. free(ddata);
  770. free(feat);
  771. free(hist);
  772. }
  773. }
  774.  
  775. /*
  776. Computes a gradient orientation histogram at a specified pixel.
  777.  
  778. @param img image
  779. @param r pixel row
  780. @param c pixel col
  781. @param n number of histogram bins
  782. @param rad radius of region over which histogram is computed
  783. @param sigma std for Gaussian weighting of histogram entries
  784.  
  785. @return Returns an n-element array containing an orientation histogram
  786. representing orientations between 0 and 2 PI.
  787. */
  788. static double* ori_hist(IplImage* img, int r, int c, int n, int rad, double sigma)
  789. {
  790. double* hist;
  791. double mag, ori, w, exp_denom, PI2 = CV_PI * 2.0;
  792. int bin, i, j;
  793.  
  794. hist = calloc(n, sizeof(double));
  795. exp_denom = 2.0 * sigma * sigma;
  796. for (i = -rad; i <= rad; i++)
  797. for (j = -rad; j <= rad; j++)
  798. if (calc_grad_mag_ori(img, r + i, c + j, &mag, &ori))
  799. {
  800. w = exp(-(i*i + j*j) / exp_denom);
  801. bin = cvRound(n * (ori + CV_PI) / PI2);
  802. bin = (bin < n) ? bin : ;
  803. hist[bin] += w * mag;
  804. }
  805.  
  806. return hist;
  807. }
  808.  
  809. /*
  810. Calculates the gradient magnitude and orientation at a given pixel.
  811.  
  812. @param img image
  813. @param r pixel row
  814. @param c pixel col
  815. @param mag output as gradient magnitude at pixel (r,c)
  816. @param ori output as gradient orientation at pixel (r,c)
  817.  
  818. @return Returns 1 if the specified pixel is a valid one and sets mag and
  819. ori accordingly; otherwise returns 0
  820. */
  821. static int calc_grad_mag_ori(IplImage* img, int r, int c, double* mag, double* ori)
  822. {
  823. double dx, dy;
  824.  
  825. if (r > && r < img->height - && c > && c < img->width - )
  826. {
  827. dx = pixval32f(img, r, c + ) - pixval32f(img, r, c - );
  828. dy = pixval32f(img, r - , c) - pixval32f(img, r + , c);
  829. *mag = sqrt(dx*dx + dy*dy);
  830. *ori = atan2(dy, dx);
  831. return ;
  832. }
  833.  
  834. else
  835. return ;
  836. }
  837.  
  838. /*
  839. Gaussian smooths an orientation histogram.
  840.  
  841. @param hist an orientation histogram
  842. @param n number of bins
  843. */
  844. static void smooth_ori_hist(double* hist, int n)
  845. {
  846. double prev, tmp, h0 = hist[];
  847. int i;
  848.  
  849. prev = hist[n - ];
  850. for (i = ; i < n; i++)
  851. {
  852. tmp = hist[i];
  853. hist[i] = 0.25 * prev + 0.5 * hist[i] +
  854. 0.25 * ((i + == n) ? h0 : hist[i + ]);
  855. prev = tmp;
  856. }
  857. }
  858.  
  859. /*
  860. Finds the magnitude of the dominant orientation in a histogram
  861.  
  862. @param hist an orientation histogram
  863. @param n number of bins
  864.  
  865. @return Returns the value of the largest bin in hist
  866. */
  867. static double dominant_ori(double* hist, int n)
  868. {
  869. double omax;
  870. int maxbin, i;
  871.  
  872. omax = hist[];
  873. maxbin = ;
  874. for (i = ; i < n; i++)
  875. if (hist[i] > omax)
  876. {
  877. omax = hist[i];
  878. maxbin = i;
  879. }
  880. return omax;
  881. }
  882.  
  883. /*
  884. Interpolates a histogram peak from left, center, and right values
  885. */
  886. #define interp_hist_peak( l, c, r ) ( 0.5 * ((l)-(r)) / ((l) - 2.0*(c) + (r)) )
  887.  
  888. /*
  889. Adds features to an array for every orientation in a histogram greater than
  890. a specified threshold.
  891.  
  892. @param features new features are added to the end of this array
  893. @param hist orientation histogram
  894. @param n number of bins in hist
  895. @param mag_thr new features are added for entries in hist greater than this
  896. @param feat new features are clones of this with different orientations
  897. */
  898. static void add_good_ori_features(CvSeq* features, double* hist, int n,
  899. double mag_thr, struct feature* feat)
  900. {
  901. struct feature* new_feat;
  902. double bin, PI2 = CV_PI * 2.0;
  903. int l, r, i;
  904.  
  905. for (i = ; i < n; i++)
  906. {
  907. l = (i == ) ? n - : i - ;
  908. r = (i + ) % n;
  909.  
  910. if (hist[i] > hist[l] && hist[i] > hist[r] && hist[i] >= mag_thr)
  911. {
  912. bin = i + interp_hist_peak(hist[l], hist[i], hist[r]);
  913. bin = (bin < ) ? n + bin : (bin >= n) ? bin - n : bin;
  914. new_feat = clone_feature(feat);
  915. new_feat->ori = ((PI2 * bin) / n) - CV_PI;
  916. cvSeqPush(features, new_feat);
  917. free(new_feat);
  918. }
  919. }
  920. }
  921.  
  922. /*
  923. Makes a deep copy of a feature
  924.  
  925. @param feat feature to be cloned
  926.  
  927. @return Returns a deep copy of feat
  928. */
  929. static struct feature* clone_feature(struct feature* feat)
  930. {
  931. struct feature* new_feat;
  932. struct detection_data* ddata;
  933.  
  934. new_feat = new_feature();
  935. ddata = feat_detection_data(new_feat);
  936. memcpy(new_feat, feat, sizeof(struct feature));
  937. memcpy(ddata, feat_detection_data(feat), sizeof(struct detection_data));
  938. new_feat->feature_data = ddata;
  939.  
  940. return new_feat;
  941. }
  942.  
  943. /*
  944. Computes feature descriptors for features in an array. Based on Section 6
  945. of Lowe's paper.
  946.  
  947. @param features array of features
  948. @param gauss_pyr Gaussian scale space pyramid
  949. @param d width of 2D array of orientation histograms
  950. @param n number of bins per orientation histogram
  951. */
  952. static void compute_descriptors(CvSeq* features, IplImage*** gauss_pyr, int d, int n)
  953. {
  954. struct feature* feat;
  955. struct detection_data* ddata;
  956. double*** hist;
  957. int i, k = features->total;
  958.  
  959. for (i = ; i < k; i++)
  960. {
  961. feat = CV_GET_SEQ_ELEM(struct feature, features, i);
  962. ddata = feat_detection_data(feat);
  963. hist = descr_hist(gauss_pyr[ddata->octv][ddata->intvl], ddata->r,
  964. ddata->c, feat->ori, ddata->scl_octv, d, n);
  965. hist_to_descr(hist, d, n, feat);
  966. release_descr_hist(&hist, d);
  967. }
  968. }
  969.  
  970. /*
  971. Computes the 2D array of orientation histograms that form the feature
  972. descriptor. Based on Section 6.1 of Lowe's paper.
  973.  
  974. @param img image used in descriptor computation
  975. @param r row coord of center of orientation histogram array
  976. @param c column coord of center of orientation histogram array
  977. @param ori canonical orientation of feature whose descr is being computed
  978. @param scl scale relative to img of feature whose descr is being computed
  979. @param d width of 2d array of orientation histograms
  980. @param n bins per orientation histogram
  981.  
  982. @return Returns a d x d array of n-bin orientation histograms.
  983. */
  984. static double*** descr_hist(IplImage* img, int r, int c, double ori,
  985. double scl, int d, int n)
  986. {
  987. double*** hist;
  988. double cos_t, sin_t, hist_width, exp_denom, r_rot, c_rot, grad_mag,
  989. grad_ori, w, rbin, cbin, obin, bins_per_rad, PI2 = 2.0 * CV_PI;
  990. int radius, i, j;
  991.  
  992. hist = calloc(d, sizeof(double**));
  993. for (i = ; i < d; i++)
  994. {
  995. hist[i] = calloc(d, sizeof(double*));
  996. for (j = ; j < d; j++)
  997. hist[i][j] = calloc(n, sizeof(double));
  998. }
  999.  
  1000. cos_t = cos(ori);
  1001. sin_t = sin(ori);
  1002. bins_per_rad = n / PI2;
  1003. exp_denom = d * d * 0.5;
  1004. hist_width = SIFT_DESCR_SCL_FCTR * scl;
  1005. radius = hist_width * sqrt() * (d + 1.0) * 0.5 + 0.5;
  1006. for (i = -radius; i <= radius; i++)
  1007. for (j = -radius; j <= radius; j++)
  1008. {
  1009. /*
  1010. Calculate sample's histogram array coords rotated relative to ori.
  1011. Subtract 0.5 so samples that fall e.g. in the center of row 1 (i.e.
  1012. r_rot = 1.5) have full weight placed in row 1 after interpolation.
  1013. */
  1014. c_rot = (j * cos_t - i * sin_t) / hist_width;
  1015. r_rot = (j * sin_t + i * cos_t) / hist_width;
  1016. rbin = r_rot + d / - 0.5;
  1017. cbin = c_rot + d / - 0.5;
  1018.  
  1019. if (rbin > -1.0 && rbin < d && cbin > -1.0 && cbin < d)
  1020. if (calc_grad_mag_ori(img, r + i, c + j, &grad_mag, &grad_ori))
  1021. {
  1022. grad_ori -= ori;
  1023. while (grad_ori < 0.0)
  1024. grad_ori += PI2;
  1025. while (grad_ori >= PI2)
  1026. grad_ori -= PI2;
  1027.  
  1028. obin = grad_ori * bins_per_rad;
  1029. w = exp(-(c_rot * c_rot + r_rot * r_rot) / exp_denom);
  1030. interp_hist_entry(hist, rbin, cbin, obin, grad_mag * w, d, n);
  1031. }
  1032. }
  1033.  
  1034. return hist;
  1035. }
  1036.  
  1037. /*
  1038. Interpolates an entry into the array of orientation histograms that form
  1039. the feature descriptor.
  1040.  
  1041. @param hist 2D array of orientation histograms
  1042. @param rbin sub-bin row coordinate of entry
  1043. @param cbin sub-bin column coordinate of entry
  1044. @param obin sub-bin orientation coordinate of entry
  1045. @param mag size of entry
  1046. @param d width of 2D array of orientation histograms
  1047. @param n number of bins per orientation histogram
  1048. */
  1049. static void interp_hist_entry(double*** hist, double rbin, double cbin,
  1050. double obin, double mag, int d, int n)
  1051. {
  1052. double d_r, d_c, d_o, v_r, v_c, v_o;
  1053. double** row, *h;
  1054. int r0, c0, o0, rb, cb, ob, r, c, o;
  1055.  
  1056. r0 = cvFloor(rbin);
  1057. c0 = cvFloor(cbin);
  1058. o0 = cvFloor(obin);
  1059. d_r = rbin - r0;
  1060. d_c = cbin - c0;
  1061. d_o = obin - o0;
  1062.  
  1063. /*
  1064. The entry is distributed into up to 8 bins. Each entry into a bin
  1065. is multiplied by a weight of 1 - d for each dimension, where d is the
  1066. distance from the center value of the bin measured in bin units.
  1067. */
  1068. for (r = ; r <= ; r++)
  1069. {
  1070. rb = r0 + r;
  1071. if (rb >= && rb < d)
  1072. {
  1073. v_r = mag * ((r == ) ? 1.0 - d_r : d_r);
  1074. row = hist[rb];
  1075. for (c = ; c <= ; c++)
  1076. {
  1077. cb = c0 + c;
  1078. if (cb >= && cb < d)
  1079. {
  1080. v_c = v_r * ((c == ) ? 1.0 - d_c : d_c);
  1081. h = row[cb];
  1082. for (o = ; o <= ; o++)
  1083. {
  1084. ob = (o0 + o) % n;
  1085. v_o = v_c * ((o == ) ? 1.0 - d_o : d_o);
  1086. h[ob] += v_o;
  1087. }
  1088. }
  1089. }
  1090. }
  1091. }
  1092. }
  1093.  
  1094. /*
  1095. Converts the 2D array of orientation histograms into a feature's descriptor
  1096. vector.
  1097.  
  1098. @param hist 2D array of orientation histograms
  1099. @param d width of hist
  1100. @param n bins per histogram
  1101. @param feat feature into which to store descriptor
  1102. */
  1103. static void hist_to_descr(double*** hist, int d, int n, struct feature* feat)
  1104. {
  1105. int int_val, i, r, c, o, k = ;
  1106.  
  1107. for (r = ; r < d; r++)
  1108. for (c = ; c < d; c++)
  1109. for (o = ; o < n; o++)
  1110. feat->descr[k++] = hist[r][c][o];
  1111.  
  1112. feat->d = k;
  1113. normalize_descr(feat);
  1114. for (i = ; i < k; i++)
  1115. if (feat->descr[i] > SIFT_DESCR_MAG_THR)
  1116. feat->descr[i] = SIFT_DESCR_MAG_THR;
  1117. normalize_descr(feat);
  1118.  
  1119. /* convert floating-point descriptor to integer valued descriptor */
  1120. for (i = ; i < k; i++)
  1121. {
  1122. int_val = SIFT_INT_DESCR_FCTR * feat->descr[i];
  1123. feat->descr[i] = MIN(, int_val);
  1124. }
  1125. }
  1126.  
  1127. /*
  1128. Normalizes a feature's descriptor vector to unitl length
  1129.  
  1130. @param feat feature
  1131. */
  1132. static void normalize_descr(struct feature* feat)
  1133. {
  1134. double cur, len_inv, len_sq = 0.0;
  1135. int i, d = feat->d;
  1136.  
  1137. for (i = ; i < d; i++)
  1138. {
  1139. cur = feat->descr[i];
  1140. len_sq += cur*cur;
  1141. }
  1142. len_inv = 1.0 / sqrt(len_sq);
  1143. for (i = ; i < d; i++)
  1144. feat->descr[i] *= len_inv;
  1145. }
  1146.  
  1147. /*
  1148. Compares features for a decreasing-scale ordering. Intended for use with
  1149. CvSeqSort
  1150.  
  1151. @param feat1 first feature
  1152. @param feat2 second feature
  1153. @param param unused
  1154.  
  1155. @return Returns 1 if feat1's scale is greater than feat2's, -1 if vice versa,
  1156. and 0 if their scales are equal
  1157. */
  1158. static int feature_cmp(void* feat1, void* feat2, void* param)
  1159. {
  1160. struct feature* f1 = (struct feature*) feat1;
  1161. struct feature* f2 = (struct feature*) feat2;
  1162.  
  1163. if (f1->scl < f2->scl)
  1164. return ;
  1165. if (f1->scl > f2->scl)
  1166. return -;
  1167. return ;
  1168. }
  1169.  
  1170. /*
  1171. De-allocates memory held by a descriptor histogram
  1172.  
  1173. @param hist pointer to a 2D array of orientation histograms
  1174. @param d width of hist
  1175. */
  1176. static void release_descr_hist(double**** hist, int d)
  1177. {
  1178. int i, j;
  1179.  
  1180. for (i = ; i < d; i++)
  1181. {
  1182. for (j = ; j < d; j++)
  1183. free((*hist)[i][j]);
  1184. free((*hist)[i]);
  1185. }
  1186. free(*hist);
  1187. *hist = NULL;
  1188. }
  1189.  
  1190. /*
  1191. De-allocates memory held by a scale space pyramid
  1192.  
  1193. @param pyr scale space pyramid
  1194. @param octvs number of octaves of scale space
  1195. @param n number of images per octave
  1196. */
  1197. static void release_pyr(IplImage**** pyr, int octvs, int n)
  1198. {
  1199. int i, j;
  1200. for (i = ; i < octvs; i++)
  1201. {
  1202. for (j = ; j < n; j++)
  1203. cvReleaseImage(&(*pyr)[i][j]);
  1204. free((*pyr)[i]);
  1205. }
  1206. free(*pyr);
  1207. *pyr = NULL;
  1208. }

utils.c

/*
Miscellaneous utility functions. Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu> @version 1.1.2-20100521
*/ #include "utils.h"
#include <stdarg.h> #include <cv.h>
#include <cxcore.h>
#include <highgui.h> #include <errno.h>
#include <string.h>
#include <stdlib.h> /*************************** Function Definitions ****************************/ /*
Prints an error message and aborts the program. The error message is
of the form "Error: ...", where the ... is specified by the \a format
argument @param format an error message format string (as with \c printf(3)).
*/
void fatal_error(char* format, ...)
{
va_list ap; fprintf(stderr, "Error: "); va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, "\n");
abort();
} /*
Replaces a file's extension, which is assumed to be everything after the
last dot ('.') character. @param file the name of a file @param extn a new extension for \a file; should not include a dot (i.e.
\c "jpg", not \c ".jpg") unless the new file extension should contain
two dots. @return Returns a new string formed as described above. If \a file does
not have an extension, this function simply adds one.
*/
char* replace_extension(const char* file, const char* extn)
{
char* new_file, *lastdot; new_file = calloc(strlen(file) + strlen(extn) + , sizeof(char));
strcpy(new_file, file);
lastdot = strrchr(new_file, '.');
if (lastdot)
*(lastdot + ) = '\0';
else
strcat(new_file, ".");
strcat(new_file, extn); return new_file;
} /*
A function that removes the path from a filename. Similar to the Unix
basename command. @param pathname a (full) path name @return Returns the basename of \a pathname.
*/
char* basename(const char* pathname)
{
char* base, *last_slash; last_slash = strrchr(pathname, '/');
if (!last_slash)
{
base = calloc(strlen(pathname) + , sizeof(char));
strcpy(base, pathname);
}
else
{
base = calloc(strlen(last_slash++), sizeof(char));
strcpy(base, last_slash);
} return base;
} /*
Displays progress in the console with a spinning pinwheel. Every time this
function is called, the state of the pinwheel is incremented. The pinwheel
has four states that loop indefinitely: '|', '/', '-', '\'. @param done if 0, this function simply increments the state of the pinwheel;
otherwise it prints "done"
*/
void progress(int done)
{
char state[] = { '|', '/', '-', '\\' };
static int cur = -; if (cur == -)
fprintf(stderr, " "); if (done)
{
fprintf(stderr, "\b\bdone\n");
cur = -;
}
else
{
cur = (cur + ) % ;
fprintf(stdout, "\b\b%c ", state[cur]);
fflush(stderr);
}
} /*
Erases a specified number of characters from a stream. @param stream the stream from which to erase characters
@param n the number of characters to erase
*/
void erase_from_stream(FILE* stream, int n)
{
int j;
for (j = ; j < n; j++)
fprintf(stream, "\b");
for (j = ; j < n; j++)
fprintf(stream, " ");
for (j = ; j < n; j++)
fprintf(stream, "\b");
} /*
Doubles the size of an array with error checking @param array pointer to an array whose size is to be doubled
@param n number of elements allocated for \a array
@param size size in bytes of elements in \a array @return Returns the new number of elements allocated for \a array. If no
memory is available, returns 0 and frees array.
*/
int array_double(void** array, int n, int size)
{
void* tmp; tmp = realloc(*array, * n * size);
if (!tmp)
{
fprintf(stderr, "Warning: unable to allocate memory in array_double(),"
" %s line %d\n", __FILE__, __LINE__);
if (*array)
free(*array);
*array = NULL;
return ;
}
*array = tmp;
return n * ;
} /*
Calculates the squared distance between two points. @param p1 a point
@param p2 another point
*/
double dist_sq_2D(CvPoint2D64f p1, CvPoint2D64f p2)
{
double x_diff = p1.x - p2.x;
double y_diff = p1.y - p2.y; return x_diff * x_diff + y_diff * y_diff;
} /*
Draws an x on an image. @param img an image
@param pt the center point of the x
@param r the x's radius
@param w the x's line weight
@param color the color of the x
*/
void draw_x(IplImage* img, CvPoint pt, int r, int w, CvScalar color)
{
cvLine(img, pt, cvPoint(pt.x + r, pt.y + r), color, w, , );
cvLine(img, pt, cvPoint(pt.x - r, pt.y + r), color, w, , );
cvLine(img, pt, cvPoint(pt.x + r, pt.y - r), color, w, , );
cvLine(img, pt, cvPoint(pt.x - r, pt.y - r), color, w, , );
} /*
Combines two images by scacking one on top of the other @param img1 top image
@param img2 bottom image @return Returns the image resulting from stacking \a img1 on top if \a img2
*/
extern IplImage* stack_imgs(IplImage* img1, IplImage* img2)
{
IplImage* stacked = cvCreateImage(cvSize(MAX(img1->width, img2->width),
img1->height + img2->height),
IPL_DEPTH_8U, ); cvZero(stacked);
cvSetImageROI(stacked, cvRect(, , img1->width, img1->height));
cvAdd(img1, stacked, stacked, NULL);
cvSetImageROI(stacked, cvRect(, img1->height, img2->width, img2->height));
cvAdd(img2, stacked, stacked, NULL);
cvResetImageROI(stacked); return stacked;
} /*
Allows user to view an array of images as a video. Keyboard controls
are as follows: <ul>
<li>Space - start and pause playback</li>
<li>Page Down - skip forward 10 frames</li>
<li>Page Up - jump back 10 frames</li>
<li>Right Arrow - skip forward 1 frame</li>
<li>Left Arrow - jump back 1 frame</li>
<li>Backspace - jump back to beginning</li>
<li>Esc - exit playback</li>
<li>Closing the window also exits playback</li>
</ul> @param imgs an array of images
@param n number of images in \a imgs
@param win_name name of window in which images are displayed
*/
void vid_view(IplImage** imgs, int n, char* win_name)
{
int k, i = , playing = ; cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
while (!win_closed(win_name))
{
/* if already playing, advance frame and check for pause */
if (playing)
{
i = MIN(i + , n - );
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
k = cvWaitKey();
if (k == ' ' || i == n - )
playing = ;
} else
{
k = cvWaitKey();
switch (k)
{
/* space */
case ' ':
playing = ;
break; /* esc */
case :
case :
cvDestroyWindow(win_name);
break; /* backspace */
case '\b':
i = ;
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
break; /* left arrow */
case :
case :
i = MAX(i - , );
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
break; /* right arrow */
case :
case :
i = MIN(i + , n - );
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
break; /* page up */
case :
case :
i = MAX(i - , );
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
break; /* page down */
case :
case :
i = MIN(i + , n - );
cvNamedWindow(win_name, );
cvShowImage(win_name, imgs[i]);
break;
}
}
}
} /*
Checks if a HighGUI window is still open or not @param name the name of the window we're checking @return Returns 1 if the window named \a name has been closed or 0 otherwise
*/
int win_closed(char* win_name)
{
if (!cvGetWindowHandle(win_name))
return ;
return ;
}

在vs环境中跑动sift特征提取(代码部分)的更多相关文章

  1. 在vs环境中跑动sift特征提取(原理部分)

    /* 如果给两张图片,中间有相似点.要求做匹配.怎么做.我现在能讲么?   比如给了两幅图片,先求出sift点.   尺度空间极值检测.高斯模糊 关键点定位 关键点方向确定 关键点描述   kdtre ...

  2. 开发环境中biztalk项目设置注意事项(转)

      适用版本:biztalk 2006 适用环境:开发测试环境 在开发过程中,在开发环境中,一定会是一个对项目不断的修改.编译.部署.测试,查看测试结果,发现有问题,然后回到开发环境再修改.编译.部署 ...

  3. 计算机视觉-sift(2)代码理解

    之前结合不同人的资料理解了sift的原理,这里通过opencv中的代码来加深对sift的实现的理解. 使得能够从原理性理解到源码级的理解.不过该博文还是大量基于<赵春江, opencv2.4.9 ...

  4. 如何在交互式环境中执行Python程序

    相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行.命令行窗口运行.开发工具上运行等,其中在不同的操作平台上还互不相同.今天,小编讲些Pyth ...

  5. 转:【Java并发编程】之八:多线程环境中安全使用集合API(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200509     在集合API中,最初设计的Vector和Hashtable是多线程安 ...

  6. macOS 下 PHPStorm + Xdebug 调试 Docker 环境中的代码

    0x00 描述 宿主机是 mac mini,构建的项目在 docker 中,所以需要在 PHPStorm 上配置 Xdebug 进行远程代码调试. 0x01 环境 宿主机:macOS High Sie ...

  7. 多线程环境中安全使用集合API(含代码)

    转自: http://blog.csdn.net/ns_code/article/details/17200509 在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于 ...

  8. 痞子衡嵌入式:在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法. 痞子衡旧文 <在IAR下将关键函数重定向到RAM中执行的方法> ...

  9. SIFT特征提取分析

    SIFT特征提取分析 sift 关键点,关键点检测 读'D. G. Lowe. Distinctive Image Features from Scale-Invariant Keypoints[J] ...

随机推荐

  1. 总结的Ubuntu的若干小知识

    一.默认开机直接进入到Ubuntu命令行界面 安装Ubuntu后,开机会默认进入到图形界面,如果不喜欢图形界面,可以通过修改配置,直接进入命令行界面,还行节省100多兆的内存空间.具体方法如下: 修改 ...

  2. work_6

    这次的作业是阅读C++11的新特性并提出问题,作为一个大部分代码都是用C++的基本语法并没有特别关注C++一代又一代新特性的学生来说,首先我阅读了一些关于新特性的文章.为了更快的理解,我首先选择了阅读 ...

  3. MSGPACK(一)

    MSGPACK跨平台的数据序列规范,为多种语言所支持.用它序列还是还原数据都异常方便. 而且它支持序列的数据格式非常之多,因为它支持的数据格式多,所以MSGPACK的第二功用:缓存. DELPHI的M ...

  4. WebForm 回传后如何保持页面的滚动位置

    转载自 http://www.cnblogs.com/renjuwht/archive/2009/06/17/1505000.html 默认情况下,ASP.NET页面回传到服务器后,页面会跳回顶部.对 ...

  5. HDU 3265 Posters (线段树+扫描线)(面积并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3265 给你n个中间被挖空了一个矩形的中空矩形,让你求他们的面积并. 其实一个中空矩形可以分成4个小的矩 ...

  6. dll开发中遇到的问题

    刚碰到个问题,我的一个项目中引用了一个dll,这个dll又引用了另一个dll,我把这俩个都放在bin文件夹下,但是会报错,说第二个dll找不到.把它放到系统文件夹system32下就没事了. 但是遇到 ...

  7. C#中的强制类型转换与as转换的区别

    C#中的强制类型转换 例如有ClassA与ClassB两个类创建两个类的对象进行转换 1 2 ClassA a = new ClassA();  ClassB b = new ClassB(); 如果 ...

  8. setbuf和freopen

    看memcached代码的时候学习了一个api,setbuf,可以设置文件流的缓冲区.        #include <stdio.h> void setbuf(FILE *stream ...

  9. 在Java中super和this的区别

    摘要:在Java中我们会时常用到super及this的用法,现在我主要来区分一下super.和this.及superL()及this()之间的区别,来对它们的认识和了解: 1.this的用法在Java ...

  10. 一,彻底理解第一个C语言程序 Hello World

    对于初学者来说,第一个程序一般都是hello world,而且是照着书上一点一点敲的.所以,在初学者眼中,敲出来的第一个程序代码不过是一堆看不懂的英语.而事实上,C语言作为一门语言,是有语法的.所以这 ...